/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.stanbol.entityhub.test.yard; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.apache.stanbol.entityhub.test.Utils.asCollection; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.stanbol.entityhub.servicesapi.defaults.NamespaceEnum; import org.apache.stanbol.entityhub.servicesapi.model.Reference; import org.apache.stanbol.entityhub.servicesapi.model.Representation; import org.apache.stanbol.entityhub.servicesapi.model.Text; import org.apache.stanbol.entityhub.servicesapi.query.FieldQuery; import org.apache.stanbol.entityhub.servicesapi.query.FieldQueryFactory; import org.apache.stanbol.entityhub.servicesapi.query.QueryResultList; import org.apache.stanbol.entityhub.servicesapi.query.RangeConstraint; import org.apache.stanbol.entityhub.servicesapi.query.ReferenceConstraint; import org.apache.stanbol.entityhub.servicesapi.query.TextConstraint; import org.apache.stanbol.entityhub.servicesapi.query.TextConstraint.PatternType; import org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint; import org.apache.stanbol.entityhub.servicesapi.util.ModelUtils; import org.apache.stanbol.entityhub.servicesapi.yard.Yard; import org.apache.stanbol.entityhub.servicesapi.yard.YardException; import org.junit.Assert; import org.junit.Test; public abstract class YardTest { /** * used for {@link FieldQuery} tests added by STANBOL-1202 */ private FieldQueryTestData fieldQueryTestData; /** * Getter for the {@link Yard} instance to be tested * * @return the {@link Yard} instance to be tested */ protected abstract Yard getYard(); /** * Stores all the IDs of Representations created by the create(..) methods. This collection is used to * clean up the store after all the unit tests are executed. */ protected static Collection<String> representationIds = new HashSet<String>(); protected Representation create() throws YardException { Representation r = getYard().create(); representationIds.add(r.getId()); return r; } protected Representation create(String id, boolean store) throws YardException { Representation r; if (store) { r = getYard().create(id); } else if (id != null && !id.isEmpty()) { r = getYard().getValueFactory().createRepresentation(id); } else { throw new IllegalArgumentException("If store is FALSE the id MUST NOT be NULL nor EMPTY!"); } representationIds.add(r.getId()); return r; } @Test public void testGetValueFactory() { assertNotNull("The ValueFactory MUST NOT be NULL", getYard().getValueFactory()); } @Test public void testGetQueryFactory() { assertNotNull("The QueryFactory MUST NOT be NULL", getYard().getQueryFactory()); } @Test public void testYardId() { assertNotNull("The ID of the Yard MUST NOT be NULL", getYard().getId()); } @Test public void testYardName() { assertNotNull("The Name of the Yard MUST NOT be NULL", getYard().getName()); assertFalse("The Name of the Yard MUST NOT be an empty String", getYard().getName().isEmpty()); } @Test public void testDefaultCreate() throws YardException { Yard yard = getYard(); Representation test = yard.create(); assertNotNull(test); Representation test2 = yard.create(); assertNotNull(test2); assertNotSame(test, test2); assertFalse("Two Representation created with create() MUST NOT be equals", test.equals(test2)); } @Test public void testCreateWithNull() throws YardException { Yard yard = getYard(); Representation test = yard.create(null); assertNotNull("Parsing NULL to create(String) MUST create a valid Representation", test); representationIds.add(test.getId()); // add id to cleanup list Representation test2 = yard.create(null); assertNotNull("Parsing NULL to create(String) MUST create a valid Representation", test2); representationIds.add(test2.getId()); // add id to cleanup list assertNotSame(test, test2); assertFalse("Two Representation created with create(null) MUST NOT be equals", test.equals(test2)); } @Test(expected = IllegalArgumentException.class) public void testCreateWithEmptyString() throws YardException { getYard().create("");// throws an IllegalArgumentException } @Test(expected = IllegalArgumentException.class) public void testCreateWithExistingId() throws YardException { Yard yard = getYard(); Representation test = create(); assertNotNull(test); yard.create(test.getId()); // throws an IllegalArgumentException } @Test(expected = IllegalArgumentException.class) public void testIsRepresentationWithNull() throws YardException { getYard().isRepresentation(null); } @Test(expected = IllegalArgumentException.class) public void testIsRepresentationWithEmptyString() throws YardException { getYard().isRepresentation(""); } @Test(expected = IllegalArgumentException.class) public void testStoreRepresentationWithNull() throws YardException { getYard().store((Representation) null); } @Test(expected = IllegalArgumentException.class) public void testStoreRepresentationsWithNull() throws YardException { getYard().store((Iterable<Representation>) null); } @Test public void testStoreRepresentation() throws YardException { // NOTE: this does not test if the updated view of the representation is // stored, but only that the store method works for representations // that are already in the Yard AND representations that are not yet // present within the yard String testId = "urn:yard.test.testStoreRepresentation:representation.id1"; String testId2 = "urn:yard.test.testStoreRepresentation:representation.id2"; Yard yard = getYard(); Representation test = create(testId, false); Representation added = yard.store(test); // this adds the representation assertEquals(test, added); Representation test2 = create(testId2, true); // this creates and adds the representation // now test that the representation can also be updated added = yard.store(test2); assertEquals(test2, added); } @Test public void testStoreRepresentations() throws YardException { // NOTE: this does not test if the updated view of the representation is // stored, but only that the store method works for representations // that are already in the Yard AND representations that are not yet // present within the yard String testId = "urn:yard.test.testStoreRepresentations:representation.id1"; String testId2 = "urn:yard.test.testStoreRepresentations:representation.id2"; String field = "urn:the.field:used.for.this.Test"; Yard yard = getYard(); Representation test = create(testId, false); Representation test2 = create(testId2, true); // this creates and adds the representation // now add both and mix Representations that are already present in the yard // with an other that is not yet present in the yard // change the representations to be sure to force an update even if the // implementation checks for changes before updating a representation test2.add(field, "test value 2"); Iterable<Representation> addedIterable = yard.store(Arrays.asList(test, test2)); assertNotNull(addedIterable); Collection<Representation> added = asCollection(addedIterable.iterator()); // test that both the parsed Representations where stored (updated & created) assertTrue(added.remove(test)); assertTrue(added.remove(test2)); assertTrue(added.isEmpty()); } @Test public void testStoreRepresentationsWithNullElement() throws YardException { String testId = "urn:yard.test.testStoreRepresentationsWithNullElement:representation.id"; Yard yard = getYard(); Representation test = create(testId, false); Iterable<Representation> added = yard.store(Arrays.asList(test, null)); // now test that only the valid representation was added and the null // value was ignored assertNotNull(added); Iterator<Representation> addedIt = added.iterator(); assertTrue(addedIt.hasNext()); assertEquals(test, addedIt.next()); assertFalse(addedIt.hasNext()); } @Test(expected = IllegalArgumentException.class) public void testGetRepresentationWithNull() throws YardException { getYard().getRepresentation(null); } @Test(expected = IllegalArgumentException.class) public void testGetRepresentationWithEmptyString() throws YardException { getYard().getRepresentation(""); } @Test public void testGetNonExistantRepresentation() throws YardException { String id = "urn:yard.test.testGetNonExistantRepresentation:representation.id"; assertNull(getYard().getRepresentation(id)); } /** * This tests that {@link Representation} retrieved from the Yard do not influence other * {@link Representation} instances for the same ID. It is important, that when different * {@link Representation} instances are returned to different caller, that these do not influence each * other. * <p> * It also tests, that any update to the {@link Representation} as managed by the {@link Yard} does also * not influence {@link Representation} instances that where created before the change. * * @throws YardException */ @Test public void testGetRepresentation() throws YardException { String id = "urn:yard.test.testGetRepresentation.id"; Yard yard = getYard(); String field = "urn:the.field:used.for.this.Test"; String value1 = "this is a test"; // Representations created via the yard need to be created (as empty // representation within the yard Representation test = create(id, true); // retrieve the representation from the store Representation retrieved = yard.getRepresentation(id); assertNotNull(retrieved); // they MUST NOT be the same, but the MUST be equals // Note: // the fact that two representations with the same id are equals is tested // by the unit tests for the representation interface assertEquals(test, retrieved); assertNotSame("getRepresentation MUST return an new instance for each " + "call, so that changes in one return instance do not influence " + "an other returned instance!", test, retrieved); // now add a property to the original one test.add(field, value1); // and check that the retrieved does not have the value assertFalse(retrieved.get(field).hasNext()); // now store the representation and check that updated are not reflected // within the retrieved one yard.store(test); assertFalse(retrieved.get(field).hasNext()); // now retrieve again an representation retrieved = null; retrieved = yard.getRepresentation(id); // now the Representation MUST HAVE the new field assertTrue(retrieved.get(field).hasNext()); assertEquals(value1, retrieved.getFirst(field)); // finally retrieve a second and perform the change test again Representation retrieved2 = yard.getRepresentation(id); retrieved.removeAll(field); // check the value is still in retrieved2 assertTrue(retrieved2.get(field).hasNext()); assertEquals(value1, retrieved2.getFirst(field)); } @Test public void testIsRepresentation() throws YardException { String id = "urn:yard.test.testIsRepresentation:representation.id"; Yard yard = getYard(); // Representations created via the yard need to be created (as empty // representation within the yard Representation test = create(); assertTrue(yard.isRepresentation(test.getId())); // Representations created via the ValueFactory MUST NOT be added to the // Yard Representation test2 = create(id, false); assertFalse(yard.isRepresentation(test2.getId())); // now store test2 and test again yard.store(test2); assertTrue(yard.isRepresentation(test2.getId())); // now remove test and test again yard.remove(test.getId()); assertFalse(yard.isRepresentation(test.getId())); yard.remove(test2.getId()); assertFalse(yard.isRepresentation(test2.getId())); } @Test(expected = IllegalArgumentException.class) public void testUpdateRepresentationWithNull() throws YardException { getYard().update((Representation) null); } @Test(expected = IllegalArgumentException.class) public void testUpdateRepresentationWithNonPresent() throws YardException { String id = "urn:yard.test.testUpdateRepresentationWithNonPresent:representation.id"; Representation test = create(id, false); getYard().update(test); // throws an Exception because test is not part of the yard } @Test(expected = IllegalArgumentException.class) public void testUpdateRepresentationsWithNull() throws YardException { getYard().update((Iterable<Representation>) null); } @Test public void testUpdateRepresentations() throws YardException { // NOTE: this does not test if the updated view of the representation is // stored, but only that the update method works correctly Yard yard = getYard(); String id1 = "urn:yard.test.testUpdateRepresentations:representation.id1"; String id2 = "urn:yard.test.testUpdateRepresentations:representation.id2"; String field = "urn:the.field:used.for.this.Test"; Representation test1 = create(id1, true); Representation test2 = create(id2, true); // change the representations to be sure to force an update even if the // implementation checks for changes before updating a representation test1.add(field, "test value 1"); test2.add(field, "test value 2"); Iterable<Representation> updatedIterable = yard.update(Arrays.asList(test1, test2)); assertNotNull(updatedIterable); Collection<Representation> updated = asCollection(updatedIterable.iterator()); // test that both the parsed Representations where stored (updated & created) assertTrue(updated.remove(test1)); assertTrue(updated.remove(test2)); assertTrue(updated.isEmpty()); } /** * When updating multiple null values need to be ignored. * * @throws YardException */ @Test public void testUpdateRepresentationsWithNullElement() throws YardException { // NOTE: this does not test if the updated view of the representation is // stored, but only that the update method works correctly Yard yard = getYard(); String id1 = "urn:yard.test.testUpdateRepresentationsWithNullElement:representation.id"; String field = "urn:the.field:used.for.this.Test"; Representation test1 = create(id1, true); // change the representations to be sure to force an update even if the // implementation checks for changes before updating a representation test1.add(field, "test value 1"); Iterable<Representation> updated = yard.update(Arrays.asList(test1, null)); assertNotNull(updated); Iterator<Representation> updatedIt = updated.iterator(); assertTrue(updatedIt.hasNext()); assertEquals(test1, updatedIt.next()); assertFalse(updatedIt.hasNext()); } /** * When updating multiple non present representations need to be ignored. * * @throws YardException */ @Test public void testUpdateRepresentationsWithNonPresent() throws YardException { // NOTE: this does not test if the updated view of the representation is // stored, but only that the update method works correctly Yard yard = getYard(); String id1 = "urn:yard.test.testUpdateRepresentationsWithNonPresent:representation.id1"; String id2 = "urn:yard.test.testUpdateRepresentationsWithNonPresent:representation.id2"; String field = "urn:the.field:used.for.this.Test"; Representation test1 = create(id1, true); // change the representations to be sure to force an update even if the // implementation checks for changes before updating a representation test1.add(field, "test value 1"); // create a 2nd Representation by using the ValueFactory (will not add it // to the yard!) Representation test2 = create(id2, false); // now test1 is present and test2 is not. Iterable<Representation> updated = yard.update(Arrays.asList(test1, test2)); // We expect that only test1 is updated and test2 is ignored assertNotNull(updated); Iterator<Representation> updatedIt = updated.iterator(); assertTrue(updatedIt.hasNext()); assertEquals(test1, updatedIt.next()); assertFalse(updatedIt.hasNext()); } @Test(expected = IllegalArgumentException.class) public void testRemoveRepresentationWithNull() throws YardException { getYard().remove((String) null); } /** * Tests two things: * <ol> * <li>if representations are removed form the yard * <li>if the representation instance is still valid after it is removed * </ol> * The second is very important, because Representations might still be used by other components after * they are remove from the store they where created in * * @throws YardException */ @Test public void testRemoveRepresentation() throws YardException { // NOTE: This test needs not to use the create(..) method, because we // remove the created representation form the store anyway as part of the // test String id = "urn:yard.test.tesrRemoveRepresentation:representation.id"; String field = "urn:the.field:used.for.this.Test"; String testValue = "This is a test"; Yard yard = getYard(); Representation test = yard.getValueFactory().createRepresentation(id); test.add(field, testValue); yard.store(test); // store the representation assertTrue(yard.isRepresentation(test.getId())); // test if stored test = null; // free the initial // create the instance form the store to test (2) test = yard.getRepresentation(id); assertEquals(id, test.getId()); // only to be sure ... yard.remove(test.getId()); // test (1) - the remove assertFalse(yard.isRepresentation(test.getId()));// test if removed // test if the test object is not destroyed by removing the representation // it represents form the store (2) assertEquals(testValue, test.getFirst(field)); } @Test(expected = IllegalArgumentException.class) public void testRemoveRepresentationsWithNull() throws YardException { getYard().remove((Iterable<String>) null); } /** * Tests that multiple Representations are removed. * * @throws YardException */ @Test public void testRemoveRepresentations() throws YardException { // NOTE: This test needs not to use the create(..) method, because we // remove the created representation form the store anyway as part of the // test String id = "urn:yard.test.testRemoveRepresentationsWithNullValue:representation.id1"; String id2 = "urn:yard.test.testRemoveRepresentationsWithNullValue:representation.id2"; String field = "urn:the.field:used.for.this.Test"; String testValue = "This is a test"; Yard yard = getYard(); // use both ways to add the two Representations (should make no differences, // but one never can know ... Representation test1 = yard.create(id); // create and add Representation test2 = yard.getValueFactory().createRepresentation(id2); // create test2.add(field, testValue); // add value yard.store(test2);// store assertTrue(yard.isRepresentation(test1.getId())); // test if stored assertTrue(yard.isRepresentation(test2.getId())); yard.remove(Arrays.asList(test1.getId(), test2.getId())); // remove assertFalse(yard.isRepresentation(test1.getId())); // test if removed assertFalse(yard.isRepresentation(test2.getId())); } /** * Tests that multiple Representations are removed. * * @throws YardException */ @Test public void testRemoveAll() throws YardException { // NOTE: This test needs not to use the create(..) method, because we // remove the created representation form the store anyway as part of the // test String id = "urn:yard.test.testRemoveAll:representation.id1"; String id2 = "urn:yard.test.testRemoveAll:representation.id2"; String field = "urn:the.field:used.for.this.Test"; String testValue = "This is a test"; Yard yard = getYard(); // use both ways to add the two Representations (should make no differences, // but one never can know ... Representation test1 = yard.create(id); // create and add test1.add(field, testValue); // add value yard.store(test1);// store Representation test2 = yard.getValueFactory().createRepresentation(id2); // create test2.add(field, testValue); // add value yard.store(test2);// store assertTrue(yard.isRepresentation(test1.getId())); // test if stored assertTrue(yard.isRepresentation(test2.getId())); yard.removeAll(); // remove assertFalse(yard.isRepresentation(test1.getId())); // test if removed assertFalse(yard.isRepresentation(test2.getId())); //test that Yard is still useable after removeAll yard.store(test1);// store assertTrue(yard.isRepresentation(test1.getId())); // test if stored yard.removeAll(); // remove assertFalse(yard.isRepresentation(test1.getId())); } /** * Tests if <code>null</code> values within the Iterable are ignored and do not cause an Exception * * @throws YardException */ @Test public void testRemoveRepresentationsWithNullValue() throws YardException { // NOTE: This test needs not to use the create(..) method, because we // remove the created representation form the store anyway as part of the // test String id = "urn:yard.test.testRemoveRepresentationsWithNullValue:representation.id"; Yard yard = getYard(); Representation test = yard.create(id); // create and add assertTrue(yard.isRepresentation(test.getId())); yard.remove(Arrays.asList(test.getId(), null)); assertFalse(yard.isRepresentation(test.getId())); } /** * Tests that {@link Representation} IDs that are not stored by the yard are ignored by the multiple * remove method * * @throws YardException */ @Test public void testRemoveRepresentationsWithNonStoredValue() throws YardException { // NOTE: This test needs not to use the create(..) method, because we // remove the created representation form the store anyway as part of the // test String id = "urn:yard.test.testRemoveRepresentationsWithNullValue:representation.stored"; String id2 = "urn:yard.test.testRemoveRepresentationsWithNullValue:representation.notStored"; Yard yard = getYard(); Representation test = yard.create(id); // create and add assertTrue(yard.isRepresentation(test.getId())); yard.remove(Arrays.asList(test.getId(), id2)); assertFalse(yard.isRepresentation(test.getId())); assertFalse(yard.isRepresentation(id2)); } /** * The {@link Representation} as stored in the Yard MUST NOT change if the source {@link Representation} * stored to the {@link Yard} or an Representation retrieved from the Yard is changed. Only the * {@link Yard#store(Representation))} and the {@link Yard#update(Representation)} methods are allowed to * synchronised the Representation within the Yard with the state (changes) of the parsed value. * * @throws YardException */ @Test public void testChangeRepresentation() throws YardException { String id = "urn:yard.test.testChangeRepresentation:representation.id"; String field = "urn:the.field:used.for.this.Test"; String testValue = "This is a test"; Yard yard = getYard(); // use the ValueFactory to create the representation to ensure that this // instance has nothing to do with the store Representation test = create(id, false); // now store the empty Representation yard.store(test); // now add a values test.add(field, testValue); // now get the representation from the yard Representation stored = yard.getRepresentation(id); // test if the stored version does not contain the value assertFalse(stored.get(field).hasNext()); stored = null; // now store the updated version yard.store(test); // now check that the updated value is stored stored = yard.getRepresentation(id); assertEquals(testValue, stored.getFirst(field)); // now we need to test if modifications of an Representation returned test = stored; stored = null; String testValue2 = "This is an ohter test value"; test.add(field, testValue2); // now get the representation from the yard and check that it still has // only one value stored = yard.getRepresentation(id); Collection<Object> values = asCollection(stored.get(field)); assertTrue(values.remove(testValue)); // test that it contains the value assertTrue(values.isEmpty()); // and that there is only this value values = null; // now update the stored version with the new state stored = null; stored = yard.update(test); values = asCollection(stored.get(field)); assertTrue(values.remove(testValue)); // test that it contains the original assertTrue(values.remove(testValue2)); // test that it contains the 2nd value assertTrue(values.isEmpty()); // and that there are only these two values values = null; } /* * All the follow up tests where added as part of STANBOL-1202 */ /** * Simple test for the QueryFactory */ @Test public void testQeuryFactory(){ FieldQueryFactory qf = getYard().getQueryFactory(); Assert.assertNotNull("The getter for the FieldQueryFactory MUST NOT return NULL!", qf); FieldQuery query = qf.createFieldQuery(); Assert.assertNotNull("The FieldQueryFactory returned NULL as query", query); } /** * Test a simple {@link TextConstraint} for any language */ @Test public void testFindText(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //query for all languages and value1 FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint(data.textValue1.getText())); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList( data.r1.getId(), data.r1en.getId(), data.r1de.getId()), Arrays.asList(data.textField, data.refField)); //same for value2 query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint(data.textValue2.getText())); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList( data.r2.getId(), data.r2en.getId(), data.r2de.getId()), Arrays.asList(data.textField, data.refField)); } /** * Same as {@link #testFindText()} but using * {@link Yard#findRepresentation(FieldQuery)} to execute the queries */ @Test public void testFindRepresentationText(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //query for all languages and value1 FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint(data.textValue1.getText())); validateQueryResults(query, getYard().findRepresentation(query), Arrays.asList( data.r1.getId(), data.r1en.getId(), data.r1de.getId()), Arrays.asList(data.textField, data.refField, data.intField)); //same for value2 query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint(data.textValue2.getText())); validateQueryResults(query, getYard().findRepresentation(query), Arrays.asList( data.r2.getId(), data.r2en.getId(), data.r2de.getId()), Arrays.asList(data.textField, data.refField, data.intField)); } /** * Same as {@link #testFindText()} but using * {@link Yard#findReferences(FieldQuery)} to execute the queries */ @Test public void testFindReferencesText(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //query for all languages and value1 FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint(data.textValue1.getText())); validateQueryResults(query, getYard().findReferences(query), Arrays.asList(data.r1.getId(), data.r1en.getId(), data.r1de.getId())); //same for value2 query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint(data.textValue2.getText())); validateQueryResults(query, getYard().findReferences(query), Arrays.asList( data.r2.getId(), data.r2en.getId(), data.r2de.getId())); } /** * Test a simple {@link TextConstraint} for any language */ @Test public void testFindTextOfLanguage(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //value1@en FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint( data.textValue1.getText(), "en")); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1en.getId()), Arrays.asList(data.textField, data.refField)); //value2@de query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint( data.textValue2.getText(), "de")); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r2de.getId()), Arrays.asList(data.textField, data.refField)); //value1@null query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint( data.textValue1.getText(), (String)null)); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1.getId()), Arrays.asList(data.textField, data.refField)); //value1@null,en query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint( data.textValue1.getText(), null, "en")); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1.getId(),data.r1en.getId()), Arrays.asList(data.textField, data.refField)); //value1@en,de query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint( data.textValue1.getText(), "en", "de")); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1en.getId(),data.r1de.getId()), Arrays.asList(data.textField, data.refField)); } @Test public void testFindTextWildcards(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //prefix search with * FieldQuery query = getYard().getQueryFactory().createFieldQuery(); String wildcard = data.textValue1.getText(); wildcard = wildcard.substring(0, wildcard.length()-1) + "*"; query.setConstraint(data.textField, new TextConstraint(wildcard,PatternType.wildcard,false, "en")); query.addSelectedField(data.refField); query.addSelectedField(data.textField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1en.getId(), data.r2en.getId()), Arrays.asList(data.refField, data.textField)); //wildcard with ? query = getYard().getQueryFactory().createFieldQuery(); //selects r1en and r2en wildcard = data.textValue1.getText(); wildcard = wildcard.substring(0, wildcard.length()-1) + "?"; query.setConstraint(data.textField, new TextConstraint(wildcard,PatternType.wildcard,false, "de")); query.addSelectedField(data.refField); query.addSelectedField(data.textField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1de.getId(), data.r2de.getId()), Arrays.asList(data.refField, data.textField)); } /** * Tests a TextConstraint with multiple optional values */ @Test public void testfindOptionalTexts(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //value1@en || value2@en FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint( Arrays.asList(data.textValue1.getText(), data.textValue2.getText()), "en")); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1en.getId(),data.r2en.getId()), Arrays.asList(data.textField, data.refField)); //value1@en,de || value2@en,de query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.textField, new TextConstraint( Arrays.asList(data.textValue1.getText(), data.textValue2.getText()), "en", "de")); query.addSelectedField(data.textField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1en.getId(),data.r1de.getId(), data.r2en.getId(), data.r2de.getId()), Arrays.asList(data.textField, data.refField)); } /** * Test a {@link ReferenceConstraint} */ @Test public void testFindReference(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //query for all languages and value1 FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.refField, new ReferenceConstraint(data.refValue1.getReference())); query.addSelectedField(data.intField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1.getId(), data.r1en.getId(), data.r1de.getId(), data.r5.getId()), Arrays.asList(data.intField, data.refField)); //same for value2 query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.refField, new ReferenceConstraint(data.refValue2.getReference())); query.addSelectedField(data.intField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r2.getId(), data.r2en.getId(), data.r2de.getId(), data.r10.getId()), Arrays.asList(data.intField, data.refField)); } /** * Tests simple {@link ValueConstraint}s */ @Test public void testFindValues(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //query for all languages and value1 FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.intField, new ValueConstraint(data.intValue1)); query.addSelectedField(data.intField); query.addSelectedField(data.textField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1.getId(), data.r1en.getId(), data.r1de.getId()), Arrays.asList(data.intField, data.textField)); //same for value2 query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.intField, new ValueConstraint(data.intValue2)); query.addSelectedField(data.intField); query.addSelectedField(data.textField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r2.getId(), data.r2en.getId(), data.r2de.getId()), Arrays.asList(data.intField, data.textField)); } /** * Tests simple {@link RangeConstraint} */ @Test public void testFindRange(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //query for all languages and value1 FieldQuery query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.intField, new RangeConstraint(data.intValue2,data.intValue5,true)); query.addSelectedField(data.intField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r2.getId(), data.r2en.getId(), data.r2de.getId(), data.r5.getId()), Arrays.asList(data.intField, data.refField)); //same for value2 query = getYard().getQueryFactory().createFieldQuery(); query.setConstraint(data.intField, new RangeConstraint(data.intValue2,data.intValue10,false)); query.addSelectedField(data.intField); query.addSelectedField(data.textField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r5.getId()), Arrays.asList(data.intField, data.textField)); } /** * Tests simple {@link RangeConstraint} */ @Test public void testFindMultipleConstraints(){ //init the test data FieldQueryTestData data = getFieldQueryTestData(); //Integer Range and reference query FieldQuery query = getYard().getQueryFactory().createFieldQuery(); //selects r2, r2en, r2de, r5 query.setConstraint(data.intField, new RangeConstraint(data.intValue2,data.intValue5, true)); //selects r1, r1en, r1de, r5 query.setConstraint(data.refField, new ReferenceConstraint(data.refValue1.getReference())); query.addSelectedField(data.intField); query.addSelectedField(data.refField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r5.getId()), Arrays.asList(data.intField, data.refField)); //text and reference query = getYard().getQueryFactory().createFieldQuery(); //selects r1en and r2en String wildcard = data.textValue1.getText(); wildcard = wildcard.substring(0, wildcard.length()-1) + "*"; query.setConstraint(data.textField, new TextConstraint(wildcard,PatternType.wildcard,false, "en")); //selects r1, r1en, r1de, r5 query.setConstraint(data.refField, new ReferenceConstraint(data.refValue1.getReference())); query.addSelectedField(data.refField); query.addSelectedField(data.textField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r1en.getId()), Arrays.asList(data.refField, data.textField)); //text and value query = getYard().getQueryFactory().createFieldQuery(); //selects r1de and r2de query.setConstraint(data.textField, new TextConstraint(wildcard,PatternType.wildcard,false, "de")); //selects r2, r2en, r2de query.setConstraint(data.intField, new ValueConstraint(data.intValue2)); query.addSelectedField(data.refField); query.addSelectedField(data.textField); validateQueryResults(query, getYard().find(query), Arrays.asList(data.r2de.getId()), Arrays.asList(data.refField, data.textField)); } /** * Used to validate the results of the query against expected results. * Supports also the validation of selected fields * @param query the query * @param results the results of the query * @param parsedExpectedResults read-only list of expected results * @param parsedExpectedFields read-only list of expected selected fields or * <code>null</code> to deactivate validation of fields */ protected final void validateQueryResults(FieldQuery query, QueryResultList<Representation> results, Collection<String> parsedExpectedResults, Collection<String> parsedExpectedFields) { Set<String> expectedResults = parsedExpectedResults == null ? new HashSet<String>() : new HashSet<String>(parsedExpectedResults); Set<String> expectedFields = parsedExpectedFields == null ? null : new HashSet<String>(parsedExpectedFields); FieldQueryTestData data = getFieldQueryTestData(); Assert.assertNotNull("NULL result for query "+query+"!", results); for(Representation result : results){ Assert.assertTrue("Result '"+ result.getId() + "' is missing for Query " + query +"!", expectedResults.remove(result.getId())); if(expectedFields != null){ //validate fields for(String field : expectedFields){ Set<Object> expectedFieldValues = ModelUtils.asSet( data.representations.get(result.getId()).get(field)); Iterator<Object> fieldValues = result.get(field); while(fieldValues.hasNext()){ Object fieldValue = fieldValues.next(); Assert.assertTrue("Unexpected value '" + fieldValue + " of selected field '" + field + "' of result " + result.getId(),expectedFieldValues.remove(fieldValue)); } Assert.assertTrue("Missing expected value(s) "+ expectedFieldValues + " of selected field '" + field + "' of result " + result.getId(), expectedFieldValues.isEmpty()); } } } Assert.assertTrue("Missing expected result(s) " + expectedResults + "for query" + query +"!", expectedResults.isEmpty()); } /** * Used to validate {@link Yard#findReferences(FieldQuery)} results * @param query the query * @param results the results * @param parsedExpectedResults the expected results */ protected final void validateQueryResults(FieldQuery query, QueryResultList<String> results, Collection<String> parsedExpectedResults) { Set<String> expectedResults = parsedExpectedResults == null ? new HashSet<String>() : new HashSet<String>(parsedExpectedResults); Assert.assertNotNull("NULL result for query "+query+"!", results); for(String id : results){ Assert.assertTrue("Result "+ id + "is missing for Query " + query +"!", expectedResults.remove(id)); } Assert.assertTrue("Missing expected result(s) " + expectedResults + "for query" + query +"!", expectedResults.isEmpty()); } /** * Class representing the test data for the {@link FieldQuery} tests added * by STANBOL-1202 * * @author Rupert Westenthaler * */ protected final class FieldQueryTestData { /** * The field used for {@link Text} values */ protected final String textField; protected final Text textValue1; protected final Text textValue1en; protected final Text textValue1de; protected final Text textValue2; protected final Text textValue2en; protected final Text textValue2de; /** * The field used for {@link Reference} values */ protected final String refField; protected final Reference refValue1; protected final Reference refValue2; /** * The field used for {@link Integer} values */ protected final String intField; protected final Integer intValue1; protected final Integer intValue2; protected final Integer intValue5; protected final Integer intValue10; /* * The Entities created by the test */ /** * Entity with {@link #textValue1}, {@link #refValue1} and * {@link #intValue1} */ protected final Representation r1; /** * Entity with {@link #textValue1en}, {@link #refValue1} and * {@link #intValue1} */ protected final Representation r1en; /** * Entity with {@link #textValue1de}, {@link #refValue1} and * {@link #intValue1} */ protected final Representation r1de; /** * Entity with {@link #textValue2}, {@link #refValue2} and * {@link #intValue2} */ protected final Representation r2; /** * Entity with {@link #textValue2en}, {@link #refValue2} and * {@link #intValue2} */ protected final Representation r2en; /** * Entity with {@link #textValue2de}, {@link #refValue2} and * {@link #intValue2} */ protected final Representation r2de; /** * Entity with {@link #intValue5} and {@link #refValue1} */ protected final Representation r5; /** * Entity with {@link #intValue10} and {@link #refValue2} */ protected final Representation r10; /** * Read-only {@link Map} allowing to lookup {@link Representation}s * used by this Test by {@link Representation#getId() ID}. */ protected final Map<String,Representation> representations; /** * Creates and initializes the query test data for the tested * {@link YardTest#getYard() Yard}. */ private FieldQueryTestData(){ textField = "urn:yard.test:find:field.text"; textValue1 = getYard().getValueFactory().createText("value1", null); textValue1en = getYard().getValueFactory().createText("value1", "en"); textValue1de = getYard().getValueFactory().createText("value1", "de"); textValue2 = getYard().getValueFactory().createText("value2", null); textValue2en = getYard().getValueFactory().createText("value2", "en"); textValue2de = getYard().getValueFactory().createText("value2", "de"); refField = "urn:yard.test:find:field.reference"; refValue1 = getYard().getValueFactory().createReference("urn:yard.test:find:reference1"); refValue2 = getYard().getValueFactory().createReference("urn:yard.test:find:reference2"); intField = "urn:yard.test:find:field.integer"; intValue1 = 1; intValue2 = 2; intValue5 = 5; intValue10 = 10; //and some Representations with a different set of values Map<String,Representation> representations = new HashMap<String, Representation>(); r1 = create("urn:yard.test:find:entity.r1", false); r1.add(textField, textValue1); r1.add(intField, intValue1); r1.add(refField, refValue1); getYard().store(r1); representations.put(r1.getId(), r1); r1en = create("urn:yard.test:find:entity.r1en", false); r1en.add(textField, textValue1en); r1en.add(intField, intValue1); r1en.add(refField, refValue1); getYard().store(r1en); representations.put(r1en.getId(), r1en); r1de = create("urn:yard.test:find:entity.r1de", false); r1de.add(textField, textValue1de); r1de.add(intField, intValue1); r1de.add(refField, refValue1); getYard().store(r1de); representations.put(r1de.getId(), r1de); r2 = create("urn:yard.test:find:entity.r2", false); r2.add(textField, textValue2); r2.add(intField, intValue2); r2.add(refField, refValue2); getYard().store(r2); representations.put(r2.getId(), r2); r2en = create("urn:yard.test:find:entity.r2en", false); r2en.add(textField, textValue2en); r2en.add(intField, intValue2); r2en.add(refField, refValue2); getYard().store(r2en); representations.put(r2en.getId(), r2en); r2de = create("urn:yard.test:find:entity.r2de", false); r2de.add(textField, textValue2de); r2de.add(intField, intValue2); r2de.add(refField, refValue2); getYard().store(r2de); representations.put(r2de.getId(), r2de); r5 = create("urn:yard.test:find:entity.r5", false); r5.add(intField, intValue5); r5.add(refField, refValue1); getYard().store(r5); representations.put(r5.getId(), r5); r10 = create("urn:yard.test:find:entity.r10", false); r10.add(intField, intValue10); r10.add(refField, refValue2); getYard().store(r10); representations.put(r10.getId(), r10); this.representations = Collections.unmodifiableMap(representations); } } /** * Getter for the {@link FieldQueryTestData}. This will also initialize * the data for the tested {@link Yard} * @return the {@link FieldQueryTestData} */ protected final FieldQueryTestData getFieldQueryTestData() { if(fieldQueryTestData == null){ //if not yet initialized for this test //create (and add) the test data for this test fieldQueryTestData = new FieldQueryTestData(); } return fieldQueryTestData; } }