001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package org.outerj.daisy.repository.serverimpl.query.facets;
017:
018: import java.util.ArrayList;
019: import java.util.List;
020: import java.util.Locale;
021: import java.util.SortedMap;
022:
023: import org.apache.commons.logging.Log;
024: import org.outerj.daisy.query.model.ValueExpr;
025: import org.outerj.daisy.repository.HierarchyPath;
026: import org.outerj.daisy.repository.query.FacetConf;
027: import org.outerj.daisy.repository.serverimpl.query.Formatter;
028:
029: class DummyFacetSampler extends AbstractFacetSampler {
030: public DummyFacetSampler(FacetConf facetConf, Locale locale,
031: Log logger) {
032: super (facetConf, locale, logger);
033: }
034:
035: // This is O(nm) where n is the amount of entries and (m) is the depth of
036: // the hierarchy
037: public void regroup(SortedMap<Object, CountGroup> countGroups) {
038: if (countGroups.firstKey() instanceof HierarchyPath) {
039: int minDepth = Integer.MAX_VALUE;
040: int maxDepth = 1;
041: for (Object key : countGroups.keySet()) {
042: minDepth = Math.min(minDepth, ((HierarchyPath) key)
043: .length());
044: maxDepth = Math.max(maxDepth, ((HierarchyPath) key)
045: .length());
046: }
047:
048: hierarchyRegroup(countGroups, maxDepth, minDepth);
049: }
050: }
051:
052: private void hierarchyRegroup(SortedMap<Object, CountGroup> groups,
053: int maxDepth, int minDepth) {
054: int diffDepth = -1;
055: if (maxDepth > minDepth) {
056: diffDepth = minDepth - 1;
057: } else if (maxDepth == minDepth) {
058: boolean foundDiff = false;
059: diffDepth = 0;
060: Object[] elements1 = ((HierarchyPath) groups.firstKey())
061: .getElements();
062: Object[] elements2 = ((HierarchyPath) groups.lastKey())
063: .getElements();
064: while (diffDepth < maxDepth && !foundDiff
065: && diffDepth < elements1.length
066: && diffDepth < elements2.length) {
067: foundDiff = !(elements1[diffDepth]
068: .equals(elements2[diffDepth]));
069: diffDepth++;
070: }
071: diffDepth--;
072: }
073:
074: if (diffDepth >= 0 && groups.size() > 1) {
075: if (!((HierarchyPath) groups.firstKey()).getElements()[diffDepth]
076: .equals(((HierarchyPath) groups.lastKey())
077: .getElements()[diffDepth])) {
078:
079: // create a list of subMaps. Each subMap will then be merged into one element.
080: List<SortedMap<Object, CountGroup>> subMaps = new ArrayList<SortedMap<Object, CountGroup>>();
081: HierarchyPath previousPath = (HierarchyPath) groups
082: .firstKey();
083: for (Object key : groups.keySet()) {
084: HierarchyPath path = (HierarchyPath) key;
085: if (!path.getElements()[diffDepth]
086: .equals(previousPath.getElements()[diffDepth])) {
087: if (subMaps.size() < 1)
088: subMaps.add(groups.headMap(key));
089: else
090: subMaps.add(groups
091: .subMap(previousPath, key));
092: previousPath = path;
093: }
094: }
095: // add the last subMap
096: subMaps.add(groups.tailMap(previousPath));
097:
098: for (SortedMap<Object, CountGroup> subMap : subMaps) {
099: CountGroup.merge(subMap);
100: }
101: } else {
102: // find the shortest(there should be only one) & 2nd shortest path
103: HierarchyPath shorty = null;
104: HierarchyPath shortysNeighbour = null;
105: int newMin = maxDepth;
106: for (Object key : groups.keySet()) {
107: HierarchyPath path = (HierarchyPath) key;
108: if (shorty != null && shortysNeighbour == null)
109: shortysNeighbour = path;
110:
111: if (path.length() == minDepth)
112: shorty = path;
113: else if (path.length() > minDepth)
114: newMin = Math.min(path.length(), newMin);
115: }
116:
117: if (shorty != null) {
118: if (shortysNeighbour != null)
119: hierarchyRegroup(groups
120: .tailMap(shortysNeighbour), maxDepth,
121: newMin);
122: else
123: hierarchyRegroup(groups.headMap(shorty),
124: maxDepth, newMin);
125: }
126: }
127: }
128: }
129:
130: public String createUserFormat(CountGroup g, ValueExpr valueExpr,
131: Formatter valueFormatter) {
132: String format;
133: if (!g.getMin().equals(g.getMax())
134: && g.getMin() instanceof HierarchyPath)
135: format = createUserPath((HierarchyPath) g.getMin(),
136: (HierarchyPath) g.getMax(), valueExpr,
137: valueFormatter);
138: else
139: format = valueFormatter.format(valueExpr, g.getMin());
140:
141: return format;
142: }
143:
144: @Override
145: protected String createQueryFormat(CountGroup g,
146: ValueExpr valueExpr, Formatter queryFormatter) {
147: String format;
148: if (!g.getMin().equals(g.getMax())
149: && g.getMin() instanceof HierarchyPath) {
150: HierarchyPath shorty = findShortestPath(g);
151: format = queryFormatter.format(valueExpr, shorty);
152: format += " OR "
153: + valueExpr.getExpression()
154: + " matchesPath('"
155: + createPath((HierarchyPath) g.getMin(),
156: (HierarchyPath) g.getMax(), valueExpr,
157: queryFormatter) + "')";
158: } else {
159: format = queryFormatter.format(valueExpr, g.getMin());
160: }
161: return format;
162: }
163:
164: private String createPath(HierarchyPath path1, HierarchyPath path2,
165: ValueExpr valueExpr, Formatter formatter) {
166: StringBuilder path = new StringBuilder();
167: Object[] elements1 = path1.getElements();
168: Object[] elements2 = path2.getElements();
169: int end = Math.min(elements1.length, elements2.length);
170: int i = 0;
171: while (i < end && elements1[i].equals(elements2[i])) {
172: path.append("/");
173: String formatted = formatter
174: .format(valueExpr, elements1[i]);
175: path.append(formatted.replaceAll("'", ""));
176: i++;
177: }
178: path.append("/**");
179:
180: return path.toString();
181: }
182:
183: private String createUserPath(HierarchyPath path1,
184: HierarchyPath path2, ValueExpr valueExpr,
185: Formatter formatter) {
186: StringBuilder path = new StringBuilder();
187: Object[] elements1 = path1.getElements();
188: Object[] elements2 = path2.getElements();
189: int end = Math.min(elements1.length, elements2.length);
190: int i = 0;
191: while (i < end && elements1[i].equals(elements2[i])) {
192: path.append("/");
193: String formatted = formatter
194: .format(valueExpr, elements1[i]);
195: if (formatted != null)
196: path.append(formatted.replaceAll("'", ""));
197: i++;
198: }
199: path.append("/...");
200:
201: return path.toString();
202: }
203:
204: private HierarchyPath findShortestPath(CountGroup g) {
205: HierarchyPath path1 = (HierarchyPath) g.getMin();
206: HierarchyPath path2 = (HierarchyPath) g.getMax();
207: return path1.length() <= path2.length() ? path1 : path2;
208: }
209: }
|