001: package com.jofti.tree;
002:
003: import java.util.Map;
004:
005: import org.apache.commons.logging.Log;
006: import org.apache.commons.logging.LogFactory;
007:
008: import com.jofti.btree.BTOperations;
009: import com.jofti.exception.JoftiException;
010: import com.jofti.exception.PropertyNotIndexedException;
011: import com.jofti.manager.IndexManagerImpl;
012: import com.jofti.parser.CommonLexerTokenTypes;
013: import com.jofti.query.MatchInQuery;
014: import com.jofti.query.MatchNotQuery;
015: import com.jofti.query.MatchQuery;
016: import com.jofti.query.MatchRangeQuery;
017: import com.jofti.util.OpenHashMap;
018:
019: /**
020: * @author Steve Woodcock (steve@jofti.com)
021: *
022: */
023: public class TreeMatcherEngine extends AbstractMatchingEngine {
024:
025: private static Log log = LogFactory.getLog(IndexManagerImpl.class);
026:
027: protected Map performQuery(int operator, Class className,
028: Object nameSpace, String attribute, Object value,
029: TreeIndex index, Map namedParameters, Object alias)
030: throws JoftiException {
031: Map temp = null;
032:
033: switch (operator) {
034:
035: case CommonLexerTokenTypes.ASSIGNEQUAL:
036: Comparable comp = attributeValueParser.constructValue(
037: (String) value, index.introspector, className,
038: attribute, namedParameters);
039: temp = matchProperty(className, attribute, comp, alias,
040: index);
041:
042: break;
043: case CommonLexerTokenTypes.IS:
044: comp = attributeValueParser.constructForIsNot(
045: (String) value, namedParameters);
046: temp = matchIsProperty(new MatchQuery(className, attribute,
047: comp, alias), index);
048:
049: break;
050: case CommonLexerTokenTypes.GREATERTHAN:
051: ;
052: comp = attributeValueParser.constructValue((String) value,
053: index.introspector, className, attribute,
054: namedParameters);
055: temp = matchPropertyRange(className, attribute, comp, null,
056: false, alias, index);
057: break;
058: case CommonLexerTokenTypes.GREATERTHANOREQUALTO1:
059: ;
060: case CommonLexerTokenTypes.GREATERTHANOREQUALTO2:
061: comp = attributeValueParser.constructValue((String) value,
062: index.introspector, className, attribute,
063: namedParameters);
064: temp = matchPropertyRange(className, attribute, comp, null,
065: true, alias, index);
066: break;
067: case CommonLexerTokenTypes.LESSTHANOREQUALTO1:
068: ;
069: case CommonLexerTokenTypes.LESSTHANOREQUALTO2:
070: ;
071: comp = attributeValueParser.constructValue((String) value,
072: index.introspector, className, attribute,
073: namedParameters);
074: temp = matchPropertyRange(className, attribute, null, comp,
075: true, alias, index);
076: break;
077: case CommonLexerTokenTypes.LESSTHAN:
078: comp = attributeValueParser.constructValue((String) value,
079: index.introspector, className, attribute,
080: namedParameters);
081: temp = matchPropertyRange(className, attribute, null, comp,
082: false, alias, index);
083: break;
084: case CommonLexerTokenTypes.NOTEQUAL1:
085: ;
086: case CommonLexerTokenTypes.NOTEQUAL2:
087: comp = attributeValueParser.constructValue((String) value,
088: index.introspector, className, attribute,
089: namedParameters);
090: temp = matchNotProperty(new MatchNotQuery(className,
091: attribute, comp, alias), index);
092: break;
093: case CommonLexerTokenTypes.NOT:
094: comp = attributeValueParser.constructForIsNot(
095: (String) value, namedParameters);
096: temp = matchNotProperty(new MatchNotQuery(className,
097: attribute, comp, alias), index);
098: break;
099: case CommonLexerTokenTypes.LIKE:
100: Comparable[] tempVals = attributeValueParser.processVals(
101: (String) value, namedParameters);
102: temp = matchPropertyRange(className, attribute,
103: tempVals[0], tempVals[1], true, alias, index);
104: break;
105: case CommonLexerTokenTypes.IN:
106: tempVals = attributeValueParser.constructArrayValue(value,
107: index.introspector, className, attribute,
108: namedParameters);
109: temp = matchProperty(new MatchInQuery(className, attribute,
110: tempVals, alias), index);
111: break;
112:
113: default:
114: break;
115: }
116: return temp;
117: }
118:
119: public Map matchProperty(MatchQuery query, TreeIndex index)
120: throws JoftiException {
121: return matchProperty(query.className, query.propertyName,
122: query.value, query.alias, index);
123: }
124:
125: public Map matchProperty(final Class className,
126: final String attribute, final Comparable comp,
127: final Object alias, TreeIndex index) throws JoftiException {
128:
129: // we need to find the dimension from the name here
130:
131: int dimension = 0;
132: try {
133: if (comp == null) {
134: throw new JoftiException(
135: "null is not allowed in equals query use IS query");
136: }
137: if (attribute == null) {
138:
139: dimension = index.introspector.getDimension(comp
140: .getClass(), null);
141: } else {
142: dimension = index.introspector.getDimension(className,
143: attribute);
144: }
145: } catch (PropertyNotIndexedException e) {
146: //no property match found
147: return new OpenHashMap(1);
148: } catch (JoftiException e) {
149: throw e;
150: }
151:
152: //log.info("Looking for property " + propertyName + " with index " + dimension);
153:
154: return BTOperations.match(index.tree, comp, dimension, alias);
155:
156: }
157:
158: public Map matchIsProperty(MatchQuery query, TreeIndex index)
159: throws JoftiException {
160:
161: // we need to find the dimension from the name here
162:
163: int dimension = 0;
164: try {
165: if (query.getPropertyName() == null) {
166: dimension = index.introspector.getDimension(query
167: .getClassName(), null);
168: } else {
169: dimension = index.introspector.getDimension(query
170: .getClassName(), query.getPropertyName());
171: }
172: } catch (PropertyNotIndexedException e) {
173: //no property match found
174: return new OpenHashMap(1);
175: } catch (JoftiException e) {
176: throw e;
177: }
178:
179: //log.info("Looking for property " + propertyName + " with index " + dimension);
180:
181: return BTOperations.match(index.tree, wrapNull(null),
182: dimension, query.alias);
183:
184: }
185:
186: public Map matchProperty(MatchInQuery query, TreeIndex index)
187: throws JoftiException {
188:
189: // we need to find the dimension from the name here
190:
191: int dimension = 0;
192: Comparable[] values = query.getValues();
193: try {
194: if (values == null || values[0] == null) {
195: return new OpenHashMap(1);
196: }
197: if (query.getPropertyName() == null) {
198:
199: dimension = index.introspector.getDimension(values[0]
200: .getClass(), null);
201: } else {
202: dimension = index.introspector.getDimension(query
203: .getClassName(), query.getPropertyName());
204: }
205: } catch (PropertyNotIndexedException e) {
206: //no property match found
207: return new OpenHashMap(1);
208: } catch (JoftiException e) {
209: throw e;
210: }
211:
212: //log.info("Looking for property " + propertyName + " with index " + dimension);
213:
214: return BTOperations.match(index.tree, values, dimension,
215: query.alias);
216:
217: }
218:
219: public Map matchNotProperty(MatchNotQuery query, TreeIndex index)
220: throws JoftiException {
221:
222: // we need to find the dimension from the name here
223:
224: int dimension = 0;
225: try {
226: if (query.getPropertyName() == null) {
227: dimension = index.introspector.getDimension(query
228: .getValue().getClass(), null);
229: } else {
230: dimension = index.introspector.getDimension(query
231: .getClassName(), query.getPropertyName());
232: }
233: } catch (PropertyNotIndexedException e) {
234: //no property match found
235: return new OpenHashMap(1);
236: } catch (JoftiException e) {
237: throw e;
238: }
239:
240: //log.info("Looking for property " + propertyName + " with index " + dimension);
241:
242: return BTOperations.notEqual(index.tree, wrapNull(query
243: .getValue()), dimension, query.alias);
244:
245: }
246:
247: /**
248: * @param cache
249: * @param col
250: * @return
251: * @throws JoftiException
252: */
253:
254: public Map matchPropertyRange(MatchRangeQuery query, TreeIndex index)
255: throws JoftiException {
256: return matchPropertyRange(query.getClassName(), query
257: .getPropertyName(), query.getStartValue(), query
258: .getEndValue(), query.isInclusive(), query.alias, index);
259:
260: }
261:
262: public Map matchPropertyRange(Class className, String attribute,
263: Comparable startValue, Comparable endValue,
264: boolean inclusive, Object alias, TreeIndex index)
265: throws JoftiException {
266: // we need to find the dimension from the name here
267: // we need to find the dimension from the name here
268: if (startValue != null && endValue != null) {
269: if (!((startValue.getClass().equals(endValue.getClass())))) {
270: throw new JoftiException(
271: "Classes for property range query must be the same. start:"
272: + startValue.getClass() + " end:"
273: + endValue.getClass());
274: }
275: if (startValue.compareTo(endValue) > 0) {
276: if (log.isDebugEnabled()) {
277: log.info("Range search: start range " + startValue
278: + " is greater then end range " + endValue
279: + " returning empty results");
280: }
281: return new OpenHashMap(1);
282: }
283: }
284: int dimension = 0;
285: try {
286:
287: if (className == null) {
288: if (startValue != null) {
289: className = startValue.getClass();
290: } else if (endValue != null) {
291: className = endValue.getClass();
292: }
293: }
294:
295: dimension = index.introspector.getDimension(className,
296: attribute);
297: } catch (PropertyNotIndexedException e) {
298: //no property match found
299: return new OpenHashMap(1);
300: } catch (JoftiException e) {
301: throw e;
302: }
303:
304: //log.info("Looking for property " + propertyName + " with index " + dimension);
305:
306: return BTOperations.range(index.tree, startValue, endValue,
307: dimension, inclusive, alias);
308:
309: }
310:
311: }
|