AgE 2.5 : Zapytania

Zapytania

Zapytania są mechanizmem komunikacji synchronicznej pomiędzy agentami. Służą do pobierania wartości właściwosci innych agentów. Kierowane są zawsze do agenta nadrzędnego. Istnieje możliwość ograniczenia obszaru agentów, do których kierowane jest zapytanie oraz możliwość filtrowania wyników zapytań.

Zapytanie może dotyczyć dwóch obszarów (por. rysunek poniżej):

  • agentów znajdujących się na tym samym poziomie hierarchii i posiadających tego samego rodzica (obszar Q11),
  • agentów znajdujących się na poziomie hierarchii rodzica i posiadających wspólnego rodzica (obszar Q1); ci agenci są potencjalnymi celami migracji agenta A111.

Bez zapytań agenci nie znaliby adresów innych agentów, a więc niemożliwa byłaby ich komunikacja ani migracja. Zadawane zapytania mogą zawierać dwa składniki:

  • ograniczenia,
  • funkcje.

Wynik zapytania składa się z par (adres agenta, zbiór własności). Dodatkowo sam wynik może zawierać własności, które definiowane są poprzez funkcje. W przypadku zadania przez agenta pustego zapytania, tzn. nie zawierającego ograniczeń i funkcji, zwrócone zostaną własności wszystkich agentów z wybranego obszaru zapytania. Ograniczenia nakładane są na pojedyncze własności agentów, które mogą znaleźć się w wyniku zapytania. W platformę zostały wbudowane trzy ograniczenia:

  • zakresu - dane agenta znajdują się w rezultacie zapytania tylko wtedy, gdy wartość danej własności znajduje się w wybranym zakresie,
  • wzorca - dane agenta znajdują się w rezultacie zapytania tylko wtedy, gdy wartość danej własności pasuje do wybranego wzorca; ograniczenie dotyczy tylko wartości tekstowych,
  • wartości - dane agenta znajdują się w rezultacie zapytania tylko wtedy, gdy wartość danej własności jest równa wybranej wartości.

Funkcje działają na wynikach zapytania i zwracają nowy wynik. Funkcje uruchamiane są kolejno na wyniku zapytania otrzymanego po zastosowaniu wszystkich ograniczeń znajdujących się w zapytaniu. Dzięki funkcjom można dowolnie przetworzyć wynik zapytania i uzyskać bardziej wyrafinowane ograniczenia (np. na wielu własnościach jednocześnie). Funkcje mogą także umieszczać własności w wyniku zapytania i dzięki temu dokonywać dowolnych obliczeń na zbiorze własności agentów, których wyniki mogą być potem odczytane przez agenta zadającego zapytanie. Końcowym wynikiem zapytania jest rezultat zwrócony przez ostatnią funkcję. Pojedyncze zapytanie może zawierać dowolną liczbę ograniczeń i funkcji.

Szczegóły implementacji można znaleźć stronie Zapytania - implementacja.

Konfiguracja pustego zapytania

Puste zapytanie zbiera wszystkie właściwości agentów znajdujących się w agregacie, do którego wysłane jest zapytanie. Aby użyć pustych zapytań należy w pliku konfiguracyjnym dopisać:

<!--  empty query definition -->
<component name="queryResult" isSingleton="false"
       class="org.jage.query.QueryableQueryResult" />

<component name="emptyQuery" isSingleton="true"
        class="org.jage.query.RecordingQuery">
	<property name="resultClass">
		<value value="queryResult" class="String" />
	</property>
</component>

W celu utworzenia takiego zapytania w kodzie agenta należy:

try {
	IQuery query = (IQuery) instanceProvider.getInstance("emptyQuery");
	assert query != null;

	answer = (QueryableQueryResult) queryEnvironment(query, new BroadcastSelector<IAgentAddress>());

} catch (AgentException e) {
	_log.error(e);
}

Konfiguracja zapytań z użyciem cache'a

Poniżej znajduje się zdefiniowane w konfiguracji query (opakowane w cache) wraz ze zdefiniowanym orgraniczeniem i funkcją, a także obiektem IQueryResult:

<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://age.iisg.agh.edu.pl/AgE/2.3" 
	xsi:schemaLocation="http://age.iisg.agh.edu.pl/AgE/2.3 http://age.iisg.agh.edu.pl/xsd/age-2.3.xsd">
	
	<component name="queryResult" isSingleton="false" class="org.jage.query.QueryableQueryResult"/>
	
	<component name="range" isSingleton="true" class="org.jage.query.QueryStepCache">
		<property name="query">
			<reference target="rangeQuery"/>
		</property>
		
		<property name="refreshAge">
			<value value="1" class="Long"/>
		</property>
	</component>
	
	<component name="rangeQuery" isSingleton="true" class="org.jage.query.RecordingQuery">
		<list name="constraintsList">
			<component name="rangeEntry" isSingleton="true" class="org.jage.query.ConstraintEntry">
				<property name="propertyName">
					<value value="height" class="String"/>
				</property>
				<property name="constraint">
					<reference target="rangeConstraint"/>
				</property>
				
				<component name="rangeConstraint" isSingleton="true" class="org.jage.query.RangeConstraint">
					<property name="lowestValue">
						<value value="3.0" class="Float"/>
					</property>
					<property name="highestValue">
						<value value="4.0" class="Float"/>
					</property>
				</component>
			</component>
			
			<reference target="rangeEntry"/>
		</list>
		
		<property name="constraints">
			<reference target="constraintsList"/>
		</property>
		
		<list name="functionsList">
			<component name="queryFunction" isSingleton="true" class="org.jage.query.PlainQueryFunction"/>
			<reference target="queryFunction"/>
		</list>
		
		<property name="functions">
			<reference target="functionsList"/>
		</property>
		
		<property name="resultClass">
			<value value="queryResult" class="String"/>
		</property>
	</component>
	
</configuration>

Attachments:

QueryConcept.png (image/png)