001: /*
002: * Geotools2 - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: package org.geotools.data.complex;
018:
019: import java.io.IOException;
020: import java.net.URL;
021: import java.util.Collection;
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.Set;
027: import java.util.Map.Entry;
028: import java.util.logging.Level;
029: import java.util.logging.Logger;
030:
031: import junit.framework.TestCase;
032:
033: import org.geotools.data.DataAccessFinder;
034: import org.geotools.data.complex.config.ComplexDataStoreConfigurator;
035: import org.geotools.data.complex.config.ComplexDataStoreDTO;
036: import org.geotools.data.complex.config.EmfAppSchemaReader;
037: import org.geotools.data.complex.config.XMLConfigDigester;
038: import org.geotools.data.complex.filter.XPath.StepList;
039: import org.geotools.data.feature.FeatureAccess;
040: import org.geotools.data.feature.FeatureSource2;
041: import org.geotools.feature.iso.Types;
042: import org.geotools.filter.FilterFactoryImplNamespaceAware;
043: import org.geotools.xlink.bindings.XLINK;
044: import org.opengis.feature.Attribute;
045: import org.opengis.feature.ComplexAttribute;
046: import org.opengis.feature.Feature;
047: import org.opengis.feature.FeatureCollection;
048: import org.opengis.feature.type.AttributeDescriptor;
049: import org.opengis.feature.type.AttributeType;
050: import org.opengis.feature.type.ComplexType;
051: import org.opengis.feature.type.FeatureType;
052: import org.opengis.feature.type.Name;
053: import org.opengis.filter.Filter;
054: import org.opengis.filter.FilterFactory2;
055: import org.opengis.filter.expression.Expression;
056: import org.opengis.filter.expression.Function;
057: import org.opengis.filter.expression.Literal;
058: import org.opengis.filter.expression.PropertyName;
059: import org.xml.sax.helpers.NamespaceSupport;
060:
061: /**
062: * DOCUMENT ME!
063: *
064: * @author Gabriel Roldan, Axios Engineering
065: * @version $Id: BoreholeTest.java 28577 2008-01-03 15:44:29Z groldan $
066: * @source $URL:
067: * http://svn.geotools.org/geotools/branches/2.4.x/modules/unsupported/community-schemas/community-schema-ds/src/test/java/org/geotools/data/complex/BoreholeTest.java $
068: * @since 2.4
069: */
070: public class BoreholeTest extends TestCase {
071: private static final Logger LOGGER = org.geotools.util.logging.Logging
072: .getLogger(BoreholeTest.class.getPackage().getName());
073:
074: private static final String XMMLNS = "http://www.opengis.net/xmml";
075:
076: private static final String SANS = "http://www.seegrid.csiro.au/xml/sampling";
077:
078: private static final String OMNS = "http://www.opengis.net/om";
079:
080: private static final String SWENS = "http://www.opengis.net/swe/0.0";
081:
082: private static final String GMLNS = "http://www.opengis.net/gml";
083:
084: private static final String GEONS = "http://www.seegrid.csiro.au/xml/geometry";
085:
086: final String schemaBase = "/test-data/";
087:
088: final Name typeName = new org.geotools.feature.Name(XMMLNS,
089: "Borehole");
090:
091: EmfAppSchemaReader reader;
092:
093: private FeatureSource2 source;
094:
095: /**
096: * DOCUMENT ME!
097: *
098: * @throws Exception
099: * DOCUMENT ME!
100: */
101: protected void setUp() throws Exception {
102: super .setUp();
103: reader = EmfAppSchemaReader.newInstance();
104: // Logging.GEOTOOLS.forceMonolineConsoleOutput(Level.FINEST);
105: }
106:
107: /**
108: * DOCUMENT ME!
109: *
110: * @throws Exception
111: * DOCUMENT ME!
112: */
113: protected void tearDown() throws Exception {
114: super .tearDown();
115: }
116:
117: /**
118: *
119: * @param location
120: * schema location path discoverable through
121: * getClass().getResource()
122: */
123: private void loadSchema(String location) throws IOException {
124: // load needed GML types directly from the gml schemas
125: URL schemaLocation = getClass().getResource(location);
126: assertNotNull(location, schemaLocation);
127: reader.parse(schemaLocation);
128: }
129:
130: /**
131: * Tests if the schema-to-FM parsing code developed for complex datastore
132: * configuration loading can parse the GeoSciML types
133: *
134: * @throws Exception
135: */
136: public void testParseBoreholeSchema() throws Exception {
137: /*
138: * not found types and elements:
139: */
140:
141: // load geosciml schema
142: try {
143: loadSchema(schemaBase + "commonSchemas/XMML/1/borehole.xsd");
144: } catch (Exception e) {
145: e.printStackTrace();
146: throw e;
147: }
148:
149: Map typeRegistry = reader.getTypeRegistry();
150:
151: Name typeName = Types.typeName(XMMLNS, "BoreholeType");
152: ComplexType borehole = (ComplexType) typeRegistry.get(typeName);
153: assertNotNull(borehole);
154: assertTrue(borehole instanceof FeatureType);
155:
156: AttributeType super Type = borehole.getSuper();
157: assertNotNull(super Type);
158: Name super TypeName = Types.typeName(SANS, "ProfileType");
159: assertEquals(super TypeName, super Type.getName());
160: assertTrue(super Type instanceof FeatureType);
161:
162: // ensure all needed types were parsed and aren't just empty proxies
163: Collection properties = borehole.getProperties();
164: assertEquals(16, properties.size());
165: Map expectedNamesAndTypes = new HashMap();
166: // from gml:AbstractFeatureType
167: expectedNamesAndTypes.put(name(GMLNS, "metaDataProperty"),
168: typeName(GMLNS, "MetaDataPropertyType"));
169: expectedNamesAndTypes.put(name(GMLNS, "description"), typeName(
170: GMLNS, "StringOrRefType"));
171: expectedNamesAndTypes.put(name(GMLNS, "name"), typeName(GMLNS,
172: "CodeType"));
173: expectedNamesAndTypes.put(name(GMLNS, "boundedBy"), typeName(
174: GMLNS, "BoundingShapeType"));
175: expectedNamesAndTypes.put(name(GMLNS, "location"), typeName(
176: GMLNS, "LocationPropertyType"));
177: // from sa:ProfileType
178: expectedNamesAndTypes.put(name(SANS, "begin"), typeName(GMLNS,
179: "PointPropertyType"));
180: expectedNamesAndTypes.put(name(SANS, "end"), typeName(GMLNS,
181: "PointPropertyType"));
182: expectedNamesAndTypes.put(name(SANS, "length"), typeName(SWENS,
183: "RelativeMeasureType"));
184: expectedNamesAndTypes.put(name(SANS, "shape"), typeName(GEONS,
185: "Shape1DPropertyType"));
186: // sa:SamplingFeatureType
187: expectedNamesAndTypes.put(name(SANS, "member"), typeName(SANS,
188: "SamplingFeaturePropertyType"));
189: expectedNamesAndTypes.put(name(SANS, "surveyDetails"),
190: typeName(SANS, "SurveyProcedurePropertyType"));
191: expectedNamesAndTypes.put(name(SANS, "associatedSpecimen"),
192: typeName(SANS, "SpecimenPropertyType"));
193: expectedNamesAndTypes.put(name(SANS, "relatedObservation"),
194: typeName(OMNS, "AbstractObservationPropertyType"));
195: // from xmml:BoreholeType
196: expectedNamesAndTypes.put(name(XMMLNS, "drillMethod"),
197: typeName(XMMLNS, "drillCode"));
198: expectedNamesAndTypes.put(name(XMMLNS, "collarDiameter"),
199: typeName(GMLNS, "MeasureType"));
200: expectedNamesAndTypes.put(name(XMMLNS, "log"), typeName(XMMLNS,
201: "LogPropertyType"));
202:
203: for (Iterator it = expectedNamesAndTypes.entrySet().iterator(); it
204: .hasNext();) {
205: Map.Entry entry = (Entry) it.next();
206: Name dName = (Name) entry.getKey();
207: Name tName = (Name) entry.getValue();
208:
209: AttributeDescriptor d = (AttributeDescriptor) Types
210: .descriptor(borehole, dName);
211: assertNotNull("Descriptor not found: " + dName, d);
212: AttributeType type;
213: try {
214: type = (AttributeType) d.type();
215: } catch (Exception e) {
216: LOGGER.log(Level.SEVERE, "type not parsed for "
217: + ((AttributeDescriptor) d).getName(), e);
218: throw e;
219: }
220: assertNotNull(type);
221: assertNotNull(type.getName());
222: assertNotNull(type.getBinding());
223: if (tName != null) {
224: assertEquals(tName, type.getName());
225: }
226: }
227:
228: Name tcl = Types.typeName(SWENS, "TypedCategoryListType");
229: AttributeType typedCategoryListType = (AttributeType) typeRegistry
230: .get(tcl);
231: assertNotNull(typedCategoryListType);
232: assertFalse(typedCategoryListType instanceof ComplexType);
233: }
234:
235: private Name typeName(String ns, String localName) {
236: return Types.typeName(ns, localName);
237: }
238:
239: private Object name(String ns, String localName) {
240: return new org.geotools.feature.Name(ns, localName);
241: }
242:
243: public void testLoadMappingsConfig() throws Exception {
244: XMLConfigDigester reader = new XMLConfigDigester();
245: URL url = getClass().getResource(
246: schemaBase + "BoreholeTest_properties.xml");
247:
248: ComplexDataStoreDTO config = reader.parse(url);
249:
250: Set mappings = ComplexDataStoreConfigurator
251: .buildMappings(config);
252:
253: assertNotNull(mappings);
254: assertEquals(1, mappings.size());
255:
256: FeatureTypeMapping mapping = (FeatureTypeMapping) mappings
257: .iterator().next();
258:
259: AttributeDescriptor targetFeature = mapping.getTargetFeature();
260: assertNotNull(targetFeature);
261: assertNotNull(targetFeature.type());
262: assertEquals(XMMLNS, targetFeature.getName().getNamespaceURI());
263: assertEquals("Borehole", targetFeature.getName().getLocalPart());
264:
265: source = mapping.getSource();
266: assertNotNull(source);
267: org.geotools.feature.FeatureType schema = source.getSchema();
268: String typeName = schema.getTypeName();
269: assertEquals("boreholes_denormalized", typeName);
270:
271: List groupingAttributes = mapping.getGroupByAttNames();
272:
273: assertEquals(4, groupingAttributes.size());
274:
275: assertTrue(groupingAttributes.contains("QS"));
276: assertTrue(groupingAttributes.contains("NUMB"));
277: assertTrue(groupingAttributes.contains("BSUFF"));
278: assertTrue(groupingAttributes.contains("RT"));
279: /*
280: * assertTrue(groupingAttributes.contains("BGS_ID"));
281: * assertTrue(groupingAttributes.contains("NAME"));
282: * assertTrue(groupingAttributes.contains("ORIGINAL_N"));
283: * assertTrue(groupingAttributes.contains("CONFIDENTI"));
284: * assertTrue(groupingAttributes.contains("LENGTHC"));
285: * assertTrue(groupingAttributes.contains("SHAPE"));
286: */
287:
288: List attributeMappings = mapping.getAttributeMappings();
289: assertEquals(24, attributeMappings.size());
290:
291: AttributeMapping attMapping = (AttributeMapping) attributeMappings
292: .get(0);
293: assertNotNull(attMapping);
294: StepList targetXPath = attMapping.getTargetXPath();
295: assertNotNull(targetXPath);
296: assertEquals("xmml:Borehole", targetXPath.toString());
297:
298: Expression idExpression = attMapping.getIdentifierExpression();
299: assertNotNull(idExpression);
300: assertTrue(idExpression instanceof Function);
301: Function idFunction = (Function) idExpression;
302: assertEquals("strConcat", idFunction.getName());
303: assertTrue(idFunction.getParameters().get(0) instanceof Literal);
304: assertTrue(idFunction.getParameters().get(1) instanceof PropertyName);
305:
306: assertEquals(Expression.NIL, attMapping.getSourceExpression());
307: }
308:
309: public void testGetDataStore() throws Exception {
310: FeatureAccess mappingDataStore = getDataStore();
311: AttributeDescriptor borehole = (AttributeDescriptor) mappingDataStore
312: .describe(typeName);
313: assertNotNull(borehole);
314: assertTrue(borehole.type() instanceof FeatureType);
315: FeatureType boreholeType = (FeatureType) borehole.type();
316: }
317:
318: public void testDataStore() throws Exception {
319: try {
320: FeatureAccess mappingDataStore = getDataStore();
321: FeatureSource2 fSource = (FeatureSource2) mappingDataStore
322: .access(typeName);
323:
324: // make a getFeatures request with a nested properties filter.
325: // note that the expected result count is set to 65 since that's the
326: // number
327: // of results I get from a sql select on min_time_d = 'carnian'
328: final int EXPECTED_RESULT_COUNT = 10;
329:
330: FeatureCollection features = (FeatureCollection) fSource
331: .content();
332:
333: int resultCount = getCount(features);
334: String msg = "be sure difference in result count is not due to different dataset."
335: + " Query used should be min_time_d = 'carnian'";
336: assertEquals(msg, EXPECTED_RESULT_COUNT, resultCount);
337:
338: Feature feature;
339: int count = 0;
340: Iterator it = features.iterator();
341: for (; it.hasNext();) {
342: feature = (Feature) it.next();
343: count++;
344: }
345: features.close(it);
346: assertEquals(EXPECTED_RESULT_COUNT, count);
347: } catch (Exception e) {
348: e.printStackTrace();
349: throw e;
350: }
351: }
352:
353: public void testQueryXlinkProperty() throws Exception {
354: try {
355: final FeatureAccess mappingDataStore = getDataStore();
356: final FeatureSource2 fSource = (FeatureSource2) mappingDataStore
357: .access(typeName);
358: final String queryProperty = "sa:shape/geo:LineByVector/geo:origin/@xlink:href";
359: final String queryLiteral = "#bh.176909.start";
360:
361: NamespaceSupport namespaces = new NamespaceSupport();
362: namespaces.declarePrefix("sa", SANS);
363: namespaces.declarePrefix("geo", GEONS);
364: namespaces.declarePrefix("xlink", XLINK.NAMESPACE);
365:
366: final FilterFactory2 ff = new FilterFactoryImplNamespaceAware(
367: namespaces);
368: final PropertyName propertyName = ff
369: .property(queryProperty);
370: final Literal literal = ff.literal(queryLiteral);
371:
372: final Filter filter = ff.equals(propertyName, literal);
373:
374: FeatureCollection features = (FeatureCollection) fSource
375: .content(filter);
376:
377: //did the query work?
378: int resultCount = getCount(features);
379: assertEquals(1, resultCount);
380:
381: //the datastore performed the query by unmapping the client property
382: //to its corresponding source expression, as defined in the AttributeMapping
383: //clientProperties.
384: //Now the Filter is able to evaluate the property name?
385:
386: //TODO: not sure why AttributePropertyHandler is not catching up at expression evaluation
387: // Feature feature = (Feature)features.iterator().next();
388: // String obtainedValue = (String) propertyName.evaluate(feature);
389: // assertNotNull(obtainedValue);
390: // assertEquals(queryLiteral, obtainedValue);
391: } catch (Exception e) {
392: e.printStackTrace();
393: throw e;
394: }
395: }
396:
397: /**
398: * Grab a feature and traverse it in deep as an encoder might do
399: * @throws Exception
400: */
401: public void testTraverseDeep() throws Exception {
402: try {
403: final FeatureAccess mappingDataStore = getDataStore();
404: final FeatureSource2 fSource = (FeatureSource2) mappingDataStore
405: .access(typeName);
406: final String queryProperty = "sa:shape/geo:LineByVector/geo:origin/@xlink:href";
407: final String queryLiteral = "#bh.176909.start";
408:
409: NamespaceSupport namespaces = new NamespaceSupport();
410: namespaces.declarePrefix("sa", SANS);
411: namespaces.declarePrefix("geo", GEONS);
412: namespaces.declarePrefix("xlink", XLINK.NAMESPACE);
413:
414: FeatureCollection features = (FeatureCollection) fSource
415: .content();
416: Feature f = (Feature) features.iterator().next();
417: traverse(f);
418: } catch (Exception e) {
419: e.printStackTrace();
420: throw e;
421: }
422: }
423:
424: private void traverse(Attribute f) {
425: Object value;
426: value = f.getValue();
427: if (f instanceof ComplexAttribute) {
428: Collection values = (Collection) value;
429: for (Iterator it = values.iterator(); it.hasNext();) {
430: Attribute att = (Attribute) it.next();
431: assertNotNull(att);
432: traverse(att);
433: }
434: }
435: }
436:
437: private FeatureAccess getDataStore() throws IOException {
438: final Map dsParams = new HashMap();
439: final URL url = getClass().getResource(
440: schemaBase + "BoreholeTest_properties.xml");
441: dsParams.put("dbtype", "complex");
442: dsParams.put("url", url.toExternalForm());
443:
444: FeatureAccess mappingDataStore = (FeatureAccess) DataAccessFinder
445: .createAccess(dsParams);
446: assertNotNull(mappingDataStore);
447: return mappingDataStore;
448: }
449:
450: private int getCount(FeatureCollection features) {
451: Iterator iterator = features.iterator();
452: int count = 0;
453: try {
454: while (iterator.hasNext()) {
455: iterator.next();
456: count++;
457: }
458: } finally {
459: features.close(iterator);
460: }
461: return count;
462: }
463:
464: }
|