Source Code Cross Referenced for GroupingFeatureIterator.java in  » GIS » GeoTools-2.4.1 » org » geotools » data » complex » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoTools 2.4.1 » org.geotools.data.complex 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:
018:        package org.geotools.data.complex;
019:
020:        import java.io.IOException;
021:        import java.util.ArrayList;
022:        import java.util.Arrays;
023:        import java.util.HashMap;
024:        import java.util.HashSet;
025:        import java.util.Iterator;
026:        import java.util.LinkedList;
027:        import java.util.List;
028:        import java.util.Map;
029:        import java.util.Set;
030:        import java.util.logging.Logger;
031:
032:        import javax.xml.namespace.QName;
033:
034:        import org.geotools.data.DefaultQuery;
035:        import org.geotools.data.Query;
036:        import org.geotools.data.complex.filter.XPath;
037:        import org.geotools.data.complex.filter.XPath.Step;
038:        import org.geotools.data.complex.filter.XPath.StepList;
039:        import org.geotools.feature.iso.AttributeFactoryImpl;
040:        import org.geotools.feature.iso.Types;
041:        import org.geotools.filter.FilterAttributeExtractor;
042:        import org.geotools.filter.FilterFactoryImplNamespaceAware;
043:        import org.opengis.feature.Attribute;
044:        import org.opengis.feature.ComplexAttribute;
045:        import org.opengis.feature.Feature;
046:        import org.opengis.feature.FeatureFactory;
047:        import org.opengis.feature.type.AttributeDescriptor;
048:        import org.opengis.feature.type.AttributeType;
049:        import org.opengis.feature.type.Name;
050:        import org.opengis.filter.FilterFactory;
051:        import org.opengis.filter.expression.Expression;
052:        import org.xml.sax.Attributes;
053:        import org.xml.sax.helpers.NamespaceSupport;
054:
055:        /**
056:         * 
057:         * A Feature can be stored in many tables of database. Restoring that feature
058:         * may be did by join, the resulting table can be explored using this iterator
059:         * class. This iterator return Features with simple or complex attributes.
060:         * <p>
061:         * In the FeatureTypeMapping must be defined the grouping attributes, this value
062:         * will be used to distinguish different features in the data sotore.
063:         * </p>
064:         * <p>
065:         * The next can be a posible data store. <table>
066:         * <tr>
067:         * <td> station_no (string) </td>
068:         * <td> sitename (string)</td>
069:         * <td> anzlic_no (string)</td>
070:         * <td> project_no (string)</td>
071:         * <td> id (string)</td>
072:         * <td> sample_collection_date (string)</td>
073:         * <td> determinand_description (string)</td>
074:         * <td> results_value (float)</td>
075:         * <td> location (Point)</td>
076:         * </tr>
077:         * <tr>
078:         * <td> station_1 </td>
079:         * <td> sitename_1 </td>
080:         * <td> anzlic_no_1 </td>
081:         * <td> project_no_1 </td>
082:         * <td> id_1_1 </td>
083:         * <td> sample_collection_date_1_1 </td>
084:         * <td> determinand_description_1_1 </td>
085:         * <td> 1.1 </td>
086:         * <td> POINT(1, 1) </td>
087:         * </tr>
088:         * <tr>
089:         * <td> station_2 </td>
090:         * <td> sitename_2 </td>
091:         * <td> anzlic_no_2 </td>
092:         * <td> project_no_2 </td>
093:         * <td> id_2_1 </td>
094:         * <td> sample_collection_date_2_1 </td>
095:         * <td> determinand_description_2_1 </td>
096:         * <td> 2.1 </td>
097:         * <td> POINT(2, 2) </td>
098:         * </tr>
099:         * <tr>
100:         * <td> station_2 </td>
101:         * <td> sitename_2 </td>
102:         * <td> anzlic_no_2 </td>
103:         * <td> project_no_2 </td>
104:         * <td> id_2_2 </td>
105:         * <td> sample_collection_date_2_2 </td>
106:         * <td> determinand_description_2_2 </td>
107:         * <td> 2.2 </td>
108:         * <td> POINT(2, 2) </td>
109:         * </tr>
110:         * <tr>
111:         * <td colspan="9">...</td>
112:         * </tr>
113:         * <tr>
114:         * <td> station_10 </td>
115:         * <td> sitename_10 </td>
116:         * <td> anzlic_no_10 </td>
117:         * <td> project_no_10 </td>
118:         * <td> id_10_10 </td>
119:         * <td> sample_collection_date_10_9 </td>
120:         * <td> determinand_description_10_9 </td>
121:         * <td> 10.10 </td>
122:         * <td> POINT(10, 10) </td>
123:         * </tr>
124:         * <tr>
125:         * <td> station_10 </td>
126:         * <td> sitename_10 </td>
127:         * <td> anzlic_no_10 </td>
128:         * <td> project_no_10 </td>
129:         * <td> id_10_10 </td>
130:         * <td> sample_collection_date_10_10 </td>
131:         * <td> determinand_description_10_10 </td>
132:         * <td> 10.10 </td>
133:         * <td> POINT(10, 10) </td>
134:         * </tr>
135:         * </table>
136:         * </p>
137:         * 
138:         * @author Mauricio Pazos, Axios Engineering
139:         * @author Gabriel Roldan, Axios Engineering
140:         * @version $Id: GroupingFeatureIterator.java 27862 2007-11-12 19:51:19Z desruisseaux $
141:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/community-schemas/community-schema-ds/src/main/java/org/geotools/data/complex/GroupingFeatureIterator.java $
142:         * @since 2.4
143:         */
144:        class GroupingFeatureIterator extends AbstractMappingFeatureIterator {
145:            private static final Logger LOGGER = org.geotools.util.logging.Logging
146:                    .getLogger(GroupingFeatureIterator.class.getPackage()
147:                            .getName());
148:
149:            /**
150:             * 
151:             */
152:            private Feature curSrcFeature;
153:
154:            /**
155:             * maxFeatures restriction value as provided by query
156:             */
157:            private int maxFeatures;
158:
159:            /** counter to ensure maxFeatures is not exceeded */
160:            private int featureCounter;
161:
162:            /**
163:             * flag to avoid fetching multiple source feature in repeated calld to
164:             * hasNext() without calls to nex() in the middle
165:             */
166:            private boolean hasNextCalled;
167:
168:            private List/* <String> */groupByAttributeNames;
169:
170:            private List/* <AttributeMapping> */groupingMappings = new ArrayList();
171:
172:            private List/* <AttributeMapping> */nonGroupingMappings = new ArrayList();
173:
174:            private XPath xpathAttributeBuilder;
175:
176:            /**
177:             * Map of xpath target attributes/parent multivalued property. Used to
178:             * recognize child properties of a multivalued and complex attributes and
179:             * set their values for each member of the group.
180:             */
181:            private Map /* <StepList, XPath.Step> */multivaluedAttributePaths = new HashMap();
182:
183:            private static final FeatureFactory attf = new AttributeFactoryImpl();
184:
185:            /**
186:             * New instance of GroupingFeatureIterator
187:             * 
188:             * @param mapping
189:             * @param query
190:             * @param groupByAttributeNames
191:             *            list of attribute identifies for grouping the source feature
192:             * @throws IOException
193:             */
194:            public GroupingFeatureIterator(ComplexDataStore store,
195:                    FeatureTypeMapping mappings, Query query)
196:                    throws IOException {
197:                super (store, mappings, query);
198:                if (mappings.getGroupByAttNames().size() == 0) {
199:                    throw new IllegalArgumentException(
200:                            "no grouping attributes defined");
201:                }
202:                groupByAttributeNames = mappings.getGroupByAttNames();
203:
204:                xpathAttributeBuilder = new XPath();
205:                xpathAttributeBuilder.setFeatureFactory(super .attf);
206:                NamespaceSupport namespaces = mappings.getNamespaces();
207:                // FilterFactory namespaceAwareFilterFactory =
208:                // CommonFactoryFinder.getFilterFactory(hints);
209:                FilterFactory namespaceAwareFilterFactory = new FilterFactoryImplNamespaceAware(
210:                        namespaces);
211:                xpathAttributeBuilder
212:                        .setFilterFactory(namespaceAwareFilterFactory);
213:
214:                // Extracts simple and complex mappings
215:                List attrMappings = this .mapping.getAttributeMappings();
216:
217:                splitMappings(attrMappings);
218:            }
219:
220:            protected Query getUnrolledQuery(Query query) {
221:                maxFeatures = query.getMaxFeatures();
222:                Query unmappedQuery = store.unrollQuery(query, mapping);
223:                ((DefaultQuery) unmappedQuery)
224:                        .setMaxFeatures(Integer.MAX_VALUE);
225:
226:                unmappedQuery = ensureGroupingAttsPresent(unmappedQuery);
227:
228:                return unmappedQuery;
229:            }
230:
231:            /**
232:             * Takes a Query and returns another one ensuring that all the grouping
233:             * attributes are requested, in order to be able of producing the correct
234:             * number of output features, for example, from a joined set of tables.
235:             * 
236:             * @param query
237:             * @return
238:             */
239:            private Query ensureGroupingAttsPresent(Query query) {
240:                if (query.retrieveAllProperties()) {
241:                    return query;
242:                }
243:
244:                groupByAttributeNames = super .mapping.getGroupByAttNames();
245:                DefaultQuery neededQuery = new DefaultQuery(query);
246:                List requestedAtts = Arrays.asList(query.getPropertyNames());
247:                if (!requestedAtts.containsAll(this .groupByAttributeNames)) {
248:                    List remaining = new ArrayList(groupByAttributeNames);
249:                    remaining.removeAll(requestedAtts);
250:                    GroupingFeatureIterator.LOGGER
251:                            .fine("Adding missing grouping atts: " + remaining);
252:
253:                    List queryAtts = new ArrayList(remaining);
254:                    queryAtts.addAll(requestedAtts);
255:
256:                    neededQuery.setPropertyNames(queryAtts);
257:                }
258:                return neededQuery;
259:            }
260:
261:            /**
262:             * @return boolean true if exist next feature, false in other case.
263:             */
264:            public final boolean hasNext() {
265:                if (hasNextCalled) {
266:                    return curSrcFeature != null;
267:                }
268:
269:                boolean exists = false;
270:
271:                if (featureCounter < maxFeatures) {
272:
273:                    exists = this .sourceFeatures.hasNext();
274:
275:                    if (exists && this .curSrcFeature == null) {
276:                        this .curSrcFeature = (Feature) this .sourceFeatures
277:                                .next();
278:                    }
279:                }
280:
281:                if (!exists) {
282:                    GroupingFeatureIterator.LOGGER
283:                            .finest("no more features, produced "
284:                                    + featureCounter);
285:                }
286:
287:                hasNextCalled = true;
288:
289:                return exists;
290:            }
291:
292:            /**
293:             * @return Feature the next feature.
294:             */
295:            public final Object /* Feature */next() {
296:                if (!hasNext()) {
297:                    throw new IllegalStateException(
298:                            "there are no more features in this iterator");
299:                }
300:                //note hasNextCalled is going to be updated in createCurrentGroup()
301:                //as it might be called directly to improve performance in
302:                //calculating the resultset size
303:                Feature next = computeNext();
304:                ++featureCounter;
305:                return next;
306:            }
307:
308:            /**
309:             * Makes a Complex Feature using the data source and grouping the field of
310:             * mapped features. The source Features can be a Simple or Complex,
311:             * furthermore an attribute of target Feature can be in one or more Source
312:             * Features.
313:             * <p>
314:             * The target (mapped) attributes are created in the order defined in the
315:             * {@linkplain FeatureTypeMapping}'s attribute mappings.
316:             * </p>
317:             * 
318:             * @return a Feature of the target FeatureType composed up of applying the
319:             *         mappings and groupings defined in the
320:             *         {@linkplain FeatureTypeMapping}
321:             */
322:            private Feature computeNext() {
323:                // get the mapping set of a feature attribute
324:                final AttributeDescriptor targetNode = mapping
325:                        .getTargetFeature();
326:                final Name targetNodeName = targetNode.getName();
327:                final List attMappings = mapping.getAttributeMappings();
328:
329:                String fid = extractIdForFeature(curSrcFeature);
330:
331:                // create the target feature and iterate in the source for set its
332:                // values.
333:                final Feature targetFeature = GroupingFeatureIterator.attf
334:                        .createFeature(null, targetNode, fid);
335:
336:                final Feature featureForGroupingAtts = this .curSrcFeature;
337:
338:                final List/* <Feature> */currentGroup = createCurrentGroup();
339:
340:                /**
341:                 * We need to set attributes in the attribute mapping's declared order
342:                 */
343:                for (Iterator itr = attMappings.iterator(); itr.hasNext();) {
344:                    AttributeMapping mapping = (AttributeMapping) itr.next();
345:                    StepList targetXPath = mapping.getTargetXPath();
346:                    if (targetXPath.size() == 1) {
347:                        Step rootStep = (Step) targetXPath.get(0);
348:                        QName stepName = rootStep.getName();
349:                        if (Types.equals(targetNodeName, stepName)) {
350:                            // ignore the top level mapping for the Feature
351:                            // itself
352:                            // as it was already set
353:                            continue;
354:                        }
355:                    }
356:
357:                    if (mapping.isMultiValued()) {
358:                        setMultivaluedAttribute(targetFeature, mapping,
359:                                currentGroup);
360:                    } else {
361:                        setSingleValuedAttribute(targetFeature,
362:                                featureForGroupingAtts, mapping, currentGroup);
363:                    }
364:                }
365:
366:                return targetFeature;
367:            }
368:
369:            /**
370:             * Iterate over the source features while they belong to the same set of
371:             * grouping attributes.
372:             * 
373:             * <p>
374:             * Each time this method is called {@link #hasNextCalled} is set to false
375:             * </p>
376:             * 
377:             * @return the set of Features from the source resultset that belongs to the
378:             *         same group.
379:             */
380:            List/* <Feature> */createCurrentGroup() {
381:                List/* <List<Attribute>> */curGroupingAttrList = extractGroupingAttributes(this .curSrcFeature);
382:                List/* <Feature> */currentGroup = new LinkedList/* <Feature> */();
383:                currentGroup.add(this .curSrcFeature);
384:
385:                // loop control: break, if has not next or grouping attributes of
386:                // next feature are diferent
387:                hasNextCalled = false;
388:
389:                while (this .sourceFeatures.hasNext()) {
390:                    this .curSrcFeature = (Feature) this .sourceFeatures.next();
391:                    List/* <List<Attribute>> */newGroupingAttrList = extractGroupingAttributes(this .curSrcFeature);
392:                    if (!curGroupingAttrList.equals(newGroupingAttrList)) {
393:                        hasNextCalled = true;
394:                        break;
395:                    }
396:                    currentGroup.add(this .curSrcFeature);
397:                }
398:                return currentGroup;
399:                // [[Attribute[station_no:station_no:@:station_no.2]],
400:                // [Attribute[sitename:sitename:@:sitename2]],
401:                // [Attribute[anzlic_no:anzlic_no:@:anzlic_no2]],
402:                // [Attribute[project_no:project_no:@:project_no2]],
403:                // [Attribute[location:location:@:POINT (2 2)]]]
404:                // [[Attribute[station_no:station_no:@:station_no.2]],
405:                // [Attribute[sitename:sitename:@:sitename2]],
406:                // [Attribute[anzlic_no:anzlic_no:@:anzlic_no2]],
407:                // [Attribute[project_no:project_no:@:project_no2]],
408:                // [Attribute[location:location:@:POINT (2 2)]]]
409:            }
410:
411:            /**
412:             * Sets the values of grouping attributes.
413:             * 
414:             * @param sourceFeature
415:             * @param groupingMappings
416:             * @param targetFeature
417:             * 
418:             * @return Feature. Target feature sets with simple attributes
419:             */
420:            private void setSingleValuedAttribute(Feature target,
421:                    final Feature source, final AttributeMapping attMapping,
422:                    final List /* <Feature> */currentGroup) {
423:
424:                Expression expression = attMapping.getSourceExpression();
425:                final AttributeType targetNodeType = attMapping
426:                        .getTargetNodeInstance();
427:                final StepList xpath = attMapping.getTargetXPath();
428:
429:                if (expression == null) {
430:                    expression = Expression.NIL;
431:                }
432:
433:                List parentMultivaluedAttributePath = (List) multivaluedAttributePaths
434:                        .get(xpath);
435:                Object value;
436:                if (parentMultivaluedAttributePath != null) {
437:                    final int parentIndex = parentMultivaluedAttributePath
438:                            .size() - 1;
439:                    int index = 0;
440:
441:                    for (Iterator it = currentGroup.iterator(); it.hasNext();) {
442:                        index++;
443:                        Feature sourceFeature = (Feature) it.next();
444:                        try {
445:                            value = getValue(expression, sourceFeature);
446:                        } catch (Exception e) {
447:                            // HACK: what we actually need to resolve is dealing
448:                            // with queries that restricts the attributes returned
449:                            // by the source featurestore
450:                            continue;
451:                        }
452:
453:                        String id = extractIdForAttribute(attMapping
454:                                .getIdentifierExpression(), sourceFeature);
455:
456:                        StepList childSteps = setIndexAtStep(xpath, index,
457:                                parentIndex);
458:
459:                        Attribute instance = xpathAttributeBuilder.set(target,
460:                                childSteps, value, id, targetNodeType);
461:                        Map clientPropsMappings = attMapping
462:                                .getClientProperties();
463:                        setClientProperties(instance, sourceFeature,
464:                                clientPropsMappings);
465:                    }
466:                } else {
467:
468:                    try {
469:                        value = getValue(expression, source);
470:
471:                        //TODO	- check we dont actually need to bind to explicit null value at some point
472:                        //TODO: bouble ckeck: commented out the following two lines since it was causing
473:                        //attributes set through <targetAttributeNode> not to work (as the actual instance type
474:                        //were not being set by returning early)
475:                        //                if ( value == null )
476:                        //                	return;
477:
478:                        // if target has id construct the id value from source
479:                        String id = extractIdForAttribute(attMapping
480:                                .getIdentifierExpression(), this .curSrcFeature);
481:                        Attribute instance = xpathAttributeBuilder.set(target,
482:                                xpath, value, id, targetNodeType);
483:                        Map clientPropsMappings = attMapping
484:                                .getClientProperties();
485:                        setClientProperties(instance, curSrcFeature,
486:                                clientPropsMappings);
487:
488:                    } catch (Exception e) {
489:                        // HACK: what we actually need to resolve is dealing
490:                        // with queries that restricts the attributes returned
491:                        // by the source featurestore
492:                        if (e instanceof  RuntimeException) {
493:                            throw (RuntimeException) e;
494:                        } else {
495:                            throw (RuntimeException) new RuntimeException()
496:                                    .initCause(e);
497:                        }
498:                    }
499:                }
500:
501:            }
502:
503:            /**
504:             * Sets values of compex attributes, meaning those that are marked by the
505:             * {@link AttributeMapping#isMultiValued() multivalued flag} on the
506:             * attribute mapping.
507:             * 
508:             * @param sourceFeature
509:             * @param complexAttrMappings
510:             * @param targetFeature
511:             * 
512:             * @return Feature target feature sets with complex attributes
513:             */
514:            private void setMultivaluedAttribute(Feature target,
515:                    AttributeMapping attMapping, List/* <Feature> */group) {
516:
517:                Expression sourceExpression = attMapping.getSourceExpression();
518:                final AttributeType targetNodeType = attMapping
519:                        .getTargetNodeInstance();
520:                final StepList targetXpath = attMapping.getTargetXPath();
521:
522:                int index = 0;
523:                Object value;
524:                for (Iterator itr = group.iterator(); itr.hasNext();) {
525:                    Feature sourceFeature = (Feature) itr.next();
526:                    try {
527:                        value = getValue(sourceExpression, sourceFeature);
528:                    } catch (Exception e) {
529:                        // HACK: what we actually need to resolve is dealing
530:                        // with queries that restricts the attributes returned
531:                        // by the source featurestore
532:                        continue;
533:                    }
534:                    index++;
535:                    // if target has id construct the id value from source
536:                    String id = extractIdForAttribute(attMapping
537:                            .getIdentifierExpression(), sourceFeature);
538:
539:                    // if complex or leaf of complex attribute then insert index in
540:                    // xpath.
541:                    StepList targetXpathAttr = null;
542:
543:                    targetXpathAttr = setIndexOfLastStep(target, targetXpath,
544:                            index);
545:                    // boolean isComplexType =
546:                    // xpathAttributeBuilder.isComplexType(targetXpath, target
547:                    // .getDescriptor());
548:                    // if (isComplexType) {
549:                    // targetXpathAttr = setIndexOfLastStep(target, targetXpath, index);
550:                    //
551:                    // } else if (isLeafOfNestedComplexType(targetXpath,
552:                    // target.getDescriptor())) {
553:                    // targetXpathAttr = setLeafInexInXPathExpression(target,
554:                    // targetXpath, index);
555:                    // } else {
556:                    // throw new IllegalArgumentException(
557:                    // "Attribute must be complex type or belong to the grouping
558:                    // attributes");
559:                    // }
560:
561:                    Attribute instance = xpathAttributeBuilder.set(target,
562:                            targetXpathAttr, value, id, targetNodeType);
563:                    Map clientPropsMappings = attMapping.getClientProperties();
564:                    setClientProperties(instance, sourceFeature,
565:                            clientPropsMappings);
566:                }
567:            }
568:
569:            private void setClientProperties(Attribute target, Feature source,
570:                    Map clientProperties) {
571:                if (clientProperties.size() == 0) {
572:                    return;
573:                }
574:
575:                final Map nodeAttributes = new HashMap();
576:                final AttributeDescriptor node = target.getDescriptor();
577:
578:                for (Iterator it = clientProperties.entrySet().iterator(); it
579:                        .hasNext();) {
580:                    Map.Entry entry = (Map.Entry) it.next();
581:                    org.opengis.feature.type.Name propName = (org.opengis.feature.type.Name) entry
582:                            .getKey();
583:                    Expression propExpr = (Expression) entry.getValue();
584:
585:                    Object propValue = getValue(propExpr, source);
586:
587:                    nodeAttributes.put(propName, propValue);
588:                }
589:
590:                node.putUserData(Attributes.class, nodeAttributes);
591:            }
592:
593:            /**
594:             * Splits the attribute mappings in two sets, one for grouping attributes
595:             * and another for non grouping (aka, multiple values) ones.
596:             * 
597:             * @param groupByAttributeNames
598:             *            names of grouping attributes (input)
599:             * @param allAttrMappings
600:             *            mappings of attributes feature (input)
601:             * @param groupMappings
602:             *            output mappings for single attributes
603:             * @param nonGroupingMappings
604:             *            output mappings for complex attributes
605:             */
606:            private final void splitMappings(final List allAttrMappings) {
607:
608:                FilterAttributeExtractor attExtractor = new FilterAttributeExtractor();
609:
610:                final List multivaluedAttributes = new ArrayList();
611:
612:                for (Iterator itr = allAttrMappings.iterator(); itr.hasNext();) {
613:                    AttributeMapping attMapping = (AttributeMapping) itr.next();
614:                    Expression source = attMapping.getSourceExpression();
615:
616:                    if (attMapping.isMultiValued()) {
617:                        StepList targetXPath = attMapping.getTargetXPath();
618:                        multivaluedAttributes.add(targetXPath);
619:                    }
620:
621:                    source.accept(attExtractor, null);
622:                    Set sourceAttNames = new HashSet(attExtractor
623:                            .getAttributeNameSet());
624:                    // if at least one of the attributes used by the expression is not
625:                    // a grouping attribute, the expression addresses a multivalued
626:                    // target property
627:                    if (groupByAttributeNames.containsAll(sourceAttNames)) {
628:                        groupingMappings.add(attMapping);
629:                    } else {
630:                        sourceAttNames.removeAll(groupByAttributeNames);
631:                        GroupingFeatureIterator.LOGGER
632:                                .fine("attributes of multivalued property: "
633:                                        + sourceAttNames);
634:                        nonGroupingMappings.add(attMapping);
635:                    }
636:                }
637:
638:                for (Iterator itr = allAttrMappings.iterator(); itr.hasNext();) {
639:                    AttributeMapping attMapping = (AttributeMapping) itr.next();
640:                    if (attMapping.isMultiValued()) {
641:                        continue;
642:                    }
643:
644:                    StepList targetSteps = attMapping.getTargetXPath();
645:
646:                    for (Iterator mvalues = multivaluedAttributes.iterator(); mvalues
647:                            .hasNext();) {
648:                        StepList parentSteps = (StepList) mvalues.next();
649:
650:                        if (targetSteps.size() <= parentSteps.size()) {
651:                            // shortcut. Couldn't be a parent path since it has
652:                            // less steps than child
653:                            continue;
654:                        }
655:
656:                        int equalCount = 0;
657:                        for (int i = 0; i < parentSteps.size(); i++) {
658:                            XPath.Step targetStep = (XPath.Step) targetSteps
659:                                    .get(i);
660:                            XPath.Step parentStep = (XPath.Step) parentSteps
661:                                    .get(i);
662:                            if (!targetStep.equals(parentStep)) {
663:                                break;
664:                            }
665:                            equalCount++;
666:                        }
667:                        int parentStepCount = parentSteps.size();
668:                        if (equalCount == parentStepCount) {
669:                            GroupingFeatureIterator.LOGGER.fine("scheduling "
670:                                    + targetSteps
671:                                    + " as property of multivalued attribute "
672:                                    + parentSteps);
673:                            multivaluedAttributePaths.put(targetSteps,
674:                                    parentSteps);
675:                        }
676:                    }
677:                }
678:            }
679:
680:            private final StepList setIndexOfLastStep(final Attribute root,
681:                    final StepList xpathAttrDefinition, int index) {
682:
683:                int insertPosition = xpathAttrDefinition.size();
684:
685:                StepList indexXpath = insertIndexInXpath(root,
686:                        xpathAttrDefinition, index, insertPosition);
687:
688:                return indexXpath;
689:            }
690:
691:            /**
692:             * 
693:             * @param xpath
694:             *            XPath expression for which to set the <code>stepIndex</code>'th
695:             *            attribute to index <code>newInde</code>
696:             * @param newIndex
697:             *            index to set for step number <code>stepIndex</code>.
698:             *            <code>newIndex</code> minimun value is <code>1</code>, as
699:             *            in XPath spec.
700:             * @param stepIndex
701:             *            index of the step in the list of steps for <code>xpath</code>
702:             *            for which to set the step index to <code>newIndex</code>.
703:             *            The minimun value is <code>0</code>, as in Java collections
704:             *            and arrays.
705:             * @return
706:             */
707:            private final StepList setIndexAtStep(StepList xpath, int newIndex,
708:                    int stepIndex) {
709:
710:                StepList steps = (StepList) xpath.clone();
711:
712:                XPath.Step step = (XPath.Step) steps.get(stepIndex);
713:                step = new XPath.Step(step.getName(), newIndex);
714:                steps.set(stepIndex, step);
715:
716:                return steps;
717:            }
718:
719:            /**
720:             * Insert index into step of xpath; Position indicate the step.
721:             * 
722:             * @param featureType
723:             * @param attrXpath
724:             * @param index
725:             * @param insertPositon
726:             * 
727:             * @return String
728:             */
729:            private final StepList insertIndexInXpath(final Attribute root,
730:                    final StepList attrXpath, final int index,
731:                    final int insertPositon) {
732:
733:                // Constructs an Xpath adding index in the step corresponding to complex
734:                // attribute
735:                StepList stepList = (StepList) attrXpath.clone();
736:
737:                Step step = (Step) stepList.get(insertPositon - 1);
738:                Step newStep = new XPath.Step(step.getName(), index);
739:
740:                stepList.set(insertPositon - 1, newStep);
741:
742:                return stepList;
743:            }
744:
745:            /**
746:             * Extract the attributes from grouping attributes.
747:             * 
748:             * @param Feature
749:             *            a source feature
750:             * @return List<List<Attribute>> the the contened list has the attributes
751:             *         required
752:             */
753:            private final List/* <List<Attribute>> */extractGroupingAttributes(
754:                    ComplexAttribute srcFeature) {
755:
756:                List/* <List<Attribute>> */attrGroup = new LinkedList/* <List<Attribute>> */();
757:
758:                for (Iterator itr = this .groupByAttributeNames.iterator(); itr
759:                        .hasNext();) {
760:                    String attrName = (String) itr.next();
761:                    Name name = Types.typeName(attrName);
762:                    List/* <Attribute> */listAttrForName = srcFeature
763:                            .get(name);
764:                    attrGroup.add(listAttrForName);
765:                }
766:
767:                return attrGroup;
768:            }
769:
770:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.