KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > outerj > daisy > frontend > FacetedBrowserApple


1 /*
2  * Copyright 2004 Outerthought bvba and Schaubroeck nv
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.outerj.daisy.frontend;
17
18 import org.outerj.daisy.frontend.util.AbstractDaisyApple;
19 import org.outerj.daisy.frontend.util.XmlObjectXMLizable;
20 import org.outerj.daisy.frontend.components.siteconf.SiteConf;
21 import org.outerj.daisy.repository.Repository;
22 import org.outerj.daisy.repository.query.FacetConf;
23 import org.outerj.daisy.repository.query.QueryHelper;
24 import org.outerj.daisy.xmlutil.LocalSAXParserFactory;
25 import org.apache.cocoon.components.flow.apples.StatelessAppleController;
26 import org.apache.cocoon.components.flow.apples.AppleRequest;
27 import org.apache.cocoon.components.flow.apples.AppleResponse;
28 import org.apache.cocoon.environment.Request;
29 import org.apache.avalon.framework.service.Serviceable;
30 import org.apache.avalon.framework.service.ServiceManager;
31 import org.apache.avalon.framework.service.ServiceException;
32 import org.apache.xmlbeans.XmlOptions;
33 import org.apache.xmlbeans.XmlException;
34 import org.apache.xmlbeans.XmlError;
35 import org.outerx.daisy.x10.FacetedQueryResultDocument;
36 import org.outerx.daisy.x10Facetednavdef.FacetedNavigationDefinitionDocument;
37
38 import java.util.*;
39 import java.io.File JavaDoc;
40
41 public class FacetedBrowserApple extends AbstractDaisyApple implements StatelessAppleController, Serviceable {
42     private ServiceManager serviceManager;
43
44     public void service(ServiceManager serviceManager) throws ServiceException {
45         this.serviceManager = serviceManager;
46     }
47
48     protected void processInternal(AppleRequest appleRequest, AppleResponse appleResponse) throws Exception JavaDoc {
49         Request request = appleRequest.getCocoonRequest();
50         Locale locale = WikiHelper.getLocale(request);
51         SiteConf siteConf = WikiHelper.getSiteConf(request);
52         Repository repository = WikiHelper.getRepository(request, serviceManager);
53
54         String JavaDoc definitionName = appleRequest.getSitemapParameter("definitionName");
55         FacetedNavigationDefinition facetedNavDef = loadFacetDefinitions(definitionName, siteConf);
56         FacetDefinition[] facetDefs = facetedNavDef.getFacetDefinitions();
57
58         Filter[] filters = parseFilters(request, facetedNavDef);
59         Condition[] conditions = filtersToConditions(filters, facetedNavDef);
60         boolean limitToSiteCollection = RequestUtil.getBooleanParameter(request, "limitToSiteCollection", facetedNavDef.getLimitToSiteCollection());
61         boolean limitToSiteVariant = RequestUtil.getBooleanParameter(request, "limitToSiteVariant", facetedNavDef.getLimitToSiteVariant());
62         String JavaDoc orderBy = RequestUtil.getStringParameter(request, "orderBy", "name ASC");
63
64         StringBuffer JavaDoc query = new StringBuffer JavaDoc();
65         query.append("select ");
66         String JavaDoc[] auxiliaryFields = facetedNavDef.getAuxiliaryFields();
67         for (int i = 0; i < auxiliaryFields.length; i++) {
68             if (i > 0)
69                 query.append(", ");
70             query.append(auxiliaryFields[i]);
71         }
72         for (int i = 0; i < facetDefs.length; i++) {
73             if (i > 0 || auxiliaryFields.length > 0)
74                 query.append(", ");
75             query.append(facetDefs[i].getExpression());
76         }
77         query.append(" where ");
78         if (conditions.length == 0) {
79             query.append("true");
80         } else {
81             for (int i = 0; i < conditions.length; i++) {
82                 if (i > 0)
83                     query.append(" and ");
84                 query.append(conditions[i].toString());
85             }
86         }
87         if (limitToSiteCollection) {
88             String JavaDoc collectionName = repository.getCollectionManager().getCollection(siteConf.getCollectionId(), false).getName();
89             query.append(" and InCollection(");
90             query.append(QueryHelper.formatString(collectionName));
91             query.append(")");
92         }
93         if (limitToSiteVariant) {
94             String JavaDoc branchName = repository.getVariantManager().getBranch(siteConf.getBranchId(), false).getName();
95             String JavaDoc languageName = repository.getVariantManager().getLanguage(siteConf.getLanguageId(), false).getName();
96             query.append(" and branch = ");
97             query.append(QueryHelper.formatString(branchName));
98             query.append(" and language = ");
99             query.append(QueryHelper.formatString(languageName));
100         }
101         if (facetedNavDef.getDefaultConditions() != null) {
102             query.append(" and ( ").append(facetedNavDef.getDefaultConditions()).append(" ) ");
103         }
104         query.append(" order by ").append(orderBy);
105
106         FacetConf[] facetConfs = parseFacetConfs(request, facetedNavDef);
107
108         int chunkOffset = RequestUtil.getIntParameter(request, "chunkOffset", 1);
109         int chunkLength = RequestUtil.getIntParameter(request, "chunkLength", 10);
110
111         FacetedQueryResultDocument result = repository.getQueryManager().performFacetedQuery(query.toString(), facetConfs, chunkOffset, chunkLength, locale);
112
113         HashMap viewData = new HashMap();
114         viewData.put("facetedQueryResult", new XmlObjectXMLizable(result));
115         viewData.put("filters", filters);
116         viewData.put("facetedNavDef", facetedNavDef);
117         viewData.put("facetConfs", facetConfs);
118         viewData.put("limitToSiteCollection", String.valueOf(limitToSiteCollection));
119         viewData.put("limitToSiteVariant", String.valueOf(limitToSiteVariant));
120         viewData.put("orderBy", orderBy);
121         viewData.put("pageContext", new PageContext(getMountPoint(), siteConf, repository, getLayoutType(), getSkin(), getContext()));
122         viewData.put("path", getMountPoint() + "/" + siteConf.getName() + "/facetedBrowser/" + definitionName);
123         appleResponse.sendPage("FacetedBrowserPipe", viewData);
124     }
125
126     private FacetConf[] parseFacetConfs(Request request, FacetedNavigationDefinition facetedNavDef) throws Exception JavaDoc {
127         FacetDefinition[] facetDefs = facetedNavDef.getFacetDefinitions();
128         String JavaDoc[] auxiliaryFields = facetedNavDef.getAuxiliaryFields();
129         FacetConf[] facetConfs = new FacetConf[auxiliaryFields.length + facetDefs.length];
130         for (int i = 0; i < auxiliaryFields.length; i++) {
131             facetConfs[i] = new FacetConf(false);
132         }
133
134         for (int i = 0; i < facetDefs.length; i++) {
135             String JavaDoc prefix = "facetConf." + (i + 1) + ".";
136             int maxValues = RequestUtil.getIntParameter(request, prefix + "maxValues", 10);
137             boolean sortOnValue = RequestUtil.getBooleanParameter(request, prefix + "sortOnValue", true);
138             boolean sortAscending = RequestUtil.getBooleanParameter(request, prefix + "sortAscending", true);
139             facetConfs[auxiliaryFields.length + i] = new FacetConf(maxValues, sortOnValue, sortAscending);
140         }
141
142         return facetConfs;
143     }
144
145     private Filter[] parseFilters(Request request, FacetedNavigationDefinition facetedNavDef) throws Exception JavaDoc {
146         List filters = new ArrayList();
147         int i = 1;
148         while (true) {
149             String JavaDoc facetIndex = "filter." + i;
150             String JavaDoc facetName = request.getParameter(facetIndex + ".facetName");
151             if (facetName == null)
152                 break;
153             facetedNavDef.getFacetDefinition(facetName);
154             String JavaDoc queryValue = RequestUtil.getStringParameter(request, facetIndex + ".queryValue");
155             String JavaDoc displayValue = RequestUtil.getStringParameter(request, facetIndex + ".displayValue");
156             String JavaDoc operatorKey = RequestUtil.getStringParameter(request, facetIndex + ".operator");
157             Operator operator = (Operator)operators.get(operatorKey);
158             if (operator == null)
159                 throw new Exception JavaDoc("Non-existing operator: " + operatorKey);
160
161             Filter filter = new Filter(facetName, operator, queryValue, displayValue);
162             filters.add(filter);
163             i++;
164         }
165         return (Filter[])filters.toArray(new Filter[filters.size()]);
166     }
167
168     public static class Filter {
169         private String JavaDoc facetName;
170         private Operator operator;
171         private String JavaDoc queryValue;
172         private String JavaDoc displayValue;
173
174         public Filter(String JavaDoc facetName, Operator operator, String JavaDoc queryValue, String JavaDoc displayValue) {
175             this.facetName = facetName;
176             this.operator = operator;
177             this.queryValue = queryValue;
178             this.displayValue = displayValue;
179         }
180
181         public String JavaDoc getFacetName() {
182             return facetName;
183         }
184
185         public Operator getOperator() {
186             return operator;
187         }
188
189         public String JavaDoc getQueryValue() {
190             return queryValue;
191         }
192
193         public String JavaDoc getDisplayValue() {
194             return displayValue;
195         }
196     }
197
198     private Condition[] filtersToConditions(Filter[] filters, FacetedNavigationDefinition facetedNavDef) {
199         Map conditions = new HashMap();
200
201         for (int i = 0; i < filters.length; i++) {
202             Condition condition = (Condition)conditions.get(filters[i].getFacetName());
203             if (condition == null) {
204                 FacetDefinition facetDef = facetedNavDef.getFacetDefinition(filters[i].getFacetName());
205                 condition = new Condition(facetDef.getExpression(), Operator.EQUALS, filters[i].getQueryValue());
206                 conditions.put(filters[i].getFacetName(), condition);
207             } else {
208                 condition.addValue(filters[i].getQueryValue());
209             }
210         }
211
212         return (Condition[])conditions.values().toArray(new Condition[conditions.size()]);
213     }
214
215     public static class Condition {
216         private String JavaDoc identifier;
217         private String JavaDoc value;
218         private List values;
219         private Operator operator;
220
221         public Condition(String JavaDoc identifier, Operator operator, String JavaDoc value) {
222             this.identifier = identifier;
223             this.operator = operator;
224             this.value = value;
225         }
226
227         public void addValue(String JavaDoc value) {
228             if (values == null) {
229                 values = new ArrayList();
230                 values.add(this.value);
231                 this.value = null;
232             }
233             values.add(value);
234         }
235
236         public String JavaDoc toString() {
237             if (values != null) {
238                 StringBuffer JavaDoc result = new StringBuffer JavaDoc();
239                 result.append(identifier);
240                 result.append(" has all(");
241                 for (int i = 0; i < values.size(); i++) {
242                     if (i > 0)
243                         result.append(", ");
244                     result.append(values.get(i));
245                 }
246                 result.append(")");
247                 return result.toString();
248             } else {
249                 return identifier + " " + operator.getSyntax() + " " + value;
250             }
251         }
252     }
253
254     private static Map operators = new HashMap();
255     static {
256         operators.put(Operator.EQUALS.getKey(), Operator.EQUALS);
257         operators.put(Operator.LIKE.getKey(), Operator.LIKE);
258     }
259
260     public static class Operator {
261         private final String JavaDoc key;
262         private final String JavaDoc syntax;
263
264         private Operator(String JavaDoc key, String JavaDoc syntax) {
265             this.key = key;
266             this.syntax = syntax;
267         }
268
269         public String JavaDoc getKey() {
270             return key;
271         }
272
273         public String JavaDoc getSyntax() {
274             return syntax;
275         }
276
277         public String JavaDoc toString() {
278             return key;
279         }
280
281         public static final Operator EQUALS = new Operator("equals", "=");
282         public static final Operator LIKE = new Operator("like", "like");
283     }
284
285     private FacetedNavigationDefinition loadFacetDefinitions(String JavaDoc name, SiteConf siteConf) throws Exception JavaDoc {
286         // TODO NEED CACHING HERE so we don't need to load/parse the definitions on each request
287
File JavaDoc file = new File JavaDoc(new File JavaDoc(siteConf.getDirectory(), "facetednavdefs"), name + ".xml");
288         if (!file.exists())
289             throw new Exception JavaDoc("Faceted navigation definition does not exist: \"" + name + "\"");
290
291         List errors = new ArrayList();
292         XmlOptions xmlOptions = new XmlOptions();
293         xmlOptions.setLoadUseXMLReader(LocalSAXParserFactory.newXmlReader());
294         xmlOptions.setErrorListener(errors);
295         xmlOptions.setLoadLineNumbers();
296         boolean valid = true;
297         FacetedNavigationDefinitionDocument facetedNavDefDoc;
298         try {
299             facetedNavDefDoc = FacetedNavigationDefinitionDocument.Factory.parse(file, xmlOptions);
300
301             xmlOptions = new XmlOptions();
302             xmlOptions.setErrorListener(errors);
303             valid = facetedNavDefDoc.validate(xmlOptions);
304         } catch (XmlException e) {
305             throw new Exception JavaDoc("Error loading faceted navigation definition: " + formatXmlErrors(errors), e);
306         } catch (Exception JavaDoc e) {
307             throw new Exception JavaDoc("Error loading faceted navigation definition.", e);
308         }
309
310         if (!valid)
311             throw new Exception JavaDoc("Error validating faceted navigation definition: " + formatXmlErrors(errors));
312
313         HashSet names = new HashSet();
314         FacetedNavigationDefinitionDocument.FacetedNavigationDefinition.Facets.Facet[] facetDefsXml = facetedNavDefDoc.getFacetedNavigationDefinition().getFacets().getFacetArray();
315         FacetDefinition[] facetDefs = new FacetDefinition[facetDefsXml.length];
316         for (int i = 0; i < facetDefsXml.length; i++) {
317             String JavaDoc expression = facetDefsXml[i].getExpression();
318             String JavaDoc facetName = makeFacetName(expression);
319             if (names.contains(facetName)) {
320                 String JavaDoc baseFacetName = facetName;
321                 int s = 1;
322                 while (names.contains(facetName)) {
323                     facetName = baseFacetName + "-" + s;
324                     s++;
325                 }
326             }
327             names.add(facetName);
328             facetDefs[i] = new FacetDefinition(facetName, facetDefsXml[i].getExpression());
329         }
330
331         FacetedNavigationDefinitionDocument.FacetedNavigationDefinition.Options options = facetedNavDefDoc.getFacetedNavigationDefinition().getOptions();
332         return new FacetedNavigationDefinition(facetDefs, new String JavaDoc[] {"name", "summary"},
333                 options.getLimitToSiteCollection(), options.getLimitToSiteVariant(), options.getDefaultConditions());
334     }
335
336     private String JavaDoc formatXmlErrors(Collection xmlErrors) {
337         StringBuffer JavaDoc message = new StringBuffer JavaDoc();
338         Iterator errorsIt = xmlErrors.iterator();
339         while (errorsIt.hasNext()) {
340             XmlError error = (XmlError)errorsIt.next();
341             if (message.length() > 0)
342                 message.append("\n");
343             message.append(error.getMessage());
344         }
345         return message.toString();
346     }
347
348     private String JavaDoc makeFacetName(String JavaDoc expression) {
349         StringBuffer JavaDoc name = new StringBuffer JavaDoc(expression.length());
350         for (int i = 0; i < expression.length(); i++) {
351             char c = expression.charAt(i);
352             if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
353                 name.append(c);
354         }
355         return name.toString();
356     }
357
358     public static class FacetedNavigationDefinition {
359         private FacetDefinition[] facetDefinitions;
360         private Map facetsByName = new HashMap();
361         private String JavaDoc[] auxiliaryFields;
362         private boolean limitToSiteCollection;
363         private boolean limitToSiteVariant;
364         private String JavaDoc defaultConditions;
365
366         public FacetedNavigationDefinition(FacetDefinition[] facetDefinitions, String JavaDoc[] auxiliaryFields,
367                 boolean limitToSiteCollection, boolean limitToSiteVariant, String JavaDoc defaultConditions) {
368             this.facetDefinitions = facetDefinitions;
369             for (int i = 0; i < facetDefinitions.length; i++) {
370                 if (facetsByName.containsKey(facetDefinitions[i].getName()))
371                     throw new RuntimeException JavaDoc("Duplicate facet name: " + facetDefinitions[i].getName());
372                 facetsByName.put(facetDefinitions[i].getName(), facetDefinitions[i]);
373             }
374             this.auxiliaryFields = auxiliaryFields;
375             this.limitToSiteCollection = limitToSiteCollection;
376             this.limitToSiteVariant = limitToSiteVariant;
377             this.defaultConditions = defaultConditions;
378         }
379
380         public FacetDefinition[] getFacetDefinitions() {
381             return facetDefinitions;
382         }
383
384         public FacetDefinition getFacetDefinition(String JavaDoc name) {
385             FacetDefinition facetDefinition = (FacetDefinition)facetsByName.get(name);
386             if (facetDefinition == null)
387                 throw new RuntimeException JavaDoc("Non-existing facet name: " + name);
388             return facetDefinition;
389         }
390
391         public String JavaDoc[] getAuxiliaryFields() {
392             return auxiliaryFields;
393         }
394
395         public boolean getLimitToSiteCollection() {
396             return limitToSiteCollection;
397         }
398
399         public boolean getLimitToSiteVariant() {
400             return limitToSiteVariant;
401         }
402
403         public String JavaDoc getDefaultConditions() {
404             return defaultConditions;
405         }
406     }
407
408     public static class FacetDefinition {
409         private String JavaDoc name;
410         private String JavaDoc expression;
411
412         public FacetDefinition(String JavaDoc name, String JavaDoc identifier) {
413             this.name = name;
414             this.expression = identifier;
415         }
416
417         public String JavaDoc getName() {
418             return name;
419         }
420
421         public String JavaDoc getExpression() {
422             return expression;
423         }
424     }
425 }
426
Popular Tags