001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of 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,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.repository.test;
017:
018: import org.outerj.daisy.repository.testsupport.AbstractDaisyTestCase;
019: import org.outerj.daisy.repository.acl.*;
020: import org.outerj.daisy.repository.*;
021: import org.outerj.daisy.repository.query.PredicateExpression;
022: import org.outerj.daisy.repository.user.Role;
023: import org.outerj.daisy.repository.schema.RepositorySchema;
024: import org.outerj.daisy.repository.schema.FieldType;
025: import org.outerj.daisy.repository.schema.DocumentType;
026:
027: import java.math.BigDecimal;
028: import java.util.GregorianCalendar;
029:
030: public class PredicateExpressionTest extends AbstractDaisyTestCase {
031: private Repository repository;
032:
033: protected boolean resetDataStores() {
034: return true;
035: }
036:
037: protected void setUp() throws Exception {
038: super .setUp();
039:
040: RepositoryManager repositoryManager = getLocalRepositoryManager();
041:
042: repository = repositoryManager.getRepository(new Credentials(
043: "testuser", "testuser"));
044: repository.switchRole(Role.ADMINISTRATOR);
045: }
046:
047: public void testPredicateEvaluation() throws Exception {
048:
049: // make sure the ACL doesn't get in our way
050: Acl acl = repository.getAccessManager().getStagingAcl();
051: AclObject aclObject = acl.createNewObject("true");
052: acl.add(aclObject);
053: AclEntry aclEntry = aclObject.createNewEntry(
054: AclSubjectType.EVERYONE, -1);
055: aclEntry.set(AclPermission.READ, AclActionType.GRANT);
056: aclEntry.set(AclPermission.WRITE, AclActionType.GRANT);
057: aclObject.add(aclEntry);
058: acl.save();
059: repository.getAccessManager().copyStagingToLive();
060:
061: CollectionManager collectionManager = repository
062: .getCollectionManager();
063: DocumentCollection collection1 = collectionManager
064: .createCollection("collection1");
065: collection1.save();
066:
067: DocumentCollection collection2 = collectionManager
068: .createCollection("collection2");
069: collection2.save();
070:
071: RepositorySchema repositorySchema = repository
072: .getRepositorySchema();
073:
074: FieldType stringField = repositorySchema.createFieldType(
075: "stringfield", ValueType.STRING);
076: stringField.save();
077:
078: FieldType longField = repositorySchema.createFieldType(
079: "longfield", ValueType.LONG);
080: longField.save();
081:
082: FieldType doubleField = repositorySchema.createFieldType(
083: "doublefield", ValueType.DOUBLE);
084: doubleField.save();
085:
086: FieldType decimalField = repositorySchema.createFieldType(
087: "decimalfield", ValueType.DECIMAL);
088: decimalField.save();
089:
090: FieldType dateField = repositorySchema.createFieldType(
091: "datefield", ValueType.DATE);
092: dateField.save();
093:
094: FieldType dateTimeField = repositorySchema.createFieldType(
095: "datetimefield", ValueType.DATETIME);
096: dateTimeField.save();
097:
098: FieldType booleanField = repositorySchema.createFieldType(
099: "booleanfield", ValueType.BOOLEAN);
100: booleanField.save();
101:
102: FieldType hierField = repositorySchema.createFieldType(
103: "hierField", ValueType.STRING, false, true);
104: hierField.save();
105:
106: FieldType hierMvField = repositorySchema.createFieldType(
107: "hierMvField", ValueType.STRING, true, true);
108: hierMvField.save();
109:
110: FieldType hierMvLinkField = repositorySchema.createFieldType(
111: "hierMvLinkField", ValueType.LINK, true, true);
112: hierMvLinkField.save();
113:
114: FieldType multiValueStringField = repositorySchema
115: .createFieldType("mv-stringfield", ValueType.STRING,
116: true);
117: multiValueStringField.save();
118:
119: FieldType linkField = repositorySchema.createFieldType(
120: "linkField", ValueType.LINK);
121: linkField.save();
122:
123: DocumentType documentType = repositorySchema
124: .createDocumentType("doctype");
125: documentType.addFieldType(stringField, false);
126: documentType.addFieldType(longField, false);
127: documentType.addFieldType(doubleField, false);
128: documentType.addFieldType(decimalField, false);
129: documentType.addFieldType(dateField, false);
130: documentType.addFieldType(dateTimeField, false);
131: documentType.addFieldType(booleanField, false);
132: documentType.addFieldType(multiValueStringField, false);
133: documentType.addFieldType(hierField, false);
134: documentType.addFieldType(hierMvField, false);
135: documentType.addFieldType(hierMvLinkField, false);
136: documentType.addFieldType(linkField, false);
137: documentType.save();
138:
139: Document document = repository.createDocument("test",
140: documentType.getId());
141: document.setField(stringField.getId(), "some value");
142: document.setField(longField.getId(), new Long(123));
143: document.setField(doubleField.getId(), new Double(123.45));
144: document.setField(decimalField.getId(), new BigDecimal(
145: "123.45678"));
146: document.setField(dateField.getId(), new GregorianCalendar(
147: 2004, 11, 6).getTime());
148: document.setField(dateTimeField.getId(), new GregorianCalendar(
149: 2004, 11, 6, 12, 15, 6).getTime());
150: document.setField(booleanField.getId(), Boolean.TRUE);
151: document.setField(multiValueStringField.getId(), new String[] {
152: "value 1", "value 2" });
153: document.setField(hierField.getId(), new HierarchyPath(
154: new Object[] { "Aaa", "Bee", "Cee" }));
155: document.setField(hierMvField.getId(), new Object[] {
156: new HierarchyPath(new Object[] { "X", "Y", "Z" }),
157: new HierarchyPath(new Object[] { "T" }) });
158: document.setField(hierMvLinkField.getId(), new Object[] {
159: new HierarchyPath(new Object[] {
160: new VariantKey("10", 1, 1),
161: new VariantKey("11", 1, 1) }),
162: new HierarchyPath(new Object[] { new VariantKey("12",
163: 1, 1) }) });
164:
165: document.addToCollection(collection1);
166: document.save();
167:
168: Document document2 = repository.createDocument("test2",
169: documentType.getId());
170: document2.setField(linkField.getId(), new VariantKey(document
171: .getId(), -1, -1));
172: document2.save();
173:
174: PredicateExpression expr;
175:
176: //
177: // Test various combinations of datatypes and operators
178: //
179:
180: // string
181: testBoth(true, "$stringfield = 'some value'", document,
182: document2);
183: testBoth(false, "$stringfield = 'some other value'", document,
184: document2);
185: testBoth(true, "$stringfield LIKE '%value'", document,
186: document2);
187: testBoth(true, "$stringfield LIKE 'some_value'", document,
188: document2);
189: testBoth(false, "$stringfield LIKE 'some\\_value'", document,
190: document2);
191:
192: // long
193: testBoth(true, "$longfield = 123", document, document2);
194: testBoth(false, "$longfield = 124", document, document2);
195:
196: // double
197: testBoth(true, "$doublefield < 124", document, document2);
198: testBoth(true, "$doublefield > 122", document, document2);
199:
200: // date
201: testBoth(true, "$datefield = '2004-12-06'", document, document2);
202: testBoth(true, "$datefield >= '2004-12-06'", document,
203: document2);
204: testBoth(true, "$datefield <= '2004-12-06'", document,
205: document2);
206: testBoth(true, "$datefield > '2004-12-05'", document, document2);
207: testBoth(true, "$datefield != '2004-12-05'", document,
208: document2);
209:
210: // datetime
211: testBoth(true, "$datetimefield = '2004-12-06 12:15:06'",
212: document, document2);
213: testBoth(true, "$datetimefield >= '2004-12-06 12:15:06'",
214: document, document2);
215: testBoth(true, "$datetimefield <= '2004-12-06 12:15:06'",
216: document, document2);
217: testBoth(true, "$datetimefield > '2004-12-05 12:15:06'",
218: document, document2);
219: testBoth(true, "$datetimefield != '2004-12-05 12:15:06'",
220: document, document2);
221:
222: // decimal
223: testBoth(true,
224: "$decimalfield IN (3232.3232, 123.45678, 890.542)",
225: document, document2);
226: testBoth(false, "$decimalfield IN (3232.3232, 890.542)",
227: document, document2);
228: testBoth(true, "$decimalfield NOT IN (3232.3232, 890.542)",
229: document, document2);
230: testBoth(true, "$decimalfield BETWEEN 89.232 AND 123.456789",
231: document, document2);
232:
233: // boolean
234: testBoth(true, "$booleanfield = 'true'", document, document2);
235:
236: //
237: // Test more complex expresions
238: //
239: expr = makeExpression("$decimalfield IN (3232.3232, 123.45678, 890.542) and $stringfield between 'a' and 'z'");
240: assertEquals(true, expr.evaluate(document, null));
241:
242: expr = makeExpression("$decimalfield IN (5) or $stringfield between 'a' and 'z'");
243: assertEquals(true, expr.evaluate(document, null));
244:
245: expr = makeExpression("($decimalfield IN (5) or $stringfield between 'a' and 'z') and $longfield > 100");
246: assertEquals(true, expr.evaluate(document, null));
247:
248: //
249: // Test non-metadata fields
250: //
251: testBoth(true, "documentType = '" + documentType.getName()
252: + "'", document, document2);
253:
254: expr = makeExpression("InCollection('" + collection1.getName()
255: + "')");
256: assertEquals(true, expr.evaluate(document, null));
257:
258: expr = makeExpression("InCollection('" + collection2.getName()
259: + "')");
260: assertEquals(false, expr.evaluate(document, null));
261:
262: testBoth(true, "collections has all ('" + collection1.getName()
263: + "')", document, document2);
264:
265: testBoth(true, "variants has all ('main:default')", document,
266: document2);
267:
268: testBoth(true, "variants has exactly ('main:default')",
269: document, document2);
270:
271: testBoth(true, "variants.valueCount = 1", document, document2);
272:
273: //
274: // Test multivalue fields
275: //
276: testBoth(true, "$mv-stringfield.valueCount = 2", document,
277: document2);
278:
279: expr = makeExpression("$mv-stringfield.valueCount > 1 and $mv-stringfield.valueCount < 3");
280: assertTrue(expr.evaluate(document, null));
281:
282: testBoth(false, "$mv-stringfield.valueCount != 2", document,
283: document2);
284:
285: testBoth(true, "$mv-stringfield has all ('value 1')", document,
286: document2);
287:
288: testBoth(true,
289: "$mv-stringfield has all ('value 1', 'value 2')",
290: document, document2);
291:
292: testBoth(false, "$mv-stringfield has exactly ('value 1')",
293: document, document2);
294:
295: testBoth(true,
296: "$mv-stringfield has exactly ('value 1', 'value 2')",
297: document, document2);
298:
299: testBoth(true, "$mv-stringfield has any ('value 1', 'xyz')",
300: document, document2);
301:
302: testBoth(true, "$mv-stringfield has some ('value 1', 'xyz')",
303: document, document2);
304:
305: testBoth(false, "$mv-stringfield has some ('abc', 'xyz')",
306: document, document2);
307:
308: testBoth(true,
309: "$mv-stringfield has some ('value 1', 'value 2')",
310: document, document2);
311:
312: testBoth(true, "$mv-stringfield = 'value 1'", document,
313: document2);
314:
315: testBoth(true, "$mv-stringfield like 'value%'", document,
316: document2);
317:
318: // TODO test other functions like LinksTo
319:
320: // Test hierarchical fields
321: testBoth(true,
322: "$hierMvField has all ( Path('/X/Y/Z'), Path('/T')) ",
323: document, document2);
324:
325: testBoth(false,
326: "$hierMvField has all ( Path('/X/Y/Z'), Path('/T1')) ",
327: document, document2);
328:
329: testBoth(true,
330: "$hierMvField has any ( Path('/X/Y/Z'), Path('/T1')) ",
331: document, document2);
332:
333: testBoth(
334: true,
335: "$hierMvField has exactly ( Path('/X/Y/Z'), Path('/T')) ",
336: document, document2);
337:
338: testBoth(
339: false,
340: "$hierMvField has exactly ( Path('/X/Y/Z'), Path('/T'), Path('/X')) ",
341: document, document2);
342:
343: testBoth(
344: false,
345: "$hierMvField has none ( Path('/X/Y/Z'), Path('/T'), Path('/X')) ",
346: document, document2);
347:
348: testBoth(
349: true,
350: "$hierMvField has none ( Path('/X/Y/Za'), Path('/Tb'), Path('/X')) ",
351: document, document2);
352:
353: testBoth(true, "$hierField matchesPath('/Aaa/Bee/Cee')",
354: document, document2);
355:
356: testBoth(false, "$hierField matchesPath('/Aaa/Bee/Ceexxx')",
357: document, document2);
358:
359: testBoth(true, "$hierField matchesPath('**/Cee')", document,
360: document2);
361:
362: testBoth(true, "$hierField matchesPath('**/Bee/Cee')",
363: document, document2);
364:
365: testBoth(true, "$hierField matchesPath('**/*/Cee')", document,
366: document2);
367:
368: testBoth(true, "$hierField matchesPath('/Aaa/**')", document,
369: document2);
370:
371: testBoth(true, "$hierField matchesPath('/Aaa/Bee/**')",
372: document, document2);
373:
374: testBoth(true, "$hierField matchesPath('/Aaa/Bee/*')",
375: document, document2);
376:
377: testBoth(true, "$hierField matchesPath('/Aaa/*/*')", document,
378: document2);
379:
380: testBoth(true, "$hierField matchesPath('/*/*/*')", document,
381: document2);
382:
383: testBoth(false, "$hierField matchesPath('/*/*/*/*')", document,
384: document2);
385:
386: testBoth(true, "$hierMvField matchesPath('/X/Y/Z')", document,
387: document2);
388:
389: testBoth(true, "$hierMvField matchesPath('/T')", document,
390: document2);
391:
392: testBoth(false, "$hierMvField matchesPath('/P')", document,
393: document2);
394:
395: testBoth(true, "$hierMvLinkField matchesPath('/daisy:12')",
396: document, document2);
397:
398: // equals operator should evaluate to true whenever the value occurs somewhere in the hierarchical field
399: testBoth(true, "$hierMvLinkField = 'daisy:12'", document,
400: document2);
401:
402: testBoth(true, "$hierField = 'Bee'", document, document2);
403: }
404:
405: private void testBoth(boolean expectedResult, String expression,
406: Document document, Document linkedDoc) throws Exception {
407: PredicateExpression expr = makeExpression(expression);
408:
409: if (expectedResult)
410: assertTrue(expr.evaluate(document, null));
411: else
412: assertFalse(expr.evaluate(document, null));
413:
414: expr = makeExpression("$linkField=>" + expression);
415: if (expectedResult)
416: assertTrue(expr.evaluate(linkedDoc, null));
417: else
418: assertFalse(expr.evaluate(linkedDoc, null));
419: }
420:
421: private PredicateExpression makeExpression(String expression)
422: throws Exception {
423: return repository.getQueryManager().parsePredicateExpression(
424: expression);
425: }
426: }
|