mirror of https://github.com/balkian/SOJA.git
Initial commit
commit
0017e5efda
@ -0,0 +1 @@
|
||||
build.properties
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
Jason Project
|
||||
|
||||
-- create on March 19, 2012
|
||||
*/
|
||||
|
||||
MAS web40sojason {
|
||||
infrastructure: Centralised
|
||||
|
||||
environment: es.upm.dit.gsi.sojason.SOEnvironment
|
||||
|
||||
agents:
|
||||
userAgent;
|
||||
travelAgent;
|
||||
commonSenseAgent;
|
||||
nluAgent;
|
||||
|
||||
aslSourcePath: "src/asl";
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
|
||||
<!--
|
||||
|
||||
This file was generated by Jason 1.3.6a
|
||||
http://jason.sf.net
|
||||
|
||||
March 20, 2012 - 16:30:55
|
||||
-->
|
||||
|
||||
<project name ="web40sojason"
|
||||
basedir=".."
|
||||
default="run">
|
||||
|
||||
<property name="mas2j.project.file" value="Web40SOJason.mas2j"/>
|
||||
<property name="debug" value=""/> <!-- use "-debug" to run in debug mode -->
|
||||
<property name="build.dir" value="${basedir}/bin/classes" />
|
||||
|
||||
<property name="jasonJar" value="/home/miguel/trabajo/Jason-1.3.6a/lib/jason.jar"/>
|
||||
|
||||
<path id="project.classpath">
|
||||
<pathelement location="${basedir}"/>
|
||||
<pathelement location="${build.dir}"/>
|
||||
<pathelement location="${jasonJar}"/>
|
||||
<fileset dir="${basedir}/lib" > <include name="*.jar" /> </fileset>
|
||||
|
||||
</path>
|
||||
|
||||
<!-- tasks the user can override in his/her c-build.xml script -->
|
||||
<target name="user-init">
|
||||
</target>
|
||||
<target name="user-end">
|
||||
</target>
|
||||
|
||||
<target name="init">
|
||||
<mkdir dir="${build.dir}" />
|
||||
<antcall target="user-init" />
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="init">
|
||||
<condition property="srcdir" value="${basedir}/src/java" else="${basedir}" >
|
||||
<available file="${basedir}/src/java" />
|
||||
</condition>
|
||||
<javac srcdir="${srcdir}" destdir="${build.dir}" debug="true" optimize="true" includeantruntime="false" >
|
||||
<classpath refid="project.classpath"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="jar" depends="compile">
|
||||
<delete file="${ant.project.name}.jar" />
|
||||
<copy file="${jasonJar}" tofile="${ant.project.name}.jar" />
|
||||
<copy file="${mas2j.project.file}" tofile="default.mas2j" />
|
||||
<jar update="yes" jarfile="${ant.project.name}.jar" >
|
||||
<fileset dir="${basedir}">
|
||||
<include name="**/*.asl" />
|
||||
<include name="**/*.mas2j" />
|
||||
</fileset>
|
||||
<fileset dir="${build.dir}">
|
||||
<include name="**/*.class" />
|
||||
</fileset>
|
||||
</jar>
|
||||
<delete file="default.mas2j" />
|
||||
</target>
|
||||
|
||||
|
||||
<target name="jnlp" depends="jar" >
|
||||
<mkdir dir="${basedir}/${ant.project.name}-jws"/>
|
||||
<java classname="jason.infra.centralised.CreateJNLP"
|
||||
failonerror="true" fork="yes" dir="${basedir}/${ant.project.name}-jws" >
|
||||
<classpath refid="project.classpath"/>
|
||||
<arg line="${ant.project.name} ${mas2j.project.file}"/>
|
||||
</java>
|
||||
<copy todir="${basedir}/${ant.project.name}-jws" failonerror="no">
|
||||
<fileset dir="${basedir}/lib" includes="**/*.jar" />
|
||||
<fileset dir="${basedir}" includes="${ant.project.name}.jar" />
|
||||
<fileset dir="/home/miguel/trabajo/Jason-1.3.6a/src/images" includes="Jason-GMoreau-Icon.jpg" />
|
||||
</copy>
|
||||
<signjar jar="${basedir}/${ant.project.name}-jws/${ant.project.name}.jar" alias="jason"
|
||||
storepass="rbjhja" keypass="rbjhja" keystore="/home/miguel/trabajo/Jason-1.3.6a/src/jasonKeystore" />
|
||||
<echo message="**" />
|
||||
<echo message="** Java Web Start application created in directory ${ant.project.name}-jws" />
|
||||
<echo message="** Update the codebase (in the second line of the .jnlp file)" />
|
||||
<echo message="** with the URL where you will upload the application." />
|
||||
<echo message="**" />
|
||||
</target>
|
||||
|
||||
|
||||
<target name="run" depends="compile" >
|
||||
<echo message="Running project ${ant.project.name}" />
|
||||
<java classname="jason.infra.centralised.RunCentralisedMAS"
|
||||
failonerror="true" fork="yes" dir="${basedir}" >
|
||||
<classpath refid="project.classpath"/>
|
||||
<arg line="${mas2j.project.file} ${debug} "/>
|
||||
<!-- jvmarg line="-Xmx500M -Xss8M"/ -->
|
||||
</java>
|
||||
<antcall target="user-end" />
|
||||
</target>
|
||||
|
||||
<target name="clean" >
|
||||
<delete failonerror="no" includeEmptyDirs="true" verbose="true">
|
||||
<fileset dir="${basedir}" includes="**/*.class"/>
|
||||
</delete>
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
</project>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
|
||||
<properties>
|
||||
<comment>Renfe city codes</comment>
|
||||
<entry key="ciudad real">37200</entry>
|
||||
<entry key="bilbao">13200 </entry>
|
||||
<entry key="almeria">56312</entry>
|
||||
<entry key="lisboa">LISBO</entry>
|
||||
<entry key="león">15100</entry>
|
||||
<entry key="bardonecchia">83005</entry>
|
||||
<entry key="puerto santa maría">51400</entry>
|
||||
<entry key="a coruña">31412 </entry>
|
||||
<entry key="monforte de lemos">20300</entry>
|
||||
<entry key="pontevedra">23004</entry>
|
||||
<entry key="albacete">60911 </entry>
|
||||
<entry key="berna">85031</entry>
|
||||
<entry key="valdepeñas">50102</entry>
|
||||
<entry key="benicassim">65318</entry>
|
||||
<entry key="málaga">54413</entry>
|
||||
<entry key="linares-baeza">50300</entry>
|
||||
<entry key="tarragona">82100</entry>
|
||||
<entry key="teruel">67200</entry>
|
||||
<entry key="cartagena">61307</entry>
|
||||
<entry key="cádiz">51405</entry>
|
||||
<entry key="jaen">03100</entry>
|
||||
<entry key="cuenca">CUENC</entry>
|
||||
<entry key="turín">83002</entry>
|
||||
<entry key="córdoba">50500</entry>
|
||||
<entry key="entroncamento">94428</entry>
|
||||
<entry key="burgos rosa de lima">11014 </entry>
|
||||
<entry key="alacant">60911</entry>
|
||||
<entry key="marvao-beira">94401</entry>
|
||||
<entry key="malaga">54413</entry>
|
||||
<entry key="sahagún">15009</entry>
|
||||
<entry key="gasteiz">11208</entry>
|
||||
<entry key="ginebra">85444</entry>
|
||||
<entry key="cordoba">50500</entry>
|
||||
<entry key="irún">11600</entry>
|
||||
<entry key="ferrol">21010</entry>
|
||||
<entry key="santander">14223</entry>
|
||||
<entry key="toledo">92102</entry>
|
||||
<entry key="caceres">35400</entry>
|
||||
<entry key="cáceres">35400</entry>
|
||||
<entry key="lugo">20309</entry>
|
||||
<entry key="friburgo">85410</entry>
|
||||
<entry key="la coruña">31412</entry>
|
||||
<entry key="utiel">03213</entry>
|
||||
<entry key="zaragoza">ZARAG</entry>
|
||||
<entry key="burgos">11014 </entry>
|
||||
<entry key="figueres">04307</entry>
|
||||
<entry key="salamanca">SALAM</entry>
|
||||
<entry key="elda-petrer">60905</entry>
|
||||
<entry key="alicante">60911</entry>
|
||||
<entry key="oviedo">15211</entry>
|
||||
<entry key="mérida">37500</entry>
|
||||
<entry key="lorca">06006</entry>
|
||||
<entry key="bern">85031</entry>
|
||||
<entry key="puente genil">PTE G</entry>
|
||||
<entry key="milano">83111</entry>
|
||||
<entry key="beira">94401</entry>
|
||||
<entry key="abrantes">94707</entry>
|
||||
<entry key="barcelona">BARCE </entry>
|
||||
<entry key="almería">56312</entry>
|
||||
<entry key="valencia">VALEN</entry>
|
||||
<entry key="castello">65300</entry>
|
||||
<entry key="figueres vilafant">04307</entry>
|
||||
<entry key="gandia">69110</entry>
|
||||
<entry key="requena">03213</entry>
|
||||
<entry key="badajoz">37606 </entry>
|
||||
<entry key="cadiz">51405</entry>
|
||||
<entry key="castellon">65300</entry>
|
||||
<entry key="zurich">85200</entry>
|
||||
<entry key="jaén">03100</entry>
|
||||
<entry key="orleans-les aubrais">87004</entry>
|
||||
<entry key="valladolid">10600</entry>
|
||||
<entry key="blois">87546 </entry>
|
||||
<entry key="lleida">78400</entry>
|
||||
<entry key="gijon">GIJON</entry>
|
||||
<entry key="algeciras">55020 </entry>
|
||||
<entry key="vigo">Guixar=22308</entry>
|
||||
<entry key="logroño">81100</entry>
|
||||
<entry key="monzon-rio cinca">78301</entry>
|
||||
<entry key="merida">37500</entry>
|
||||
<entry key="paris austerlitz">87011</entry>
|
||||
<entry key="reus">71400</entry>
|
||||
<entry key="fribourg">85410</entry>
|
||||
<entry key="san sebastián">11511</entry>
|
||||
<entry key="tudela de navarra">81202</entry>
|
||||
<entry key="milán">83111</entry>
|
||||
<entry key="palencia">14100</entry>
|
||||
<entry key="málaga maría zambrano">54413</entry>
|
||||
<entry key="coruña">31412</entry>
|
||||
<entry key="bilbao-abando">13200 </entry>
|
||||
<entry key="lorca-sutullena">06006</entry>
|
||||
<entry key="paris">87011</entry>
|
||||
<entry key="madrid">MADRI</entry>
|
||||
<entry key="monzón-río cinca">78301</entry>
|
||||
<entry key="guadalajara">GUADA</entry>
|
||||
<entry key="xàtiva">64100</entry>
|
||||
<entry key="murcia">61200</entry>
|
||||
<entry key="navalmoral de la mata">35206</entry>
|
||||
<entry key="torino">83002</entry>
|
||||
<entry key="segovia">SEGOV</entry>
|
||||
<entry key="geneve">85444</entry>
|
||||
<entry key="parís austerlitz">87011</entry>
|
||||
<entry key="gandía">69110</entry>
|
||||
<entry key="bobadilla">54400 </entry>
|
||||
<entry key="orleans">87004</entry>
|
||||
<entry key="leon">15100</entry>
|
||||
<entry key="castellón">65300</entry>
|
||||
<entry key="puerto santa maria">51400</entry>
|
||||
<entry key="alcázar de san juan">60400 </entry>
|
||||
<entry key="zamora">30200</entry>
|
||||
<entry key="santiago de compostela">31400</entry>
|
||||
<entry key="antequera">ANTEQ</entry>
|
||||
<entry key="montpellier">87173</entry>
|
||||
<entry key="donostia">11511</entry>
|
||||
<entry key="pamplona">80100</entry>
|
||||
<entry key="villena">60902</entry>
|
||||
<entry key="orpesa">65304</entry>
|
||||
<entry key="novara">83008</entry>
|
||||
<entry key="avila">10400 </entry>
|
||||
<entry key="iruña">80100</entry>
|
||||
<entry key="granada">05000</entry>
|
||||
<entry key="gijón">GIJON</entry>
|
||||
<entry key="ourense">22100</entry>
|
||||
<entry key="turin">83002</entry>
|
||||
<entry key="soria">82100</entry>
|
||||
<entry key="puertollano">37300</entry>
|
||||
<entry key="oropesa">65304</entry>
|
||||
<entry key="huesca">74200</entry>
|
||||
<entry key="san sebastian">11511</entry>
|
||||
<entry key="hendaya">11602</entry>
|
||||
<entry key="milan">83111</entry>
|
||||
<entry key="ponferrada">20200</entry>
|
||||
<entry key="huelva">43019</entry>
|
||||
<entry key="portbou">79315</entry>
|
||||
<entry key="alcazar de san juan">60400 </entry>
|
||||
<entry key="parís">87011</entry>
|
||||
<entry key="malaga maria zambrano">54413</entry>
|
||||
<entry key="vitoria">11208</entry>
|
||||
<entry key="sahagun">15009</entry>
|
||||
<entry key="miranda de ebro">11200</entry>
|
||||
<entry key="irun">11600</entry>
|
||||
<entry key="medina del campo">10500</entry>
|
||||
<entry key="calatayud">70600</entry>
|
||||
<entry key="girona">79300</entry>
|
||||
<entry key="sevilla">51003</entry>
|
||||
<entry key="jerez de la frontera">51300</entry>
|
||||
<entry key="limoges">87034</entry>
|
||||
<entry key="castelló">65300</entry>
|
||||
</properties>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
// Agent userAgent in project Web40
|
||||
|
||||
/* Initial beliefs and rules */
|
||||
|
||||
/* Initial goals */
|
||||
|
||||
|
||||
/* Plans */
|
@ -0,0 +1,40 @@
|
||||
// Agent nluAgent in project Web40SOJason
|
||||
|
||||
/* Initial beliefs and rules */
|
||||
|
||||
/* Initial goals */
|
||||
|
||||
/* Plans */
|
||||
|
||||
@in_msg
|
||||
+user_msg(Msg, Query) : true
|
||||
<- sendNLU(Query, Msg);
|
||||
-user_msg(Msg, Query). // clear the memory
|
||||
|
||||
|
||||
/* Tell the user agent what the NLU system understood */
|
||||
+price(Terms, Price)[query(Query), domain(travel)] : true
|
||||
<- .send(userAgent, tell, price(Terms, Price)[query(Query)], domain(travel));
|
||||
.print("Percibido: price ",Terms, " ", Price ).
|
||||
|
||||
+date(Terms, Day, Month, Year)[query(Query), domain(travel)] : true
|
||||
<- .send(userAgent, tell, date(Terms, Day, Month, Year)[query(Query), domain(travel)]);
|
||||
.print("Percibido: date ",Terms, " ", Day, " ", Month, " ", Year).
|
||||
|
||||
+time(Terms, Hours, Minutes)[query(Query), domain(travel)] : true
|
||||
<- .send(userAgent, tell, time(Terms, Hours, Minutes)[query(Query), domain(travel)]);
|
||||
.print("Percibido: time ",Terms, " ", Hours, " ", Minutes).
|
||||
|
||||
+location(Terms, Place)[query(Query), domain(travel)] : true
|
||||
<- .send(userAgent, tell, location(Terms, Place)[query(Query), domain(travel)]);
|
||||
.print("Percibido: location ",Terms, " ", Place).
|
||||
|
||||
+type(Terms)[query(Query), domain(travel)] : true
|
||||
<- .send(userAgent, tell, type(Terms)[query(Query), domain(travel)]);
|
||||
.print("Percibido: type ",Terms).
|
||||
|
||||
@sendFindTravel
|
||||
+done[query(Query), domain(Domain)] : true
|
||||
<- .wait(1000); // wait until all other information is sent
|
||||
.print("Percepcion completada");
|
||||
.send(userAgent, achieve, find(Domain, Query)).
|
@ -0,0 +1,60 @@
|
||||
// Agent travelAgent in project Web40
|
||||
|
||||
/* Initial beliefs and rules */
|
||||
canFindTravel(Query)
|
||||
:- location(from,_)[query(Query)] &
|
||||
location(to,_)[query(Query)] &
|
||||
date(departure,_,_,_)[query(Query)].
|
||||
|
||||
/* Initial goals */
|
||||
contact(userAgent).
|
||||
my_service(travel).
|
||||
my_service(train).
|
||||
|
||||
/************** Plans *****************/
|
||||
|
||||
/* Introduce myself to the user agent */
|
||||
@introduce_myself
|
||||
+my_service(Domain)
|
||||
: contact(Agent) & .my_name(Me)
|
||||
<- .send(Agent, tell, service(Me, Domain)).
|
||||
|
||||
@introduction_rety
|
||||
+my_service(Domain) : not contact(Agent)
|
||||
<- -+my_service(Domain).
|
||||
|
||||
|
||||
/* Find travel plans */
|
||||
@findTravel1
|
||||
+!find(travel, Query) : not canFindTravel(Query) & not delay(Query)
|
||||
<- .print("Not enought data. Lets wait some time");
|
||||
.wait(3000);
|
||||
+delay(Query);
|
||||
!find(travel, Query).
|
||||
|
||||
@findTravel2
|
||||
+!find(travel, Query) : not canFindTravel(Query) & delay(Query)
|
||||
<- -delay(Query);
|
||||
.print("Not enought data. Lets ask!").
|
||||
|
||||
@findTravel3
|
||||
+!find(travel, Query) : canFindTravel(Query)
|
||||
<- ?location(to, To);
|
||||
?location(from, From);
|
||||
?date(departure, Day, Month, Year);
|
||||
findTravel(From, To, Day, Month, Year);
|
||||
.print("ok").
|
||||
|
||||
@findTravelFailureRety
|
||||
-!find(travel, Query) : not error(Msg, Query)<- !findTravel(Query).
|
||||
|
||||
@findTravelFailureError
|
||||
-!find(travel, Query) : error(Msg, Query)
|
||||
<- .print("Problema al encontrar viajes:", Msg);
|
||||
!findTravel(Query).
|
||||
|
||||
|
||||
/* log results */
|
||||
@log_the_journey
|
||||
+journey(From, To, Departure, Arrival, Fares) : true
|
||||
<- .print("Travel found: From ", From,"<", Departure, "> to ", To, "<", Arrival, "> for ", Fares).
|
@ -0,0 +1,56 @@
|
||||
// Agent userAgent in project Web40
|
||||
|
||||
/* Initial beliefs and rules */
|
||||
new_query(Query) :- .random(R) & Query = (1000*R)+1.
|
||||
|
||||
!start.
|
||||
|
||||
/* Initial goals */
|
||||
|
||||
/******* Plans ***************************/
|
||||
|
||||
/* Wait for service introduction (temporal plan, to erase) */
|
||||
+!start : true
|
||||
<- .wait(1000);
|
||||
+user_msg("I want to travel from Madrid to Cuenca in the morning that costs no more than 200€ and dinner in a romantic restaurant").
|
||||
|
||||
|
||||
/* Ask the nlu agent */
|
||||
+user_msg(Msg) : new_query(Query)
|
||||
<- .send(nluAgent, tell, user_msg(Msg, Query) ).
|
||||
|
||||
/* Log the received data */
|
||||
+price(Terms, Price)[query(Query), domain(Domain)] : true
|
||||
<- .print("Percibido: price ",Terms, " ", Price );
|
||||
+data(price(Terms), Query, Domain).
|
||||
|
||||
+date(Terms, Day, Month, Year)[query(Query), domain(Domain)] : true
|
||||
<- .print("Percibido: date ",Terms, " ", Day, " ", Month, " ", Year);
|
||||
+data(date(Terms, Day, Month, Year), Query, Domain).
|
||||
|
||||
+time(Terms, Hours, Minutes)[query(Query), domain(Domain)] : true
|
||||
<- .print("Percibido: time ",Terms, " ", Hours, " ", Minutes);
|
||||
+data(time(Terms, Hours, Minutes), Query, Domain).
|
||||
|
||||
+location(Terms, Place)[query(Query), domain(Domain)] : true
|
||||
<- .print("Percibido: location ",Terms, " ", Place);
|
||||
+data(location(Terms, Place), Query, Domain).
|
||||
|
||||
+type(Terms)[query(Query), domain(Domain)] : true
|
||||
<- .print("Percibido: type ",Terms).
|
||||
|
||||
/* find travel */
|
||||
/*@find_travel
|
||||
+!find(travel, Query) : true
|
||||
<- .println("lets find travel ", Query);
|
||||
.findall(Name, service(Name, travel), List);
|
||||
.send(List, achieve, find(travel, Query)).
|
||||
*/
|
||||
|
||||
@do_search
|
||||
+!find(Domain, Query) : true
|
||||
<- .print("Perform find ", Domain, " ", Query);
|
||||
.findall(Name, service(Name, Domain), AgList);
|
||||
.findall(Atom[query(Query)], data(Atom, Query, Domain), DataList);
|
||||
.send(AgList, tell, DataList);
|
||||
.send(AgList, achieve, find(Domain, Query)).
|
@ -0,0 +1,87 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package es.upm.dit.gsi.jason.utils;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
*
|
||||
* Project: Web40SOJason
|
||||
* Package: es.upm.dit.gsi.jason.utils
|
||||
* Class: CollectionUtils
|
||||
*
|
||||
* @author Miguel Coronado (miguelcb@dit.upm.es)
|
||||
* @version Mar 9, 2012
|
||||
*
|
||||
*/
|
||||
public abstract class CollectionUtils {
|
||||
|
||||
/**
|
||||
* This wraps a Literal in a collection
|
||||
* @param literal The literal
|
||||
* @return Collection containing the literal given
|
||||
*/
|
||||
public static Collection<Literal> wrapList(Literal literal) {
|
||||
Collection<Literal> res = new LinkedList<Literal>();
|
||||
res.add(literal);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* This wraps a Literal in a collection
|
||||
* @param literal The string that represents a literal
|
||||
* @return Collection containing the literal given
|
||||
*/
|
||||
public static Collection<Literal> wrapList(String literal) {
|
||||
Collection<Literal> res = new LinkedList<Literal>();
|
||||
res.add(Literal.parseLiteral(literal));
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* This
|
||||
* @param collection
|
||||
* @return
|
||||
*/
|
||||
public static String[] toStringArray (Collection<? extends Object> collection){
|
||||
String[] strArray = new String[collection.size()];
|
||||
|
||||
int index = 0;
|
||||
for(Object obj : collection){
|
||||
if(obj == null) {
|
||||
strArray[index] = "null";
|
||||
}
|
||||
else {
|
||||
strArray[index] = obj.toString();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return strArray;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param items
|
||||
* @return
|
||||
*/
|
||||
public static String[] toStringArray (Object[] items){
|
||||
String[] strArray = new String[items.length];
|
||||
|
||||
for(int index = 0; index < items.length; index++){
|
||||
Object obj = items[index];
|
||||
if(obj == null){
|
||||
strArray[index] = "null";
|
||||
}
|
||||
else{
|
||||
strArray[index] = items[index].toString();
|
||||
}
|
||||
}
|
||||
|
||||
return strArray;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package es.upm.dit.gsi.jason.utils;
|
||||
|
||||
|
||||
/**
|
||||
* This Utils class is used to validate string according to the Jason atom
|
||||
* notation criteria, and transform an invalid notation into a valid one
|
||||
* and vice versa.
|
||||
*
|
||||
* This is useful in some context where the agents need to interact with an
|
||||
* uncontrollable environment such as the Web.
|
||||
*
|
||||
* In Jason notation, white-spaces are not allowed, neither, words that starts
|
||||
* with capital letter.
|
||||
*
|
||||
* @author gsi.dit.upm.es
|
||||
*
|
||||
*/
|
||||
public class NotationUtils {
|
||||
|
||||
/**
|
||||
* @param toCheck
|
||||
* @return
|
||||
*/
|
||||
public static boolean isValidAtom (String toCheck) {
|
||||
String lowerCase = toCheck.toLowerCase();
|
||||
return !toCheck.contains(" ") && !toCheck.contains(",") && toCheck.equals(lowerCase);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param toCheck
|
||||
* @return
|
||||
*/
|
||||
public static boolean isCompactable (String toCheck) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String compact(String str) {
|
||||
|
||||
if (isValidAtom (str)) {return str;}
|
||||
if (!isCompactable(str)) {return null;}
|
||||
|
||||
str = str.replace("_", "___");
|
||||
str = str.replace(" ", "_");
|
||||
str = str.replace("ñ", "n");
|
||||
return str.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String uncompact(String str) {
|
||||
str = str.replace("___", "#");
|
||||
str = str.replace("_", " ");
|
||||
str = str.replace("#", " ");
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This removes the quotation mark from the string given. If that
|
||||
* string has no quotation marks it returned trimmed.</p>
|
||||
*
|
||||
* <p>The quotation marks are only removed from the beginning and the
|
||||
* end of the string, so any quotation mark inserted in the middle of
|
||||
* the string will be kept.</p>
|
||||
*
|
||||
* @return the string without the quotation marks
|
||||
*/
|
||||
public static String removeQuotation (String str) {
|
||||
String message = str.trim();
|
||||
if(message.startsWith("\"")) message = message.substring(1);
|
||||
if(message.endsWith("\"")) message = message.substring(0, message.length()-1);
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package es.upm.dit.gsi.sojason;
|
||||
// Environment code for project Web40SOJason
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
import jason.asSyntax.Structure;
|
||||
import jason.asSyntax.Term;
|
||||
import jason.environment.Environment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This represents a Software Oriented Environment.
|
||||
* It overrides the getPercepts method so every time the agent perceives
|
||||
* it checks the model to update the percepts for the particular agent.
|
||||
*
|
||||
* Project: Web40SOJason
|
||||
* Package: es.upm.dit.gsi.sojason
|
||||
* Class: SOEnvironment
|
||||
*
|
||||
* @author Miguel Coronado (miguelcb@dit.upm.es)
|
||||
* @version Mar 9, 2012
|
||||
*
|
||||
*/
|
||||
public class SOEnvironment extends Environment {
|
||||
|
||||
/** The logger */
|
||||
private Logger logger = Logger.getLogger("Web40SOJason." + SOEnvironment.class.getName());
|
||||
|
||||
/** The model */
|
||||
public Web40Model model;
|
||||
|
||||
/** Called before the MAS execution with the args informed in .mas2j */
|
||||
@Override
|
||||
public void init(String[] args) {
|
||||
super.init(args);
|
||||
try {
|
||||
this.model = new Web40Model();
|
||||
} catch (IOException e) {
|
||||
addPercept(Literal.parseLiteral("error(\"Could not inatantiate the model\")"));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeAction(String agName, Structure action) {
|
||||
logger.info("executing: " + action + " (" + agName + ")");
|
||||
|
||||
// select the external action
|
||||
boolean result = false;
|
||||
String functor = action.getFunctor();
|
||||
List<Term> terms = action.getTerms();
|
||||
|
||||
if (functor.equals("sendNLU")) {
|
||||
result = this.model.sendNlu(agName, terms);
|
||||
}
|
||||
else if (functor.equals("findTravel")) {
|
||||
result = this.model.findTravel(agName, terms);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
logger.info(action + " was not implemented.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Called before the end of MAS execution */
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
}
|
||||
|
||||
/** */
|
||||
@Override
|
||||
public List<Literal> getPercepts(String agName) {
|
||||
updatePerceptsForAg(agName);
|
||||
return super.getPercepts(agName);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param agName
|
||||
*/
|
||||
public void updatePerceptsForAg (String agName) {
|
||||
clearPercepts(agName);
|
||||
Collection<Literal> literals = model.getDataFromInbox(agName);
|
||||
for(Literal literal : literals){
|
||||
addPercept(agName, literal);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package es.upm.dit.gsi.sojason;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Project: Web40SOJason
|
||||
* Package: es.upm.dit.gsi.sojason
|
||||
* Class: SOModel
|
||||
*
|
||||
* @author Miguel Coronado (miguelcb@dit.upm.es)
|
||||
* @version Mar 9, 2012
|
||||
*
|
||||
*/
|
||||
abstract public class SOModel {
|
||||
|
||||
/**
|
||||
* This contains the data that will be
|
||||
*/
|
||||
private Map<String, Set<Literal>> serviceDataInbox;
|
||||
|
||||
/**
|
||||
* Constructor. Just initializes attributes.
|
||||
*/
|
||||
public SOModel(){
|
||||
this.serviceDataInbox = Collections.synchronizedMap(new HashMap<String, Set<Literal>>());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This puts data into the <code>serviceDataInbox</code> for a
|
||||
* particular agent. The data loaded will be appended into the already
|
||||
* existing data if any.</p>
|
||||
*
|
||||
* <p>The data from the <code>serviceDataInbox</code> is removed as
|
||||
* described in the documentation of {@link #getDataFromInbox(String)}</p>
|
||||
*
|
||||
* @param agName The name of the agent.
|
||||
* @param serviceData The service-data.
|
||||
*/
|
||||
public void setDataInbox (String agName, Collection<Literal> serviceData){
|
||||
|
||||
synchronized (serviceDataInbox) {
|
||||
if (!this.serviceDataInbox.containsKey(agName)) {
|
||||
Set<Literal> set = new HashSet<Literal>();
|
||||
set.addAll(serviceData); // create a set and add all the collection
|
||||
this.serviceDataInbox.put(agName, set);
|
||||
return;
|
||||
}
|
||||
|
||||
// There is no data in the inbox for the agent given
|
||||
Set<Literal> set = this.serviceDataInbox.get(agName);
|
||||
set.addAll(serviceData);
|
||||
this.serviceDataInbox.put(agName, set);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This provides a different way to call the method
|
||||
* {@linkplain #setDataInbox(String, Collection)} with a single literal
|
||||
* instead of a collection of literals.</p>
|
||||
*
|
||||
* @param agName the name of the agent.
|
||||
* @param literal the literal.
|
||||
*/
|
||||
public void setDataInbox (String agName, Literal literal) {
|
||||
Set <Literal> set = new HashSet<Literal>();
|
||||
set.add(literal);
|
||||
setDataInbox(agName, set);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This gets from the <code>serviceDataInbox</code> the data stored for
|
||||
* the agent given. It will remove the data from the inbox, so two consequent
|
||||
* invocations of this method will return different results, actually, if no
|
||||
* new data is put, the second invocation will return no data.</p>
|
||||
*
|
||||
* <p>So, it is important to point out this method empties the
|
||||
* <code>serviceDataInbox</code>.</p>
|
||||
*
|
||||
* <p>This method never returns null to avoid null pointer</p>
|
||||
*
|
||||
* @param agName the name of the agent who data will be retrieved from
|
||||
* the inbox
|
||||
* @return The data retrieved
|
||||
*/
|
||||
public Collection<Literal> getDataFromInbox (String agName) {
|
||||
if (!this.serviceDataInbox.containsKey(agName)){
|
||||
return new HashSet<Literal>();
|
||||
}
|
||||
// return this.serviceDataInbox.get(agName);
|
||||
return this.serviceDataInbox.remove(agName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package es.upm.dit.gsi.sojason;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
import jason.asSyntax.Term;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import es.upm.dit.gsi.jason.utils.CollectionUtils;
|
||||
import es.upm.dit.gsi.sojason.services.nlu.NLUConnector;
|
||||
import es.upm.dit.gsi.sojason.services.travel.RenfeScrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Project: Web40
|
||||
* Package: es.upm.dit.gsi.qa
|
||||
* Class: Web40Model
|
||||
*
|
||||
* @author Miguel Coronado (miguelcb@dit.upm.es)
|
||||
* @version Feb 29, 2012
|
||||
*
|
||||
*/
|
||||
public class Web40Model extends SOModel{
|
||||
|
||||
/** */
|
||||
public final static String NLU_SERVICE_URL = "http://46.4.52.82:3333/nlu";
|
||||
/** */
|
||||
private NLUConnector nluConnector;
|
||||
/** */
|
||||
private RenfeScrapper renfeScrapper;
|
||||
/** */
|
||||
private Logger logger = Logger.getLogger("Web40SOJason." + Web40Model.class.getName());
|
||||
|
||||
/** Constructor
|
||||
* @throws IOException */
|
||||
public Web40Model () throws IOException {
|
||||
super();
|
||||
this.nluConnector = new NLUConnector(NLU_SERVICE_URL);
|
||||
this.renfeScrapper = new RenfeScrapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* This calls the NLU service
|
||||
*
|
||||
* Internally this modifies the model so it reports the agent
|
||||
*
|
||||
* @param agName the name of the agent that will be reported with the
|
||||
* results of the call.
|
||||
* @param terms The parameters
|
||||
* @return
|
||||
*/
|
||||
public boolean sendNlu (String agName, Collection<Term> params) {
|
||||
|
||||
logger.info("Entering sendNLU...");
|
||||
try{
|
||||
String[] strParams = CollectionUtils.toStringArray(params);
|
||||
Collection<Literal> serviceData = nluConnector.call(strParams);
|
||||
if(serviceData == null){
|
||||
logger.info("Could not complete action sendNLU: no service data found");
|
||||
return false;
|
||||
}
|
||||
|
||||
// put data into mailbox
|
||||
this.setDataInbox(agName, serviceData);
|
||||
}
|
||||
catch (Exception e){
|
||||
logger.info("Could not complete action sendNLU:" + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.info("NLU call completed successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param agName
|
||||
* @param terms
|
||||
* @return
|
||||
*/
|
||||
public boolean findTravel (String agName, Collection<Term> params) {
|
||||
|
||||
try{
|
||||
String[] strParams = CollectionUtils.toStringArray(params);
|
||||
Collection<Literal> serviceData = renfeScrapper.call(strParams);
|
||||
if(serviceData == null){ return false; }
|
||||
|
||||
// put data into mailbox
|
||||
this.setDataInbox(agName, serviceData);
|
||||
}
|
||||
catch (Exception e){ return false; }
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package es.upm.dit.gsi.sojason.beans;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import es.upm.dit.gsi.jason.utils.NotationUtils;
|
||||
|
||||
/**
|
||||
* @author miguel
|
||||
*
|
||||
*/
|
||||
public class ErrorReport extends HashMap<String, String> implements Perceptable {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see es.upm.dit.gsi.qa.beans.Perceptable#toPercepts()
|
||||
*/
|
||||
public List<Literal> toPercepts() {
|
||||
|
||||
List<Literal> res = new LinkedList<Literal>();
|
||||
for (String key : this.keySet()){
|
||||
if(!NotationUtils.isCompactable(key)) continue;
|
||||
res.add(Literal.parseLiteral("error(" + NotationUtils.compact(key) + ", \"" + get(key) + "\")"));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,217 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package es.upm.dit.gsi.sojason.beans;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import es.upm.dit.gsi.jason.utils.NotationUtils;
|
||||
|
||||
/**
|
||||
* @author miguel
|
||||
*
|
||||
*/
|
||||
public class Journey implements Perceptable{
|
||||
|
||||
/** The departure time of the journey */
|
||||
private String departureTime;
|
||||
|
||||
/** The arrival time of the journey */
|
||||
private String arrivalTime;
|
||||
|
||||
/**
|
||||
* The duration of the journey. This is not simply the difference of the
|
||||
* departure and arrival time because of timezone considerations.
|
||||
*/
|
||||
private String duration;
|
||||
|
||||
/** The origin */
|
||||
private String origin;
|
||||
|
||||
/** The destination */
|
||||
private String destination;
|
||||
|
||||
/** The fee map that contains the different available fee */
|
||||
private Map<String, String> fares;
|
||||
|
||||
/**
|
||||
* @return the departureTime
|
||||
*/
|
||||
public String getDepartureTime() {
|
||||
return departureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param departureTime the departureTime to set
|
||||
*/
|
||||
public void setDepartureTime(String departureTime) {
|
||||
this.departureTime = departureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the arrivalTime
|
||||
*/
|
||||
public String getArrivalTime() {
|
||||
return arrivalTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param arrivalTime the arrivalTime to set
|
||||
*/
|
||||
public void setArrivalTime(String arrivalTime) {
|
||||
this.arrivalTime = arrivalTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the duration
|
||||
*/
|
||||
public String getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param duration the duration to set
|
||||
*/
|
||||
public void setDuration(String duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the oringin
|
||||
*/
|
||||
public String getOringin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param oringin the oringin to set
|
||||
*/
|
||||
public void setOrigin(String origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the destination
|
||||
*/
|
||||
public String getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param destination the destination to set
|
||||
*/
|
||||
public void setDestination(String destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fares
|
||||
*/
|
||||
public Map<String, String> getFares() {
|
||||
return fares;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fares the fares to set
|
||||
*/
|
||||
public void setFares(Map<String, String> fares) {
|
||||
this.fares = fares;
|
||||
}
|
||||
|
||||
/** Textual representation of the journey. Use for debuging purposes inly.*/
|
||||
public String toString() {
|
||||
|
||||
String toString = "From: ";
|
||||
toString = toString.concat(origin);
|
||||
toString = toString.concat(" (");
|
||||
toString = toString.concat(departureTime);
|
||||
toString = toString.concat(") to: ");
|
||||
toString = toString.concat(destination);
|
||||
toString = toString.concat(" (");
|
||||
toString = toString.concat(arrivalTime);
|
||||
toString = toString.concat(") in ");
|
||||
toString = toString.concat(duration);
|
||||
toString = toString.concat(" for ");
|
||||
if(fares != null)
|
||||
toString = toString.concat(fares.toString());
|
||||
else
|
||||
toString += null;
|
||||
return toString;
|
||||
}
|
||||
|
||||
/**
|
||||
* journey(madrid, ciudad_real, 10.15, 11.5, [fare(turista, 22.5), fare(preferente, 35)]
|
||||
* journey(madrid, ciudad_real, time(10,15), time(11,5), [fare(turista, 22.5), fare(preferente, 35)]
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Literal> toPercepts() {
|
||||
|
||||
// if (this.fares.size() == 0){ return null; }
|
||||
//
|
||||
// String percept = "journey(";
|
||||
// percept = percept.concat(this.origin);
|
||||
// percept = percept.concat(", ");
|
||||
// percept = percept.concat(this.destination);
|
||||
// percept = percept.concat(", ");
|
||||
// percept = percept.concat(this.departureTime);
|
||||
// percept = percept.concat(", ");
|
||||
// percept = percept.concat(this.arrivalTime);
|
||||
//
|
||||
// percept = percept.concat(", [");
|
||||
// for(String fareName : fares.keySet()) {
|
||||
// percept = percept.concat("fare(");
|
||||
// percept = percept.concat(fareName);
|
||||
// percept = percept.concat(", ");
|
||||
// percept = percept.concat(fares.get(fareName));
|
||||
// percept = percept.concat("), ");
|
||||
// }
|
||||
// percept = percept.substring(0, percept.lastIndexOf(","));
|
||||
// percept = percept.concat("])");
|
||||
//
|
||||
// LinkedList<Literal> ret = new LinkedList<Literal>();
|
||||
// ret.add(Literal.parseLiteral(percept));
|
||||
//
|
||||
// return ret;
|
||||
|
||||
if (this.fares.size() == 0){ return null; }
|
||||
|
||||
String percept = "journey(";
|
||||
percept = percept.concat(NotationUtils.compact(this.origin));
|
||||
percept = percept.concat(", ");
|
||||
percept = percept.concat(NotationUtils.compact(this.destination));
|
||||
|
||||
percept = percept.concat(", time(");
|
||||
String digits[] = this.departureTime.split("[\\x2E\\x3A]"); // [.:]
|
||||
percept = percept.concat(digits[0]);
|
||||
percept = percept.concat(", ");
|
||||
percept = percept.concat(digits[1]);
|
||||
|
||||
percept = percept.concat("), time(");
|
||||
digits = this.arrivalTime.split("[\\x2E\\x3A]"); // [.:]
|
||||
percept = percept.concat(digits[0]);
|
||||
percept = percept.concat(", ");
|
||||
percept = percept.concat(digits[1]);
|
||||
|
||||
percept = percept.concat("), [");
|
||||
for(String fareName : fares.keySet()) {
|
||||
percept = percept.concat("fare(");
|
||||
percept = percept.concat(NotationUtils.compact(fareName));
|
||||
percept = percept.concat(", ");
|
||||
percept = percept.concat(fares.get(fareName));
|
||||
percept = percept.concat("), ");
|
||||
}
|
||||
percept = percept.substring(0, percept.lastIndexOf(","));
|
||||
percept = percept.concat("])");
|
||||
|
||||
LinkedList<Literal> ret = new LinkedList<Literal>();
|
||||
ret.add(Literal.parseLiteral(percept));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,347 @@
|
||||
package es.upm.dit.gsi.sojason.beans;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import es.upm.dit.gsi.jason.utils.NotationUtils;
|
||||
import es.upm.dit.gsi.sojason.services.nlu.NLUModel;
|
||||
|
||||
public class NLUTravel implements Perceptable {
|
||||
|
||||
/** */
|
||||
public final static String TRAVEL_DOMAIN = "travel";
|
||||
|
||||
/** The departure date. */
|
||||
private String departureDate = null;
|
||||
/** The return date. It may be null. */
|
||||
private String returnDate = null;
|
||||
|
||||
/** The maximum price the user is willing to pay */
|
||||
private double priceMin = -1;
|
||||
/** The minimum price */
|
||||
private double priceMax = -1;
|
||||
/** The currency */
|
||||
private String currency = null;
|
||||
|
||||
/** The departure location */
|
||||
private String locationFrom = null;
|
||||
/** The destination location */
|
||||
private String locationTo = null;
|
||||
|
||||
/** The preferred departure Time */
|
||||
private String departureTime = null;
|
||||
/** the preferred return Time*/
|
||||
private String returnTime = null;
|
||||
|
||||
/** the number of people is traveling */
|
||||
private int number = 1;
|
||||
|
||||
/** */
|
||||
private TravelType type = null;
|
||||
/** */
|
||||
private boolean scales = false;
|
||||
|
||||
/** The unique id for the dialog. It is used to group dialog entries */
|
||||
private String queryId = null;
|
||||
|
||||
/**
|
||||
* @return the departureDate
|
||||
*/
|
||||
public String getDepartureDate() {
|
||||
return departureDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param departureDate the departureDate to set
|
||||
*/
|
||||
public void setDepartureDate(String departureDate) {
|
||||
this.departureDate = departureDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the returnDate
|
||||
*/
|
||||
public String getReturnDate() {
|
||||
return returnDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param returnDate the returnDate to set
|
||||
*/
|
||||
public void setReturnDate(String returnDate) {
|
||||
this.returnDate = returnDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the priceMin
|
||||
*/
|
||||
public double getPriceMin() {
|
||||
return priceMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param priceMin the priceMin to set
|
||||
*/
|
||||
public void setPriceMin(double priceMin) {
|
||||
this.priceMin = priceMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param priceMax the priceMax to set
|
||||
*/
|
||||
public void setPriceMin(String priceMin) {
|
||||
if (priceMin == null){ return; }
|
||||
|
||||
try{
|
||||
this.priceMin = Double.parseDouble(priceMin);
|
||||
}
|
||||
catch (NumberFormatException nfe){
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the priceMax
|
||||
*/
|
||||
public double getPriceMax() {
|
||||
return priceMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param priceMax the priceMax to set
|
||||
*/
|
||||
public void setPriceMax(double priceMax) {
|
||||
this.priceMax = priceMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param priceMax the priceMax to set
|
||||
*/
|
||||
public void setPriceMax(String priceMax) {
|
||||
if (priceMax == null){ return; }
|
||||
|
||||
try{
|
||||
this.priceMax = Double.parseDouble(priceMax);
|
||||
}
|
||||
catch (NumberFormatException nfe){
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currency
|
||||
*/
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currency the currency to set
|
||||
*/
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the locationFrom
|
||||
*/
|
||||
public String getLocationFrom() {
|
||||
return locationFrom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param locationFrom the locationFrom to set
|
||||
*/
|
||||
public void setLocationFrom(String locationFrom) {
|
||||
this.locationFrom = locationFrom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the locationTo
|
||||
*/
|
||||
public String getLocationTo() {
|
||||
return locationTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param locationTo the locationTo to set
|
||||
*/
|
||||
public void setLocationTo(String locationTo) {
|
||||
this.locationTo = locationTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the departureTime
|
||||
*/
|
||||
public String getDepartureTime() {
|
||||
return departureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param departureTime the departureTime to set
|
||||
*/
|
||||
public void setDepartureTime(String departureTime) {
|
||||
this.departureTime = departureTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the returnReturn
|
||||
*/
|
||||
public String getReturnTime() {
|
||||
return returnTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param returnReturn the returnReturn to set
|
||||
*/
|
||||
public void setReturnTime(String returnTime) {
|
||||
this.returnTime = returnTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public TravelType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type the type to set
|
||||
*/
|
||||
public void setType(TravelType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scales
|
||||
*/
|
||||
public boolean isScales() {
|
||||
return scales;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scales the scales to set
|
||||
*/
|
||||
public void setScales(boolean scales) {
|
||||
this.scales = scales;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number
|
||||
*/
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param number the number to set
|
||||
*/
|
||||
public void setNumber(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public void setNumber(String number){
|
||||
if(number == null){ return; }
|
||||
try{
|
||||
this.number = Integer.parseInt(number);
|
||||
}
|
||||
catch(NumberFormatException nfe){
|
||||
// Ok
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the queryId
|
||||
*/
|
||||
public String getQueryId() {
|
||||
return queryId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param queryId the queryId to set
|
||||
*/
|
||||
public void setQueryId(String queryId) {
|
||||
this.queryId = queryId;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
|
||||
String toString = queryId + number;
|
||||
toString += "ticket(s) from: ";
|
||||
toString += locationFrom;
|
||||
toString += " to: ";
|
||||
toString += locationTo;
|
||||
toString += " the day ";
|
||||
toString += departureDate;
|
||||
toString += " at ";
|
||||
toString += departureTime;
|
||||
toString += " returning the day ";
|
||||
toString += returnTime;
|
||||
toString += " at ";
|
||||
toString += returnTime;
|
||||
toString += " for ";
|
||||
toString += priceMax + "->" + priceMin;
|
||||
toString += " ";
|
||||
toString += currency;
|
||||
return toString;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public List<Literal> toPercepts() {
|
||||
|
||||
List<Literal> list = new LinkedList<Literal>();
|
||||
|
||||
if(departureDate != null){
|
||||
list.add(NLUModel.getLiteralDateDeparture(queryId, TRAVEL_DOMAIN, "03", "04", "2012"));
|
||||
}
|
||||
|
||||
if(returnDate != null){
|
||||
list.add(NLUModel.getLiteralDateReturn(queryId, TRAVEL_DOMAIN, "03", "04", "2012"));
|
||||
}
|
||||
|
||||
if(departureTime != null){
|
||||
list.add(NLUModel.getLiteralTimeDeparture(queryId, TRAVEL_DOMAIN, "09", "00"));
|
||||
}
|
||||
|
||||
if(returnTime != null){
|
||||
list.add(NLUModel.getLiteralTimeReturn(queryId, TRAVEL_DOMAIN, "09", "00"));
|
||||
}
|
||||
|
||||
if(priceMax >= 0){
|
||||
list.add(NLUModel.getLiteralPriceMax(queryId, TRAVEL_DOMAIN, priceMax));
|
||||
}
|
||||
|
||||
if(priceMin >= 0){
|
||||
list.add(NLUModel.getLiteralPriceMin(queryId, TRAVEL_DOMAIN, priceMin));
|
||||
}
|
||||
|
||||
if(currency != null){
|
||||
list.add(NLUModel.getLiteralCurrency(queryId, TRAVEL_DOMAIN, NotationUtils.compact(currency)));
|
||||
}
|
||||
|
||||
if(locationFrom != null){
|
||||
list.add(NLUModel.getLiteralLocationFrom(queryId, TRAVEL_DOMAIN, NotationUtils.compact(locationFrom)));
|
||||
}
|
||||
|
||||
if(locationTo != null){
|
||||
list.add(NLUModel.getLiteralLocationTo(queryId, TRAVEL_DOMAIN, NotationUtils.compact(locationTo)));
|
||||
}
|
||||
|
||||
if(scales){
|
||||
list.add(Literal.parseLiteral("scales[query(" + queryId + "), domain(" + TRAVEL_DOMAIN + ")]"));
|
||||
}
|
||||
else{
|
||||
list.add(Literal.parseLiteral("~scales[query(" + queryId + "), domain(" + TRAVEL_DOMAIN + ")]"));
|
||||
}
|
||||
|
||||
list.add(Literal.parseLiteral("done[query(" + queryId + "), domain(" + TRAVEL_DOMAIN + ")]"));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package es.upm.dit.gsi.sojason.beans;
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author miguel
|
||||
*
|
||||
*/
|
||||
public interface Perceptable {
|
||||
|
||||
public List<Literal> toPercepts();
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package es.upm.dit.gsi.sojason.beans;
|
||||
|
||||
/**
|
||||
* This defines the different means of transport.
|
||||
* @author gsi.dit.upm.es
|
||||
*/
|
||||
public enum TravelType {
|
||||
flight,
|
||||
train,
|
||||
coach
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package es.upm.dit.gsi.sojason.services;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* This interface defines a standard way to connect to a web service in
|
||||
* the definition of an external action in Jason.
|
||||
*
|
||||
* Project: Web40SOJason
|
||||
* Package: es.upm.dit.gsi.sojason.services
|
||||
* Class: WebServiceConnector
|
||||
*
|
||||
* @author Miguel Coronado (miguelcb@dit.upm.es)
|
||||
* @version Feb 27, 2012
|
||||
*
|
||||
*/
|
||||
public interface WebServiceConnector {
|
||||
|
||||
/**
|
||||
* This calls the service including in the request the parameters given.
|
||||
* The URL of the service, the method to use and any other particularity
|
||||
* of the transaction to connect to the service must be determined in the
|
||||
* implementation of the method.
|
||||
*
|
||||
* @param params The list of parameters to include in the service
|
||||
* request. Due to this is not a <code>Dictionary</code>
|
||||
* the order of the parameters it is important and will be
|
||||
* determined by the implementation of the extendee
|
||||
* classes.
|
||||
*/
|
||||
public Collection<Literal> call(String... params);
|
||||
|
||||
/**
|
||||
* This validates the set of parameters provided. Typically, this method
|
||||
* should use some regex exprsesions to check whether a parameter is valid
|
||||
* or not, due to the nature of the parameter cannot be checked because of
|
||||
* the type of the parameters has been unified to String.
|
||||
*
|
||||
* @param params The list of parameters to validate
|
||||
*/
|
||||
public boolean validateParams(String... params);
|
||||
|
||||
/**
|
||||
* This generates a set of error <code>Literal</code>s that describes the
|
||||
* errors committed when trying to call the given service with the set of
|
||||
* parameters given.
|
||||
*
|
||||
* @param params The list of parameters
|
||||
*/
|
||||
// public Set<Literal> checkForErrors(String... params);
|
||||
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package es.upm.dit.gsi.sojason.services.nlu;
|
||||
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_CURRENCY_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_DATES_DEPART_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_DATES_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_DATES_RETURN_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_DOMAINS_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_FROM_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_TO_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_LOCATIONS_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_MAX_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_MIN_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_NUMBER_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_PRICE_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_TIME_DEPART_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_TIME_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_TIME_RETURN_NODENAME;
|
||||
import static es.upm.dit.gsi.sojason.services.nlu.NLUModel.JSON_TRAVEL_NODENAME;
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.codehaus.jackson.JsonNode;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
|
||||
import es.upm.dit.gsi.jason.utils.NotationUtils;
|
||||
import es.upm.dit.gsi.sojason.Web40Model;
|
||||
import es.upm.dit.gsi.sojason.beans.NLUTravel;
|
||||
import es.upm.dit.gsi.sojason.services.WebServiceConnector;
|
||||
|
||||
/**
|
||||
* Project: Web40SOJason
|
||||
* Package: es.upm.dit.gsi.sojason.services.nlu
|
||||
* Class: NLUConnector
|
||||
*
|
||||
* @author Miguel Coronado (miguelcb@dit.upm.es)
|
||||
* @version Feb 27, 2012
|
||||
*
|
||||
*/
|
||||
public class NLUConnector implements WebServiceConnector{
|
||||
|
||||
/** The url of the service */
|
||||
private String serviceUrl;
|
||||
/** */
|
||||
private Logger logger = Logger.getLogger("Web40SOJason." + NLUConnector.class.getName());
|
||||
|
||||
|
||||
/** Constructor */
|
||||
public NLUConnector(String serviceUrl) {
|
||||
this.serviceUrl = serviceUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public Collection<Literal> call(String... params) {
|
||||
|
||||
/* Are parameters correct */
|
||||
if (!validateParams(params)){
|
||||
logger.info("Parameters are not valid:" + Arrays.toString(params));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Prepare the request
|
||||
String urlRequest = prepareRequest(params[0], params[1]);
|
||||
|
||||
URL url = new URL(urlRequest);
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.connect();
|
||||
|
||||
// Parse the data received (using Jackson lib)
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode rootNode = mapper.readValue(connection.getInputStream(), JsonNode.class); // src can be a File, URL, InputStream etc
|
||||
JsonNode travelNode = rootNode.with(JSON_DOMAINS_NODENAME).get(JSON_TRAVEL_NODENAME);
|
||||
|
||||
NLUTravel travel = new NLUTravel();
|
||||
travel.setDepartureDate(travelNode.with(JSON_DATES_NODENAME).get(JSON_DATES_DEPART_NODENAME).getTextValue());
|
||||
travel.setReturnDate(travelNode.with(JSON_DATES_NODENAME).get(JSON_DATES_RETURN_NODENAME).getTextValue());
|
||||
|
||||
travel.setCurrency(travelNode.with(JSON_PRICE_NODENAME).get(JSON_CURRENCY_NODENAME).getTextValue());
|
||||
travel.setPriceMax(travelNode.with(JSON_PRICE_NODENAME).get(JSON_MAX_NODENAME).getTextValue());
|
||||
travel.setPriceMin(travelNode.with(JSON_PRICE_NODENAME).get(JSON_MIN_NODENAME).getTextValue());
|
||||
|
||||
travel.setLocationFrom(travelNode.with(JSON_LOCATIONS_NODENAME).get(JSON_FROM_NODENAME).getTextValue());
|
||||
travel.setLocationTo(travelNode.with(JSON_LOCATIONS_NODENAME).get(JSON_TO_NODENAME).getTextValue());
|
||||
|
||||
travel.setNumber(travelNode.get(JSON_NUMBER_NODENAME).getTextValue());
|
||||
|
||||
travel.setReturnTime(travelNode.with(JSON_TIME_NODENAME).get(JSON_TIME_RETURN_NODENAME).getTextValue());
|
||||
travel.setDepartureTime(travelNode.with(JSON_TIME_NODENAME).get(JSON_TIME_DEPART_NODENAME).getTextValue());
|
||||
|
||||
travel.setQueryId(params[0]);
|
||||
|
||||
// System.out.println(travel);
|
||||
|
||||
return travel.toPercepts();
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
// return CollectionUtils.wrapList("error(malformed_url, \"The given url is not valid\")");
|
||||
logger.info("MalformedURLException:" + e.getMessage()); return null;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// return CollectionUtils.wrapList("error(undupported_encodig, \"The encoding given is not supported\")");
|
||||
logger.info("UnsupportedEncodingException:" + e.getMessage()); return null;
|
||||
} catch (IOException e) {
|
||||
// return CollectionUtils.wrapList("error(io_exception, \"Someio exception ocurr\")");
|
||||
logger.info("IOException:" + e.getMessage()); return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This generates a String used as http GET request to access the service
|
||||
* including the parameters given by the user
|
||||
*
|
||||
* @param queryid
|
||||
* @param message
|
||||
* @return the url service string (utf-8 encoded)
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
String prepareRequest(String queryid, String message) throws UnsupportedEncodingException {
|
||||
String urlRequest = this.serviceUrl;
|
||||
urlRequest = urlRequest.concat("?text=");
|
||||
message = NotationUtils.removeQuotation(message);
|
||||
urlRequest = urlRequest.concat(URLEncoder.encode(message, "utf-8"));
|
||||
// urlRequest = urlRequest.concat(URLEncoder.encode("&query_id=", "utf-8"));
|
||||
urlRequest = urlRequest.concat("&query_id=");
|
||||
urlRequest = urlRequest.concat(URLEncoder.encode(queryid, "utf-8"));
|
||||
|
||||
logger.info(urlRequest);
|
||||
return urlRequest ;
|
||||
}
|
||||
|
||||
/**
|
||||
* This validates the parameters received. The
|
||||
* {@link NLUConnector#call(String...)} method expects to receive two
|
||||
* parameters of the nature and characteristics described below:
|
||||
*
|
||||
* <ul>
|
||||
* <li>The first parameter is que query id. It is an alphanumeric string
|
||||
* which normally will contain numbers, but other non-digit characters
|
||||
* are permitted. <b>No alphanumeric values are not allowed</b></li>
|
||||
* <li></li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
public boolean validateParams(String... params) {
|
||||
if (params.length != 2){
|
||||
return false;
|
||||
}
|
||||
// TODO: check other things
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package es.upm.dit.gsi.sojason.services.nlu;
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Project: Web40
|
||||
* Package: es.upm.dit.gsi.qa.services.nlu
|
||||
* Class:
|
||||
*
|
||||
* @author Miguel Coronado (miguelcb@dit.upm.es)
|
||||
* @version Feb 28, 2012
|
||||
*
|
||||
*/
|
||||
public class NLUModel {
|
||||
|
||||
|
||||
public final static String JSON_DOMAINS_NODENAME = "domains";
|
||||
|
||||
public final static String JSON_TRAVEL_NODENAME = "travel";
|
||||
|
||||
public final static String JSON_DATES_NODENAME = "dates";
|
||||
|
||||
public final static String JSON_DATES_DEPART_NODENAME = "depart";
|
||||
|
||||
public final static String JSON_DATES_RETURN_NODENAME = "return";
|
||||
|
||||
public final static String JSON_PRICE_NODENAME = "price";
|
||||
|
||||
public final static String JSON_CURRENCY_NODENAME = "currency";
|
||||
|
||||
public final static String JSON_MAX_NODENAME = "max";
|
||||
|
||||
public final static String JSON_MIN_NODENAME = "min";
|
||||
|
||||
public final static String JSON_LOCATIONS_NODENAME = "locations";
|
||||
|
||||
public final static String JSON_FROM_NODENAME = "from";
|
||||
|
||||
public final static String JSON_TO_NODENAME = "to";
|
||||
|
||||
public final static String JSON_NUMBER_NODENAME = "number";
|
||||
|
||||
public final static String JSON_TIME_NODENAME = "time";
|
||||
|
||||
public final static String JSON_TIME_DEPART_NODENAME = "depart";
|
||||
|
||||
public final static String JSON_TIME_RETURN_NODENAME = "return";
|
||||
|
||||
|
||||
|
||||
public static Literal getLiteralPriceMin (String query, String domain, double price) {
|
||||
return Literal.parseLiteral("price(min," + price + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralPriceMax (String query, String domain, double price) {
|
||||
return Literal.parseLiteral("price(max," + price + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralCurrency (String query, String domain, String currency) {
|
||||
return Literal.parseLiteral("currency(" + currency + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralLocationFrom (String query, String domain, String place) {
|
||||
return Literal.parseLiteral("location(from," + place + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralLocationTo (String query, String domain, String place) {
|
||||
return Literal.parseLiteral("location(to," + place + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralDateDeparture (String query, String domain, String day, String month, String year) {
|
||||
return Literal.parseLiteral("date(departure," + day + "," + month + "," + year + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralDateReturn (String query, String domain, String day, String month, String year) {
|
||||
return Literal.parseLiteral("date(return," + day + "," + month + "," + year + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralTimeDeparture (String query, String domain, String hour, String min) {
|
||||
return Literal.parseLiteral("time(departure," + hour + "," + min + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralTimeReturn (String query, String domain, String hour, String min) {
|
||||
return Literal.parseLiteral("time(return," + hour + "," + min + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
public static Literal getLiteralType (String query, String domain, String type) {
|
||||
return Literal.parseLiteral("type(" + type + ")[query("+ query +"),domain("+ domain +")]");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package es.upm.dit.gsi.sojason.services.travel;
|
||||
|
||||
import jason.asSyntax.Literal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import es.upm.dit.gsi.sojason.beans.Journey;
|
||||
import es.upm.dit.gsi.sojason.beans.Perceptable;
|
||||
import es.upm.dit.gsi.sojason.services.WebServiceConnector;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author miguel
|
||||
*
|
||||
*/
|
||||
public class RenfeScrapper implements WebServiceConnector {
|
||||
|
||||
/**
|
||||
* It contains all the information about the <i>Renfe</i>
|
||||
* web service URL convenion.
|
||||
*/
|
||||
RenfeServiceConvenion queryGenerator;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @throws IOException if there is any error while loading the station ids.
|
||||
*/
|
||||
public RenfeScrapper() throws IOException {
|
||||
this.queryGenerator = new RenfeServiceConvenion();
|
||||
}
|
||||
|
||||
|
||||
public Collection<Literal> call(String... params) {
|
||||
|
||||
if(!validateParams(params)){
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
List<Perceptable> schedule = getSchedule ( params[0].toString(),
|
||||
params[1].toString(),
|
||||
params[2].toString(),
|
||||
params[3].toString(),
|
||||
params[4].toString());
|
||||
|
||||
// prepare response
|
||||
Collection<Literal> res = new LinkedList<Literal>();
|
||||
for (Perceptable travel : schedule){
|
||||
res.addAll(travel.toPercepts());
|
||||
}
|
||||
return res;
|
||||
|
||||
} catch (IOException e) {
|
||||
// return CollectionUtils.wrapList("error(io_exception, \"Someio exception ocurr\")");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean validateParams(String... params) {
|
||||
if(params.length != 5){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: filter by time
|
||||
*
|
||||
*
|
||||
* @param origin
|
||||
* @param destination
|
||||
* @param day
|
||||
* @param month
|
||||
* @param year
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public List<Perceptable> getSchedule (String origin, String destination,
|
||||
String day, String month, String year) throws IOException {
|
||||
|
||||
// The list with the journeys that matches the given criteria
|
||||
List<Perceptable> retList = new LinkedList<Perceptable>();
|
||||
|
||||
// Get the html
|
||||
String queryUrl = "";
|
||||
try{
|
||||
queryUrl = queryGenerator.generateQuery(origin, destination, day, month, year);
|
||||
}
|
||||
catch(IllegalArgumentException iae){
|
||||
retList.add( queryGenerator.reportParamErrors(origin, destination, day, month, year) );
|
||||
return retList;
|
||||
}
|
||||
Document doc = Jsoup.connect(queryUrl).get();
|
||||
|
||||
// Get the rows of the schedule table
|
||||
Elements rows = doc.select("table#row > tbody > tr");
|
||||
// Each row has the information of a different journey
|
||||
for (Element row : rows) {
|
||||
Elements cells = row.getElementsByTag("td");
|
||||
if(cells.size() > 2){
|
||||
|
||||
// get and fill the journey information
|
||||
Journey journey = new Journey();
|
||||
journey.setOrigin(origin);
|
||||
journey.setDestination(destination);
|
||||
journey.setDepartureTime(cells.get(1).text());
|
||||
journey.setArrivalTime(cells.get(2).text());
|
||||
journey.setDuration(cells.get(3).text());
|
||||
|
||||
// the fee map for the particular journey
|
||||
Map<String, String> feeMap = new HashMap<String,String>();
|
||||
// get the fares
|
||||
Elements feeRows = cells.get(4).select("tbody tr");
|
||||
|
||||
/* According to Renfe's website we select the following sublist */
|
||||
int fromIndex = 1; // skip the header row
|
||||
/* They present 2 set of fares (Internet and station) so we skip
|
||||
* the header rows and divide by 2 to get the amount of fares to
|
||||
* parse */
|
||||
int toIndex = 1+(feeRows.size()-2)/2;
|
||||
|
||||
for(Element feeRow : feeRows.subList(fromIndex, toIndex)) {
|
||||
Elements feeCells = feeRow.getElementsByTag("td");
|
||||
// String feeName = feeCells.get(1).text().toLowerCase().replace(" ", "").replace(":", "").replace("ñ", "n");
|
||||
String feeName = feeCells.get(1).text().replace(":", "");
|
||||
String price = feeCells.get(2).text().replace(",", ".");
|
||||
// Set the fee
|
||||
feeMap.put(feeName, price);
|
||||
}
|
||||
|
||||
// Set the fares
|
||||
journey.setFares(feeMap);
|
||||
retList.add(journey);
|
||||
}
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
||||
/**
|
||||
* try it
|
||||
* @param args
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String [] args) throws IOException{
|
||||
RenfeScrapper rs = new RenfeScrapper();
|
||||
List<Perceptable> list = rs.getSchedule ("Madrid", "ciudad real", "16", "04", "2012");
|
||||
for(Perceptable journey : list){
|
||||
System.out.println(journey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,210 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package es.upm.dit.gsi.sojason.services.travel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import es.upm.dit.gsi.jason.utils.NotationUtils;
|
||||
import es.upm.dit.gsi.sojason.beans.ErrorReport;
|
||||
|
||||
/**
|
||||
* This class describes the
|
||||
* @author gsi.dit.upm.es
|
||||
* @version 1.0
|
||||
*/
|
||||
public class RenfeServiceConvenion {
|
||||
|
||||
public final static String SERVICE_URL = "http://horarios.renfe.com/HIRRenfeWeb/buscar.do";
|
||||
public final static String ORIGIN_PARAM = "O";
|
||||
public final static String DESTINATION_PARAM = "D";
|
||||
public final static String YEAR_PARAM = "AF";
|
||||
public final static String MONTH_PARAM = "MF";
|
||||
public final static String DAY_PARAM = "DF";
|
||||
public final static String DEFAULT_PATH_TO_CITY_CODES_FILE = "conf/cities.xml";
|
||||
|
||||
private Properties cityCodes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param cityCodesFile
|
||||
* @throws IOException
|
||||
*/
|
||||
public RenfeServiceConvenion (File cityCodesFile) throws IOException {
|
||||
this.cityCodes = new Properties();
|
||||
this.cityCodes.loadFromXML(new FileInputStream(cityCodesFile));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
* @throws IOException
|
||||
*/
|
||||
public RenfeServiceConvenion () throws IOException {
|
||||
this(new File(DEFAULT_PATH_TO_CITY_CODES_FILE));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param origin
|
||||
* @param destination
|
||||
* @param day
|
||||
* @param month
|
||||
* @param year
|
||||
* @return
|
||||
*/
|
||||
public String generateQuery (String origin, String destination,
|
||||
String day, String month, String year){
|
||||
|
||||
origin = NotationUtils.uncompact(origin);
|
||||
destination = NotationUtils.uncompact(destination);
|
||||
|
||||
if(!validateParams(origin, destination, day, month, year)){
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
String res = SERVICE_URL;
|
||||
res = res.concat("?");
|
||||
res = res.concat(ORIGIN_PARAM);
|
||||
res = res.concat("=");
|
||||
res = res.concat(this.cityCodes.getProperty(origin.toLowerCase()));
|
||||
res = res.concat("&");
|
||||
res = res.concat(DESTINATION_PARAM);
|
||||
res = res.concat("=");
|
||||
res = res.concat(this.cityCodes.getProperty(destination.toLowerCase()));
|
||||
res = res.concat("&");
|
||||
res = res.concat(YEAR_PARAM);
|
||||
res = res.concat("=");
|
||||
res = res.concat(year);
|
||||
res = res.concat("&");
|
||||
res = res.concat(MONTH_PARAM);
|
||||
res = res.concat("=");
|
||||
res = res.concat(month);
|
||||
res = res.concat("&");
|
||||
res = res.concat(DAY_PARAM);
|
||||
res = res.concat("=");
|
||||
res = res.concat(day);
|
||||
// 'concat' is faster than '+' operator
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param origin
|
||||
* @param destination
|
||||
* @param day
|
||||
* @param month
|
||||
* @param year
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
protected boolean validateParams(String origin, String destination, String day,
|
||||
String month, String year) {
|
||||
|
||||
if(!Pattern.matches("\\d{4}", year)){
|
||||
return false;
|
||||
}
|
||||
if(!Pattern.matches("\\d{1,2}", month)){
|
||||
return false;
|
||||
}
|
||||
if(!Pattern.matches("\\d{1,2}", day)){
|
||||
return false;
|
||||
}
|
||||
|
||||
int monthI = Integer.parseInt(month);
|
||||
int dayI = Integer.parseInt(day);
|
||||
int monthNumberOfDays[] = {31,29,31,30,31,30,31,31,30,31,30,31};
|
||||
if(monthI < 1 || monthI > 12){
|
||||
return false;
|
||||
}
|
||||
if(dayI < 1 || dayI > monthNumberOfDays[monthI-1]){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(origin == null || !this.cityCodes.containsKey(origin.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(destination == null || !this.cityCodes.containsKey(destination.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected ErrorReport reportParamErrors (String origin, String destination, String day,
|
||||
String month, String year) {
|
||||
|
||||
ErrorReport errors = new ErrorReport();
|
||||
|
||||
if(!Pattern.matches("\\d{4}", year)){
|
||||
errors.put("year", "invalid format");
|
||||
}
|
||||
if(!Pattern.matches("\\d{1,2}", month)){
|
||||
errors.put("month", "invalid format");
|
||||
}
|
||||
if(!Pattern.matches("\\d{1,2}", day)){
|
||||
errors.put("day", "invalid format");
|
||||
}
|
||||
|
||||
int monthI = Integer.parseInt(month);
|
||||
int dayI = Integer.parseInt(day);
|
||||
int monthNumberOfDays[] = {31,29,31,30,31,30,31,31,30,31,30,31};
|
||||
if(monthI < 1 || monthI > 12){
|
||||
errors.put("month", "out of range");
|
||||
monthI = 1; // this lets check the day
|
||||
}
|
||||
if(dayI < 1 || dayI > monthNumberOfDays[monthI-1]){
|
||||
errors.put("day", "out of range");
|
||||
}
|
||||
|
||||
if(origin == null || !this.cityCodes.containsKey(origin.toLowerCase())) {
|
||||
errors.put("origin", "no such location");
|
||||
}
|
||||
|
||||
if(destination == null || !this.cityCodes.containsKey(destination.toLowerCase())) {
|
||||
errors.put("destination", "no such location");
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param arga
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void main(String [] arga) throws IOException{
|
||||
|
||||
// RenfeServiceConvenion rsc = new RenfeServiceConvenion();
|
||||
// Properties newProperties = new Properties();
|
||||
//
|
||||
// for (Object key : rsc.cityCodes.keySet() ){
|
||||
// String keyStr = (String)key;
|
||||
// keyStr = keyStr.toLowerCase();
|
||||
// newProperties.put(keyStr, rsc.cityCodes.get(key));
|
||||
// if (keyStr.contains("á") ||
|
||||
// keyStr.contains("é") ||
|
||||
// keyStr.contains("í") ||
|
||||
// keyStr.contains("ó") ||
|
||||
// keyStr.contains("ú")) {
|
||||
//
|
||||
// keyStr = keyStr.replace("á", "a").replace("é", "e").replace("í", "i").replace("ó", "o").replace("ú", "u");
|
||||
// newProperties.put(keyStr, rsc.cityCodes.get(key));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// newProperties.storeToXML(new FileOutputStream(DEFAULT_PATH_TO_CITY_CODES_FILE), "comment");
|
||||
|
||||
RenfeServiceConvenion rsc = new RenfeServiceConvenion();
|
||||
String res = rsc.generateQuery("Madrid", "Ciudad Real", "15", "02", "2012");
|
||||
System.out.println(res);
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue