// properties can only be set by constructor, before initialising source features // (for joining nested mappings) private void setPropertyNames(Collection<PropertyName> propertyNames) { selectedProperties = new HashMap<AttributeMapping, List<PropertyName>>(); if (propertyNames == null) { selectedMapping = mapping.getAttributeMappings(); } else { final AttributeDescriptor targetDescriptor = mapping.getTargetFeature(); selectedMapping = new ArrayList<AttributeMapping>(); for (AttributeMapping attMapping : mapping.getAttributeMappings()) { final StepList targetSteps = attMapping.getTargetXPath(); boolean alreadyAdded = false; if (includeMandatory) { PropertyName targetProp = namespaceAwareFilterFactory.property(targetSteps.toString()); Object descr = targetProp.evaluate(targetDescriptor.getType()); if (descr instanceof PropertyDescriptor) { if (((PropertyDescriptor) descr).getMinOccurs() >= 1) { selectedMapping.add(attMapping); selectedProperties.put(attMapping, new ArrayList<PropertyName>()); alreadyAdded = true; } } } for (PropertyName requestedProperty : propertyNames) { StepList requestedPropertySteps; if (requestedProperty.getNamespaceContext() == null) { requestedPropertySteps = XPath.steps(targetDescriptor, requestedProperty.getPropertyName(), namespaces); } else { requestedPropertySteps = XPath.steps( targetDescriptor, requestedProperty.getPropertyName(), requestedProperty.getNamespaceContext()); } if (requestedPropertySteps == null ? AppSchemaDataAccess.matchProperty(requestedProperty.getPropertyName(), targetSteps) : AppSchemaDataAccess.matchProperty(requestedPropertySteps, targetSteps)) { if (!alreadyAdded) { selectedMapping.add(attMapping); selectedProperties.put(attMapping, new ArrayList<PropertyName>()); alreadyAdded = true; } if (requestedPropertySteps != null && requestedPropertySteps.size() > targetSteps.size()) { List<PropertyName> pnList = selectedProperties.get(attMapping); StepList subProperty = requestedPropertySteps.subList(targetSteps.size(), requestedPropertySteps.size()); pnList.add( filterFac.property( subProperty.toString(), requestedProperty.getNamespaceContext())); } } } } } }
protected Object getValues( boolean isMultiValued, Expression expression, Object sourceFeatureInput) { if (isMultiValued && sourceFeatureInput instanceof FeatureImpl && expression instanceof AttributeExpressionImpl) { // RA: Feature Chaining // complex features can have multiple nodes of the same attribute.. and if they are used // as input to an app-schema data access to be nested inside another feature type of a // different XML type, it has to be mapped like this: // <AttributeMapping> // <targetAttribute> // gsml:composition // </targetAttribute> // <sourceExpression> // <inputAttribute>mo:composition</inputAttribute> // <linkElement>gsml:CompositionPart</linkElement> // <linkField>gml:name</linkField> // </sourceExpression> // <isMultiple>true</isMultiple> // </AttributeMapping> // As there can be multiple nodes of mo:composition in this case, we need to retrieve // all of them AttributeExpressionImpl attribExpression = ((AttributeExpressionImpl) expression); String xpath = attribExpression.getPropertyName(); ComplexAttribute sourceFeature = (ComplexAttribute) sourceFeatureInput; StepList xpathSteps = XPath.steps(sourceFeature.getDescriptor(), xpath, namespaces); return getProperties(sourceFeature, xpathSteps); } return expression.evaluate(sourceFeatureInput); }
protected boolean skipTopElement( Name topElement, AttributeMapping attMapping, AttributeType type) { // don't skip if there's OCQL return XPath.equals(topElement, attMapping.getTargetXPath()) && (attMapping.getSourceExpression() == null || Expression.NIL.equals(attMapping.getSourceExpression())); }
/** * * * <pre> * </pre> * * @param targetFeature * @return * @throws Exception */ public static List /* <AttributeMapping> */ createMappingsColumnsAndValues( AttributeDescriptor targetFeature) throws Exception { List mappings = new LinkedList(); AttributeMapping attMapping; Expression source; String target; FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); source = ff.literal("ph"); target = "sample/measurement[1]/parameter"; // empty nssupport as the test properties have no namespace NamespaceSupport namespaces = new NamespaceSupport(); attMapping = new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces)); mappings.add(attMapping); source = ff.property("ph"); target = "sample/measurement[1]/value"; attMapping = new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces)); mappings.add(attMapping); source = ff.literal("temp"); target = "sample/measurement[2]/parameter"; attMapping = new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces)); mappings.add(attMapping); source = ff.property("temp"); target = "sample/measurement[2]/value"; attMapping = new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces)); mappings.add(attMapping); source = ff.literal("turbidity"); target = "sample/measurement[3]/parameter"; attMapping = new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces)); mappings.add(attMapping); source = ff.property("turbidity"); target = "sample/measurement[3]/value"; attMapping = new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces)); mappings.add(attMapping); return mappings; }
protected Attribute setAttributeContent( Attribute target, StepList xpath, Object value, String id, AttributeType targetNodeType, boolean isXlinkRef, Expression sourceExpression, Object source, final Map<Name, Expression> clientProperties, boolean ignoreXlinkHref) { Attribute instance = null; Map<Name, Expression> properties = new HashMap<Name, Expression>(clientProperties); if (ignoreXlinkHref) { properties.remove(XLINK_HREF_NAME); } if (properties.containsKey(XLINK_HREF_NAME) && resolveDepth > 0) { // local resolve String refid = referenceToIdentifier(getValue(properties.get(XLINK_HREF_NAME), source).toString()); if (refid != null) { final Hints hints = new Hints(); if (resolveDepth > 1) { hints.put(Hints.RESOLVE, ResolveValueType.ALL); // only the top-level resolve thread should monitor timeout hints.put(Hints.RESOLVE_TIMEOUT, Integer.MAX_VALUE); hints.put(Hints.ASSOCIATION_TRAVERSAL_DEPTH, resolveDepth - 1); } else { hints.put(Hints.RESOLVE, ResolveValueType.NONE); } // let's try finding it FeatureFinder finder = new FeatureFinder(refid, hints); // this will be null if joining or sleeping is interrupted Feature foundFeature = null; if (resolveTimeOut == Integer.MAX_VALUE) { // not the top-level resolve thread so do not monitor timeout finder.run(); foundFeature = finder.getFeature(); } else { Thread thread = new Thread(finder); long startTime = System.currentTimeMillis(); thread.start(); try { while (thread.isAlive() && (System.currentTimeMillis() - startTime) / 1000 < resolveTimeOut) { Thread.sleep(RESOLVE_TIMEOUT_POLL_INTERVAL); } thread.interrupt(); // joining ensures synchronisation thread.join(); foundFeature = finder.getFeature(); } catch (InterruptedException e) { // clean up as best we can thread.interrupt(); throw new RuntimeException("Interrupted while resolving resource " + refid); } } if (foundFeature != null) { // found it instance = xpathAttributeBuilder.set( target, xpath, Collections.singletonList(foundFeature), id, targetNodeType, false, sourceExpression); properties.remove(XLINK_HREF_NAME); } } } if (instance == null) { instance = xpathAttributeBuilder.set( target, xpath, value, id, targetNodeType, false, sourceExpression); } setClientProperties(instance, source, properties); return instance; }
public AbstractMappingFeatureIterator( AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, Query unrolledQuery, boolean removeQueryLimitIfDenormalised, boolean hasPostFilter) throws IOException { this.store = store; this.attf = new AppSchemaFeatureFactoryImpl(); this.mapping = mapping; // validate and initialise resolve options Hints hints = query.getHints(); ResolveValueType resolveVal = (ResolveValueType) hints.get(Hints.RESOLVE); boolean resolve = ResolveValueType.ALL.equals(resolveVal) || ResolveValueType.LOCAL.equals(resolveVal); if (!resolve && resolveVal != null && !ResolveValueType.NONE.equals(resolveVal)) { throw new IllegalArgumentException( "Resolve:" + resolveVal.getName() + " is not supported in app-schema!"); } Integer atd = (Integer) hints.get(Hints.ASSOCIATION_TRAVERSAL_DEPTH); resolveDepth = resolve ? atd == null ? 0 : atd : 0; resolveTimeOut = (Integer) hints.get(Hints.RESOLVE_TIMEOUT); namespaces = mapping.getNamespaces(); namespaceAwareFilterFactory = new FilterFactoryImplNamespaceAware(namespaces); Object includeProps = query.getHints().get(Query.INCLUDE_MANDATORY_PROPS); includeMandatory = includeProps instanceof Boolean && ((Boolean) includeProps).booleanValue(); if (mapping.isDenormalised()) { // we need to disable the max number of features retrieved so we can // sort them manually just in case the data is denormalised. Do this // by overriding the max features for this query just before executing // it. Note that the original maxFeatures value was copied to // this.requestMaxFeatures in the constructor and will be re-applied after // the rows have been returned if (removeQueryLimitIfDenormalised) { this.dataMaxFeatures = 1000000; if (hasPostFilter) { // true max features will be handled in PostFilteringMappingFeatureIterator this.requestMaxFeatures = 1000000; } else { this.requestMaxFeatures = query.getMaxFeatures(); } } else { this.dataMaxFeatures = query.getMaxFeatures(); this.requestMaxFeatures = query.getMaxFeatures(); } } else { this.requestMaxFeatures = query.getMaxFeatures(); this.dataMaxFeatures = query.getMaxFeatures(); } if (unrolledQuery == null) { unrolledQuery = getUnrolledQuery(query); if (query instanceof JoiningQuery && unrolledQuery instanceof JoiningQuery) { ((JoiningQuery) unrolledQuery).setRootMapping(((JoiningQuery) query).getRootMapping()); } } // NC - property names if (query != null && query.getProperties() != null) { setPropertyNames(query.getProperties()); } else { setPropertyNames(null); // we need the actual property names (not surrogates) to do // this... } xpathAttributeBuilder = new XPath(); xpathAttributeBuilder.setFeatureFactory(attf); initialiseSourceFeatures(mapping, unrolledQuery, query.getCoordinateSystemReproject()); xpathAttributeBuilder.setFilterFactory(namespaceAwareFilterFactory); }
/** * Flat FeatureType: * * <ul> * wq_ir_results * <li>station_no * <li>sitename * <li>anzlic_no * <li>project_no * <li>id * <li>sample_collection_date * <li>determinand_description * <li>results_value * <li>location * </ul> * * <p>Complex type: * * <ul> * wq_plus * <li>sitename * <li>anzlic_no * <li>project_no * <li>location * <li>measurement (0..*) * <ul> * <li>determinand_description * <li>result * </ul> * </ul> * * <p>Mappings definition: * * <pre> * <strong>wq_ir_results</strong> <strong>wq_plus</strong> * station_no --> wq_plus@id * sitename --> sitename * anzlic_no --> anzlic_no * project_no --> project_no * id --> measurement/@id * sample_collection_date--> [not used] * determinand_description-->measurement/determinand_description * results_value -->measurement/result * location -->location * </pre> * * @param simpleStore * @return * @throws Exception */ public static FeatureTypeMapping createMappingsGroupByStation(MemoryDataStore simpleStore) throws Exception { Name sourceTypeName = WATERSAMPLE_TYPENAME; final SimpleFeatureSource wsSource = simpleStore.getFeatureSource(sourceTypeName); FeatureType targetType = createComplexWaterQualityType(); FeatureTypeFactory tf = new UniqueNameFeatureTypeFactoryImpl(); AttributeDescriptor targetFeature = tf.createAttributeDescriptor( targetType, targetType.getName(), 0, Integer.MAX_VALUE, true, null); List mappings = new LinkedList(); Expression id; Expression source; String target; FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); id = ff.property("station_no"); source = Expression.NIL; target = "wq_plus"; NamespaceSupport namespaces = new NamespaceSupport(); mappings.add(new AttributeMapping(id, source, XPath.steps(targetFeature, target, namespaces))); source = ff.property("sitename"); target = "wq_plus/sitename"; mappings.add( new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces))); source = ff.property("anzlic_no"); target = "wq_plus/anzlic_no"; mappings.add( new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces))); source = ff.property("project_no"); target = "wq_plus/project_no"; mappings.add( new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces))); id = ff.property("id[1]"); source = null; target = "wq_plus/measurement"; mappings.add( new AttributeMapping( id, source, XPath.steps(targetFeature, target, namespaces), null, true, null)); source = ff.property("determinand_description"); target = "wq_plus/measurement/determinand_description"; mappings.add( new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces))); source = ff.property("results_value"); target = "wq_plus/measurement/result"; mappings.add( new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces))); source = ff.property("location"); target = "wq_plus/location"; mappings.add( new AttributeMapping(null, source, XPath.steps(targetFeature, target, namespaces))); return new FeatureTypeMapping(wsSource, targetFeature, mappings, namespaces); }
public NestedAttributeExpression(Expression expression, FeatureTypeMapping mappings) { super(expression.toString()); this.mappings = mappings; fullSteps = XPath.steps(mappings.getTargetFeature(), this.attPath.toString(), mappings.getNamespaces()); }