/** * Implementation for tests of fid -> fid unmapping. * * @param idExpression * @throws Exception */ private void checkUnrollIdExpression(Expression idExpression) throws Exception { AttributeMapping featureMapping = null; Name featurePath = mapping.getTargetFeature().getName(); QName featureName = Types.toQName(featurePath); for (Iterator it = mapping.getAttributeMappings().iterator(); it.hasNext(); ) { AttributeMapping attMapping = (AttributeMapping) it.next(); StepList targetXPath = attMapping.getTargetXPath(); if (targetXPath.size() > 1) { continue; } Step step = (Step) targetXPath.get(0); if (featureName.equals(step.getName())) { featureMapping = attMapping; break; } } featureMapping.setIdentifierExpression(idExpression); this.visitor = new UnmappingFilterVisitor(this.mapping); // retrieve a single sample feature Feature sourceFeature = DataUtilities.first(mapping.getSource().getFeatures()); String fid = sourceFeature.getIdentifier().toString(); Id fidFilter = ff.id(Collections.singleton(ff.featureId(fid))); Filter unrolled = (Filter) fidFilter.accept(visitor, null); assertNotNull(unrolled); assertTrue(unrolled instanceof Id); FeatureCollection<SimpleFeatureType, SimpleFeature> results = mapping.getSource().getFeatures(unrolled); assertEquals(1, getCount(results)); SimpleFeature unmappedFeature = DataUtilities.first(results); assertEquals(fid, unmappedFeature.getID()); }
private void setIdValues(AttributeMapping mapping, List<Feature> features, List<Object> values) { Expression exp = null; if (mapping == null || mapping.getIdentifierExpression() == Expression.NIL) { // no specific attribute mapping or that idExpression is not mapped // use primary key exp = CommonFactoryFinder.getFilterFactory(null).property("@id"); } else { exp = mapping.getIdentifierExpression(); } if (exp != null) { for (Feature f : features) { Object value = getValue(exp, f); if (value != null) { values.add(value); } } } }
/** * Find the source expression if the step is a client property. * * @param nextRootStep the step * @param fMapping feature type mapping to get namespaces from * @param mapping attribute mapping * @param targetXPath the full target xpath * @return */ private Expression getClientPropertyExpression(AttributeMapping mapping, Step lastStep) { if (lastStep.isXmlAttribute()) { Map<Name, Expression> clientProperties = mapping.getClientProperties(); QName lastStepQName = lastStep.getName(); Name lastStepName; if (lastStepQName.getPrefix() != null && lastStepQName.getPrefix().length() > 0 && (lastStepQName.getNamespaceURI() == null || lastStepQName.getNamespaceURI().length() == 0)) { String prefix = lastStepQName.getPrefix(); String uri = namespaceSupport.getURI(prefix); lastStepName = Types.typeName(uri, lastStepQName.getLocalPart()); } else { lastStepName = Types.toTypeName(lastStepQName); } if (clientProperties.containsKey(lastStepName)) { // end NC - added return (Expression) clientProperties.get(lastStepName); } } return null; }
private List<Object> getValues( int startIndex, int endIndex, List<Feature> roots, FeatureTypeMapping fMapping, AttributeMapping prevMapping) { List<Object> values = new ArrayList<Object>(); if (startIndex > fullSteps.size() || endIndex > fullSteps.size()) { return values; } while (startIndex <= endIndex) { List<AttributeMapping> attMappings = new ArrayList<AttributeMapping>(); StepList steps = null; if (isLastStep(endIndex)) { // exhausted all paths return values; } while (attMappings.isEmpty() && endIndex < fullSteps.size()) { endIndex++; steps = fullSteps.subList(startIndex, endIndex); attMappings = fMapping.getAttributeMappingsIgnoreIndex(steps); if (steps.size() == 1) { if (Types.equals(fMapping.getTargetFeature().getName(), steps.get(0).getName()) && !(Types.isSimpleContentType(fMapping.getTargetFeature().getType()))) { // skip element type name, but not when it's a simple content // like gml:name because it wouldn't have the element type name in the xpath startIndex++; endIndex = startIndex; steps = fullSteps.subList(startIndex, endIndex); attMappings = fMapping.getAttributeMappingsIgnoreIndex(steps); continue; } else if (attMappings.isEmpty() && steps.get(0).isId()) { // sometimes there's no explicit attribute mapping for top element name // but id should still resolve to primary key by default // e.g. gsml:GeologicUnit/@gml:id should resolve even though there's no // AttributeMapping for gsml:GeologicUnit setIdValues(null, roots, values); return values; } } } if (attMappings.isEmpty()) { // not found here, but might be found in other nodes if multi-valued // and polymorphic continue; } for (AttributeMapping mapping : attMappings) { if (mapping instanceof NestedAttributeMapping) { if (isClientProperty(endIndex)) { // check for client properties boolean isNestedXlinkHref = isXlinkHref(mapping); boolean valueFound = false; if (!isNestedXlinkHref) { // check if client properties are set in the parent attributeMapping in root mapping // file valueFound = getClientProperties(mapping, values, roots); } if (!valueFound) { // or if they're set in the attributeMapping in feature chained mapping file getNestedClientProperties( (NestedAttributeMapping) mapping, roots, values, isNestedXlinkHref); } } else { boolean isSimpleContent = Types.isSimpleContent(steps, fMapping.getTargetFeature().getType()); // if simple content, then it doesn't need to increment the next starting // index // since there will be no type name in the xpath, e.g. when gml:name is // feature // chained // the path stays as gml:name.. but if it's a complex type with complex // content, // e.g. gsml:specification // the path will be gsml:specification/gsml:GeologicUnit/<some leaf // attribute to // filter by> getNestedValues( (NestedAttributeMapping) mapping, roots, values, isSimpleContent ? startIndex : startIndex + 1); } } else { // normal attribute mapping if (endIndex == fullSteps.size()) { Expression exp = mapping.getSourceExpression(); for (Feature f : roots) { Object value = getValue(exp, f); if (value != null) { values.add(value); } } } else if (isClientProperty(endIndex)) { // peek at the next attribute to check for client properties if (getLastStep().isId()) { setIdValues(mapping, roots, values); } else { getClientProperties(mapping, values, roots); } } else { // increment the xpath List<Object> nestedValues = getValues(startIndex, endIndex, roots, fMapping, mapping); if (nestedValues != null) { values.addAll(nestedValues); } } } } return values; } return values; }