001    /**
002     * Test3.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     * 10/01/2007
008     */
009    package jcolibri.test.test3;
010    
011    
012    import java.util.Collection;
013    import java.util.HashMap;
014    
015    import jcolibri.casebase.LinealCaseBase;
016    import jcolibri.cbraplications.StandardCBRApplication;
017    import jcolibri.cbrcore.Attribute;
018    import jcolibri.cbrcore.CBRCase;
019    import jcolibri.cbrcore.CBRCaseBase;
020    import jcolibri.cbrcore.CBRQuery;
021    import jcolibri.cbrcore.Connector;
022    import jcolibri.connector.DataBaseConnector;
023    import jcolibri.exception.ExecutionException;
024    import jcolibri.method.retrieve.RetrievalResult;
025    import jcolibri.method.retrieve.NNretrieval.NNConfig;
026    import jcolibri.method.retrieve.NNretrieval.NNScoringMethod;
027    import jcolibri.method.retrieve.NNretrieval.similarity.global.Average;
028    import jcolibri.method.retrieve.NNretrieval.similarity.local.Equal;
029    import jcolibri.method.retrieve.NNretrieval.similarity.local.Interval;
030    import jcolibri.method.retrieve.selection.SelectCases;
031    import jcolibri.method.reuse.CombineQueryAndCasesMethod;
032    
033    /**
034     * This example shows how to use a compound attribute in the description of a case and how to complete the CBR cycle.
035     * <br>
036     * Now, the description has not a string defining the region. Instead that, it has other bean named "Region" that stores different attributes about the region (nearest city, airport, currency...).
037     * This way, the structure of the case is:
038     * <pre>
039     * Case
040     *  |
041     *  +- Description
042     *          |
043     *          +- caseId
044     *          +- HollidayType
045     *          +- Price
046     *          +- NumberOfPersons
047     *          +- Region
048     *          |     |
049     *          |     +- regionId
050     *          |     +- regionName
051     *          |     +- NearestCity
052     *          |     +- Airport
053     *          |     +- Currency
054     *          +- Transportation
055     *          +- Duration
056     *          +- Season
057     *          +- Accomodation
058     *          +- Hotel
059     * </pre>
060     * <br>
061     * This structure is mapped to the travelext data base that can be created using the travelext.sql file.
062     * It is composed by two tables: travel and region. Travel has a number in the regionid column identifying the row in the region table that contains the information:
063     * <pre>
064     * travel:
065     * +-----------+-------------+-------+-----------------+----------+----------------+----------+-----------+---------------+-----------------------------+
066     * | caseId    | HolidayType | Price | NumberOfPersons | regionId | Transportation | Duration | Season    | Accommodation | Hotel                       |
067     * +-----------+-------------+-------+-----------------+----------+----------------+----------+-----------+---------------+-----------------------------+
068     * | Journey11 | City        |  1978 |               2 |        1 | Plane          |        7 | April     | ThreeStars    | Hotel Victoria, Cairo       |
069     * | Journey21 | Recreation  |  1568 |               2 |        2 | Car            |       14 | May       | TwoStars      | Hotel Ostend, Belgium       |
070     *  ...
071     * region:
072     * +----------+------------+-------------+---------------------------+----------------+
073     * | regionId | RegionName | NearestCity | Airport                   | Currency       |
074     * +----------+------------+-------------+---------------------------+----------------+
075     * |        1 | Cairo      | Cairo       | Cairo Airport             | Egyptian Pound |
076     * |        2 | Belgium    | Brussels    | Brussels National Airport | Euro           |
077     *  ...
078     * </pre>
079     * To map the case structure with the data base we have to modify these lines in hibernate.cfg.xml:
080     * <pre>
081     * &lt;hibernate-mapping default-lazy="false"&gt;
082     *   &lt;class name="jcolibri.test.test3.TravelDescription" table="travel"&gt;
083     *      ...
084     *      &lt;many-to-one name="Region" column="regionId" not-null="true" cascade="save-update"/&gt; 
085     *      ...
086     *   &lt;/class&gt;
087     *   &lt;class name="jcolibri.test.test3.Region" table="region"&gt;
088     *      &lt;id name="id" column="regionId"&gt;
089     *      &lt;/id&gt;
090     *      &lt;property name="region" column="RegionName"/&gt;
091     *      &lt;property name="city" column="NearestCity"/&gt;
092     *      &lt;property name="airport" column="Airport"/&gt;
093     *      &lt;property name="currency" column="Currency"/&gt;
094     *   &lt;/class&gt;
095     * &lt;/hibernate-mapping&gt;
096     * </pre>
097     * The many-to-one tag indicates the association between the regionId column in the travel table with the values of the region table.
098     * <p>
099     * This example also shows how to complete the CBR cycle including reuse, revise and retain methods:
100     * <ul>
101     * <li>Reuse. To reuse a case we have to combine its solution with the description of the query. 
102     * It is done by the method: CombineQueryAndCasesMethod.combine()
103     * <li>Revise. A simple revision consists on defining new values for the ids of the compound attributes to save the new case into the persistence layer. 
104     * It is done by: DefineNewIdsMethod.defineNewIdsMethod()
105     * <li>Retain. Consists on saving a new case into the persistence layer. This is performed by: StoreCasesMethod.storeCase()
106     * </ul>
107     * 
108     * @author Juan A. Recio-Garcia
109     * @version 1.0
110     * @see jcolibri.test.test3.TravelDescription
111     * @see jcolibri.test.test3.Region
112     * @see jcolibri.method.reuse.CombineQueryAndCasesMethod
113     * @see jcolibri.method.revise.DefineNewIdsMethod
114     * @see jcolibri.method.retain.StoreCasesMethod
115     * 
116     */
117    public class Test3 implements StandardCBRApplication {
118    
119            Connector _connector;
120            CBRCaseBase _caseBase;
121            
122            /* (non-Javadoc)
123             * @see jcolibri.cbraplications.BasicCBRApplication#configure()
124             */
125            public void configure() throws ExecutionException{
126                    try{
127                    _connector = new DataBaseConnector();
128                    _connector.initFromXMLfile(jcolibri.util.FileIO.findFile("jcolibri/test/test3/databaseconfig.xml"));
129                    _caseBase  = new LinealCaseBase();
130                    } catch (Exception e){
131                            throw new ExecutionException(e);
132                    }
133            }
134    
135            
136            /* (non-Javadoc)
137             * @see jcolibri.cbraplications.BasicCBRApplication#preCycle()
138             */
139            public CBRCaseBase preCycle() throws ExecutionException {
140                    _caseBase.init(_connector);     
141                    for(jcolibri.cbrcore.CBRCase c: _caseBase.getCases())
142                            System.out.println(c);
143                    return _caseBase;
144            }
145            
146            /* (non-Javadoc)
147             * @see jcolibri.cbraplications.BasicCBRApplication#cycle()
148             */
149            public void cycle(CBRQuery query) throws ExecutionException 
150            {               
151                    /********* NumericSim Retrieval **********/
152                    
153                    NNConfig simConfig = new NNConfig();
154                    simConfig.setDescriptionSimFunction(new Average());
155                    simConfig.addMapping(new Attribute("Accommodation", TravelDescription.class), new Equal());
156                    Attribute duration = new Attribute("Duration", TravelDescription.class);
157                    simConfig.addMapping(duration, new Interval(31));
158                    simConfig.setWeight(duration, 0.5);
159                    simConfig.addMapping(new Attribute("HolidayType", TravelDescription.class), new Equal());
160                    simConfig.addMapping(new Attribute("NumberOfPersons", TravelDescription.class), new Equal());
161                    simConfig.addMapping(new Attribute("Price", TravelDescription.class), new Interval(4000));
162                    
163                    simConfig.addMapping(new Attribute("Region",   TravelDescription.class), new Average());
164                    simConfig.addMapping(new Attribute("region",   Region.class), new Equal());
165                    simConfig.addMapping(new Attribute("city",     Region.class), new Equal());
166                    simConfig.addMapping(new Attribute("airport",  Region.class), new Equal());
167                    simConfig.addMapping(new Attribute("currency", Region.class), new Equal());
168    
169                    
170                    System.out.println("Query:");
171                    System.out.println(query);
172                    System.out.println();
173                    
174                    
175                    /********* Execute NN ************/
176                    Collection<RetrievalResult> eval = NNScoringMethod.evaluateSimilarity(_caseBase.getCases(), query, simConfig);
177                    
178                    /********* Select cases **********/
179                    Collection<CBRCase> selectedcases = SelectCases.selectTopK(eval, 1);
180                    
181                    /********* Reuse **********/
182                    
183                    //Combine query description with cases solutions, obtaining a list of new cases.
184                    Collection<CBRCase> newcases = CombineQueryAndCasesMethod.combine(query, selectedcases);
185                    System.out.println("Combined cases");
186                    for(jcolibri.cbrcore.CBRCase c: newcases)
187                            System.out.println(c);
188                    
189                    /********* Revise **********/
190                    // Lets store only the best case
191                    CBRCase bestCase = newcases.iterator().next();
192                    
193                    // Define new ids for the compound attributes
194                    HashMap<Attribute, Object> componentsKeys = new HashMap<Attribute,Object>();
195                    componentsKeys.put(new Attribute("caseId",TravelDescription.class), "test3id"); 
196                    componentsKeys.put(new Attribute("id",Region.class), 7);        
197                    jcolibri.method.revise.DefineNewIdsMethod.defineNewIdsMethod(bestCase, componentsKeys);
198                    
199                    System.out.println("Cases with new Id");
200                    System.out.println(bestCase);
201                    
202                    /********* Retain **********/
203                    
204                    // Uncomment next line to store cases into persistence
205                    //jcolibri.method.retain.StoreCasesMethod.storeCase(_caseBase, bestCase);
206            }
207    
208            /* (non-Javadoc)
209             * @see jcolibri.cbraplications.BasicCBRApplication#postCycle()
210             */
211            public void postCycle() throws ExecutionException {
212                    this._caseBase.close();
213    
214            }
215    
216            /**
217             * @param args
218             */
219            public static void main(String[] args) {
220                    // Launch DDBB manager
221                    jcolibri.test.database.HSQLDBserver.init();
222    
223                    Test3 test3 = new Test3();
224                    try {
225                            test3.configure();
226                            test3.preCycle();
227                            
228                            //BufferedReader reader  = new BufferedReader(new InputStreamReader(System.in));                        
229                            //do
230                            //{     
231                            
232                            /********* Query Definition **********/
233                            TravelDescription queryDesc = new TravelDescription();
234                            queryDesc.setAccommodation(TravelDescription.AccommodationTypes.ThreeStars);
235                            queryDesc.setDuration(7);
236                            queryDesc.setHolidayType("Recreation");
237                            queryDesc.setNumberOfPersons(2);
238                            queryDesc.setPrice(700);
239                            
240                            Region region = new Region();
241                            region.setRegion("Bulgaria");
242                            region.setCity("Sofia");
243                            region.setCurrency("Euro");
244                            region.setAirport("airport");
245                            queryDesc.setRegion(region);
246                            
247                            CBRQuery query = new CBRQuery();
248                            query.setDescription(queryDesc);
249                            
250                            test3.cycle(query);
251                            
252                            //      System.out.println("Cycle finished. Type exit to idem");
253                            //}while(!reader.readLine().equals("exit"));
254                            
255                            test3.postCycle();
256                            
257                            //Shutdown DDBB manager
258                            jcolibri.test.database.HSQLDBserver.shutDown();
259    
260                    } catch (ExecutionException e) {
261                            System.out.println(e.getMessage());
262                            e.printStackTrace();
263                    } catch (Exception e) {
264                            // TODO Auto-generated catch block
265                            e.printStackTrace();
266                    }
267            }
268    
269    }