001/** 002 * Test1.java 003 * jCOLIBRI2 framework. 004 * @author Juan A. Recio-Garc�a. 005 * GAIA - Group for Artificial Intelligence Applications 006 * http://gaia.fdi.ucm.es 007 * 28/11/2006 008 */ 009package es.ucm.fdi.gaia.jcolibri.test.test1; 010 011import java.util.Collection; 012 013import es.ucm.fdi.gaia.jcolibri.casebase.LinealCaseBase; 014import es.ucm.fdi.gaia.jcolibri.cbraplications.StandardCBRApplication; 015import es.ucm.fdi.gaia.jcolibri.cbrcore.Attribute; 016import es.ucm.fdi.gaia.jcolibri.cbrcore.CBRCaseBase; 017import es.ucm.fdi.gaia.jcolibri.cbrcore.CBRQuery; 018import es.ucm.fdi.gaia.jcolibri.cbrcore.Connector; 019import es.ucm.fdi.gaia.jcolibri.connector.DataBaseConnector; 020import es.ucm.fdi.gaia.jcolibri.exception.ExecutionException; 021import es.ucm.fdi.gaia.jcolibri.method.retrieve.RetrievalResult; 022import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.NNConfig; 023import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.NNScoringMethod; 024import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.similarity.global.Average; 025import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.similarity.local.Equal; 026import es.ucm.fdi.gaia.jcolibri.method.retrieve.NNretrieval.similarity.local.Interval; 027import es.ucm.fdi.gaia.jcolibri.method.retrieve.selection.SelectCases; 028 029/** 030 * Test 1 shows how to use a simple data base connector and perform the KNN retrieval. It uses the travel example with cases that only have description 031 * (without solution or result). 032 * <br> 033 * This example uses the DataBase connector that is implemented using the <a href="www.hibernate.org">Hibernate</a> library. 034 * That library is a Java Data Objects implementation that automatically manages the persistence of 035 * Java beans in relational data bases. 036 * <br>For an introduction to hibernate see: <a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/tutorial.html">http://www.hibernate.org/hib_docs/v3/reference/en/html/tutorial.html</a> 037 * <p> 038 * The DataBase connector in es/ucm/fdi/gaia/jcolibri/test/test1/databaseconfig.xml and that xml defines the configuration of Hibernate and 039 * the mapping of the description of our case with the data base. In this example, all the attributes of the description bean are stored in the same table. 040 * <br> 041 * <ul> 042 * <li><b>databaseconfig.xml</b>.<br>Connector configuration file: indicates the path to the hibernate config file, the name of the class/bean that stores the description and its mapping file.<br> 043 * <pre> 044 * <DataBaseConfiguration> 045 * <HibernateConfigFile>es/ucm/fdi/gaia/jcolibri/test/test1/hibernate.cfg.xml</HibernateConfigFile> 046 * <DescriptionMappingFile>es/ucm/fdi/gaia/jcolibri/test/test1/TravelDescription.hbm.xml</DescriptionMappingFile> 047 * <DescriptionClassName>es.ucm.fdi.gaia.jcolibri.test.test1.TravelDescription</DescriptionClassName> 048 * </DataBaseConfiguration> 049 * </pre> 050 * 051 * <li><b>hibernate.cfg.xml</b>.<br>Hibernate configuration file: developers should only modify the database connection settings.<br> 052 * <pre> 053 * <hibernate-configuration> 054 * <session-factory> 055 * <!-- Database connection settings --> 056 * <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> 057 * <property name="connection.url">jdbc:hsqldb:hsql://localhost/travel</property> 058 * <property name="connection.username">sa</property> 059 * <property name="connection.password"></property> 060 * 061 * <!-- JDBC connection pool (use the built-in) --> 062 * <property name="connection.pool_size">1</property> 063 * 064 * <!-- SQL dialect --> 065 * <property name="dialect">org.hibernate.dialect.HSQLDialect</property> 066 * 067 * <!-- Enable Hibernate's automatic session context management --> 068 * <property name="current_session_context_class">thread</property> 069 * 070 * <!-- Disable the second-level cache --> 071 * <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> 072 * 073 * <!-- Echo all executed SQL to stdout --> 074 * <property name="show_sql">true</property> 075 * </session-factory> 076 * </hibernate-configuration> 077 * </pre> 078 * <p>This test uses the HSQLDB data base server with an example table containing 079 * the data of the case base. Developers can use any other DBMS changing the 080 * hibernate configuration file. 081 * <br> 082 * If you use another database change the driver, url and dialect fields. 083 * For example, to use a MySQL server you should use: 084 * <pre> 085 * <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 086 * <property name="connection.url">jdbc:mysql://localhost:3306/travel</property> 087 * <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 088 * </pre> 089 * For other configuration settings see hiberante documentation: 090 * <a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/session-configuration.html">http://www.hibernate.org/hib_docs/v3/reference/en/html/session-configuration.html</a> 091 * </p> 092 * </li> 093 * <li><b>TravelDescription.hbm.xml</b>.<br> Hibernate mapping file for the description bean the case (TravelDescription.java). 094 * It stores each attribute of the description in a column of the table Travel.<br> 095 * <pre> 096 * <hibernate-mapping default-lazy="false"> 097 * <class name="es.ucm.fdi.gaia.jcolibri.test.test1.TravelDescription" table="Travel"> 098 * <id name="caseId" column="caseId"> 099 * <generator class="native"/> 100 * </id> 101 * <property name="HolidayType" column="HolidayType"/> 102 * <property name="Price" column="Price"/> 103 * <property name="NumberOfPersons" column="NumberOfPersons"/> 104 * <property name="Region" column="Region"/> 105 * <property name="Transportation" column="Transportation"/> 106 * <property name="Duration" column="Duration"/> 107 * <property name="Season" column="Season"/> 108 * <property name="Accomodation" column="Accommodation"/> 109 * <property name="Hotel" column="Hotel"/> 110 * </class> 111 * </hibernate-mapping> 112 * </pre> 113 * Here we set that TravelDescription is mapped in the Travel table. caseId is the primary key of the table and Hibernate will use a 114 * native key generator for new cases (there are different ways to create primary keys, for more information see Hiberante documentation). 115 * Each attribute is mapped into a table with the same name. You should notice that here we don't indicate the type of the attributes. 116 * Hibernate automatically detects the type and converts from/to the database. Anyway if you want to use an unrecognoized type that hibernate does not 117 * understand or create your own one you can do it by implementing the jcolibri.connector.TypeAdaptor interface in your type. 118 * <br> 119 * This is the structure of the table: 120 * <pre> 121 * +----------+-------------+-------+-----------------+--------+----------------+----------+--------+---------------+--------------------------+ 122 * | caseId | HolidayType | Price | NumberOfPersons | Region | Transportation | Duration | Season | Accommodation | Hotel | 123 * +----------+-------------+-------+-----------------+--------+----------------+----------+--------+---------------+--------------------------+ 124 * | Journey1 | Bathing | 2498 | 2 | Egypt | Plane | 14 | April | TwoStars | Hotel White House, Egypt | 125 * | Journey2 | Bathing | 3066 | 3 | Egypt | Plane | 21 | May | TwoStars | Hotel White House, Egypt | 126 * ... 127 * </pre> 128 * The travel.sql file contains the code to create this data base. 129 * </ul> 130 * 131 * @author Juan A. Recio-Garcia 132 * @version 1.0 133 * @see es.ucm.fdi.gaia.jcolibri.test.test1.TravelDescription 134 * @see jcolibri.connector.DataBaseConnector 135 */ 136public class Test1 implements StandardCBRApplication { 137 138 /** Connector object */ 139 Connector _connector; 140 /** CaseBase object */ 141 CBRCaseBase _caseBase; 142 143 /* (non-Javadoc) 144 * @see jcolibri.cbraplications.BasicCBRApplication#configure() 145 */ 146 public void configure() throws ExecutionException{ 147 try{ 148 // Create a data base connector 149 _connector = new DataBaseConnector(); 150 // Init the ddbb connector with the config file 151 _connector.initFromXMLfile(es.ucm.fdi.gaia.jcolibri.util.FileIO.findFile("es/ucm/fdi/gaia/jcolibri/test/test1/databaseconfig.xml")); 152 // Create a Lineal case base for in-memory organization 153 _caseBase = new LinealCaseBase(); 154 } catch (Exception e){ 155 throw new ExecutionException(e); 156 } 157 } 158 159 160 161 /* (non-Javadoc) 162 * @see jcolibri.cbraplications.BasicCBRApplication#preCycle() 163 */ 164 public CBRCaseBase preCycle() throws ExecutionException { 165 // Load cases from connector into the case base 166 _caseBase.init(_connector); 167 // Print the cases 168 //java.util.Collection<CBRCase> cases = _caseBase.getCases(); 169 //for(CBRCase c: cases) System.out.println(c); 170 return _caseBase; 171 } 172 173 /* (non-Javadoc) 174 * @see jcolibri.cbraplications.BasicCBRApplication#cycle() 175 */ 176 public void cycle(CBRQuery query) throws ExecutionException 177 { 178 // First configure the KNN 179 NNConfig simConfig = new NNConfig(); 180 // Set the average() global similarity function for the description of the case 181 simConfig.setDescriptionSimFunction(new Average()); 182 // The accomodation attribute uses the equal() local similarity function 183 simConfig.addMapping(new Attribute("Accomodation", TravelDescription.class), new Equal()); 184 // For the duration attribute we are going to set its local similarity function and the weight 185 Attribute duration = new Attribute("Duration", TravelDescription.class); 186 simConfig.addMapping(duration, new Interval(31)); 187 simConfig.setWeight(duration, 0.5); 188 // HolidayType --> equal() 189 simConfig.addMapping(new Attribute("HolidayType", TravelDescription.class), new Equal()); 190 // NumberOfPersons --> equal() 191 simConfig.addMapping(new Attribute("NumberOfPersons", TravelDescription.class), new Equal()); 192 // Price --> InrecaLessIsBetter() 193 simConfig.addMapping(new Attribute("Price", TravelDescription.class), new Interval(4000)); 194 195 196 // A bit of verbose 197 System.out.println("Query Description:"); 198 System.out.println(query.getDescription()); 199 System.out.println(); 200 201 // Execute NN 202 Collection<RetrievalResult> eval = NNScoringMethod.evaluateSimilarity(_caseBase.getCases(), query, simConfig); 203 204 // Select k cases 205 eval = SelectCases.selectTopKRR(eval, 5); 206 207 // Print the retrieval 208 System.out.println("Retrieved cases:"); 209 for(RetrievalResult nse: eval) 210 System.out.println(nse); 211 212 213 } 214 215 /* (non-Javadoc) 216 * @see jcolibri.cbraplications.BasicCBRApplication#postCycle() 217 */ 218 public void postCycle() throws ExecutionException { 219 this._caseBase.close(); 220 221 } 222 223 /** 224 * Main function 225 */ 226 public static void main(String[] args) { 227 // Launch DDBB manager 228 es.ucm.fdi.gaia.jcolibri.test.database.HSQLDBserver.init(); 229 // Create the application 230 Test1 test1 = new Test1(); 231 try { 232 // Configure it 233 test1.configure(); 234 // Run the precycle --> load the cases 235 test1.preCycle(); 236 237 //BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 238 //do 239 { 240 // Configure the query. Queries only have description. 241 TravelDescription queryDesc = new TravelDescription(); 242 queryDesc.setAccomodation("ThreeStars"); 243 queryDesc.setDuration(7); 244 queryDesc.setHolidayType("Recreation"); 245 queryDesc.setNumberOfPersons(2); 246 queryDesc.setPrice(700); 247 248 CBRQuery query = new CBRQuery(); 249 query.setDescription(queryDesc); 250 251 // Run a cycle with the query 252 test1.cycle(query); 253 254 System.out.println("Cycle finished. Type exit to idem or enter to repeat the cycle"); 255 } 256 //while(!reader.readLine().equals("exit")); 257 258 // Run the postcycle 259 test1.postCycle(); 260 261 //Shutdown DDBB manager 262 es.ucm.fdi.gaia.jcolibri.test.database.HSQLDBserver.shutDown(); 263 } catch (Exception e) { 264 System.out.println(e.getMessage()); 265 e.printStackTrace(); 266 } 267 } 268 269}