001 /** 002 * Houses3.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 * 23/10/2007 008 */ 009 package jcolibri.test.recommenders.rec3; 010 011 import java.util.ArrayList; 012 import java.util.Collection; 013 import java.util.HashMap; 014 import java.util.Map; 015 016 import jcolibri.casebase.LinealCaseBase; 017 import jcolibri.cbraplications.StandardCBRApplication; 018 import jcolibri.cbrcore.Attribute; 019 import jcolibri.cbrcore.CBRCase; 020 import jcolibri.cbrcore.CBRCaseBase; 021 import jcolibri.cbrcore.CBRQuery; 022 import jcolibri.cbrcore.Connector; 023 import jcolibri.connector.PlainTextConnector; 024 import jcolibri.exception.ExecutionException; 025 import jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod; 026 import jcolibri.extensions.recommendation.casesDisplay.UserChoice; 027 import jcolibri.extensions.recommendation.conditionals.BuyOrQuit; 028 import jcolibri.extensions.recommendation.conditionals.ContinueOrFinish; 029 import jcolibri.extensions.recommendation.conditionals.DisplayCasesIfNumber; 030 import jcolibri.method.gui.formFilling.ObtainQueryWithFormMethod; 031 import jcolibri.method.retrieve.FilterBasedRetrieval.FilterBasedRetrievalMethod; 032 import jcolibri.method.retrieve.FilterBasedRetrieval.FilterConfig; 033 import jcolibri.method.retrieve.FilterBasedRetrieval.predicates.Equal; 034 import jcolibri.method.retrieve.FilterBasedRetrieval.predicates.QueryLessOrEqual; 035 import jcolibri.method.retrieve.FilterBasedRetrieval.predicates.QueryMoreOrEqual; 036 import jcolibri.test.recommenders.housesData.HouseDescription; 037 038 /** 039 * Conversational (type B) flats recommender using form-filling and Filter-Based retrieval. 040 * <br> 041 * This recommender obtains the user preferences through a form. Then, it performs the 042 * retrieval filtering the items that obbey the user preferences. If the retrieval set 043 * is small enough, items are shown to the user. If the retrieval set is too big or 044 * the user does not find the desired item, the system presents again a form to modify 045 * the user requirements. The form has some initial values and custom labels. 046 * <br>Summary: 047 * <ul> 048 * <li>Type: Conversational B 049 * <li>Case base: houses 050 * <li>One off Preference Elicitation: Form Filling with initial values and custom labels 051 * <li>Retrieval: Filter 052 * <li>Display Condition: number of cases (showing messages) 053 * <li>Display: In table with "Edit Query" enabled 054 * <li>Iterated Preference Elicitation: Form Filling with initial values and custom labels 055 * </ul> 056 * This recommender implements the following template:<br> 057 * <center><img src="../Template3_Cycle.jpg"/></center> 058 * 059 * <br>Read the documentation of the recommenders extension for details about templates 060 * and recommender strategies: {@link jcolibri.extensions.recommendation} 061 * 062 * @see jcolibri.method.gui.formFilling.ObtainQueryWithFormMethod 063 * @see jcolibri.method.retrieve.FilterBasedRetrieval.FilterBasedRetrievalMethod 064 * @see jcolibri.extensions.recommendation.conditionals.DisplayCasesIfNumber 065 * @see jcolibri.extensions.recommendation.casesDisplay.DisplayCasesTableMethod 066 * 067 * @author Juan A. Recio-Garcia 068 * @author Developed at University College Cork (Ireland) in collaboration with Derek Bridge. 069 * @version 1.0 070 * 071 */ 072 public class Houses3 implements StandardCBRApplication 073 { 074 /** Connector object */ 075 Connector _connector; 076 /** CaseBase object */ 077 CBRCaseBase _caseBase; 078 079 /** Configuration object for Form Filling */ 080 Map<Attribute,String> labels; 081 /** Configuration object for Form Filling */ 082 ArrayList<Attribute> hiddenAtts; 083 /** Configuration object for Filter Based retrieval*/ 084 FilterConfig filterConfig; 085 086 public void configure() throws ExecutionException 087 { 088 // Create a data base connector 089 _connector = new PlainTextConnector(); 090 // Init the ddbb connector with the config file 091 _connector.initFromXMLfile(jcolibri.util.FileIO 092 .findFile("jcolibri/test/recommenders/housesData/plaintextconfig.xml")); 093 // Create a Lineal case base for in-memory organization 094 _caseBase = new LinealCaseBase(); 095 096 // Configure Form Filling 097 hiddenAtts = new ArrayList<Attribute>(); 098 labels = new HashMap<Attribute,String>(); 099 labels.put(new Attribute("beds", HouseDescription.class), "Min bedrooms"); 100 labels.put(new Attribute("price", HouseDescription.class), "Max price"); 101 labels.put(new Attribute("baths", HouseDescription.class), "Min bahtrooms"); 102 103 //Configure the Filter based retrieval 104 filterConfig = new FilterConfig(); 105 filterConfig.addPredicate(new Attribute("area", HouseDescription.class), new Equal()); 106 filterConfig.addPredicate(new Attribute("beds", HouseDescription.class), new QueryLessOrEqual()); 107 filterConfig.addPredicate(new Attribute("price", HouseDescription.class), new QueryMoreOrEqual()); 108 filterConfig.addPredicate(new Attribute("furnished", HouseDescription.class), new Equal()); 109 filterConfig.addPredicate(new Attribute("type", HouseDescription.class), new Equal()); 110 filterConfig.addPredicate(new Attribute("baths", HouseDescription.class), new QueryLessOrEqual()); 111 112 113 } 114 115 public void cycle(CBRQuery query) throws ExecutionException 116 { 117 // Obtain the query 118 ObtainQueryWithFormMethod.obtainQueryWithInitialValues(query,hiddenAtts,labels); 119 120 121 // Jump to the conversation cycle 122 sequence1(query); 123 } 124 125 126 public void sequence1(CBRQuery query) 127 { 128 // Retrieve using filter based retrieval 129 Collection<CBRCase> retrievedCases = FilterBasedRetrievalMethod.filterCases(_caseBase.getCases(), query, filterConfig); 130 131 // Display condition based on the number of cases. 132 if(DisplayCasesIfNumber.displayCases(50, 1, retrievedCases,true)) 133 sequence2(query, retrievedCases); 134 else 135 sequence3(query); 136 } 137 138 public void sequence2(CBRQuery query, Collection<CBRCase> retrievedCases) 139 { 140 // Display cases in table 141 UserChoice choice = DisplayCasesTableMethod.displayCasesInTableEditQuery(retrievedCases); 142 143 if(ContinueOrFinish.continueOrFinish(choice)) 144 sequence3(query); 145 else 146 sequence4(choice, retrievedCases); 147 } 148 149 public void sequence3(CBRQuery query) 150 { 151 // Refine query and back to the main sequence 152 ObtainQueryWithFormMethod.obtainQueryWithInitialValues(query,hiddenAtts,labels); 153 154 sequence1(query); 155 } 156 157 public void sequence4(UserChoice choice, Collection<CBRCase> retrievedCases) 158 { 159 if(BuyOrQuit.buyOrQuit(choice)) 160 System.out.println("Finish - User Buys: "+choice.getSelectedCase()); 161 162 else 163 System.out.println("Finish - User Quits"); 164 } 165 166 public void postCycle() throws ExecutionException 167 { 168 } 169 170 public CBRCaseBase preCycle() throws ExecutionException 171 { 172 // Load cases from connector into the case base 173 _caseBase.init(_connector); 174 // Print the cases 175 java.util.Collection<CBRCase> cases = _caseBase.getCases(); 176 for(CBRCase c: cases) 177 System.out.println(c); 178 return _caseBase; 179 } 180 181 public static void main(String[] args) { 182 StandardCBRApplication recommender = new Houses3(); 183 try 184 { 185 recommender.configure(); 186 187 recommender.preCycle(); 188 189 CBRQuery query = new CBRQuery(); 190 191 HouseDescription hd = new HouseDescription(); 192 hd.setArea(HouseDescription.Area.Hampstead); 193 hd.setBaths(1); 194 hd.setBeds(HouseDescription.Beds.two); 195 hd.setFurnished(true); 196 hd.setPrice(500); 197 hd.setType(HouseDescription.Type.Flat); 198 199 query.setDescription(hd); 200 201 recommender.cycle(query); 202 203 recommender.postCycle(); 204 205 //System.exit(0); 206 } catch (Exception e) 207 { 208 org.apache.commons.logging.LogFactory.getLog(Houses3.class).error(e); 209 210 } 211 212 213 } 214 215 }