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    }