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