/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.mapping.factory; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.emf.ecore.EObject; import org.teiid.designer.mapping.PluginConstants; /** * @since 8.0 */ public class IterationBasedBuilderStrategy implements MappingClassBuilderStrategy { protected ITreeToRelationalMapper mapper; protected IMappableTree tree; /** * @see org.teiid.designer.mapping.factory.MappingClassBuilderStrategy#buildMappingClassMap(org.eclipse.emf.ecore.EObject) * @since 4.3 */ @Override public Map buildMappingClassMap( EObject theTopNode, IMappableTree tree, ITreeToRelationalMapper mapper ) { this.mapper = mapper; this.tree = tree; Map result = recursiveBuild(theTopNode, null, new HashMap()); // null out the instance variables so this object can be held this.mapper = null; this.tree = null; return result; } protected Map recursiveBuild( EObject node, EObject currentMappingClassStorageNode, Map classAttributeMap ) { // see if the node we are on right now is mappable if (mapper.isMappable(node)) { // if so, then we need to put this node in the attribute list for the currentMappingClassStorageNode addAttributeToMap(node, currentMappingClassStorageNode, classAttributeMap); } // now look at the children of this node and see if any have maxOccurs > 1 for (Iterator iter = tree.getChildren(node).iterator(); iter.hasNext();) { EObject child = (EObject)iter.next(); if (mapper.isMappable(child) && !mapper.allowsMappingClass(child)) { // found a mappable attribute, so add it to the attribute list for the currentMappingClassStorageNode currentMappingClassStorageNode = addAttributeToMap(child, currentMappingClassStorageNode, classAttributeMap); } else { // put a new mapping class here if this node's maxOccurs > 1 or if it's recursive if (shouldContainMappingClass(child)) { // then this node needs to store a MappingClass classAttributeMap.put(child, new ArrayList()); recursiveBuild(child, child, classAttributeMap); } else { // recurse down through the children of this node recursiveBuild(child, currentMappingClassStorageNode, classAttributeMap); } } } return classAttributeMap; } protected boolean shouldContainMappingClass( EObject node ) { boolean result = false; try { if (mapper.allowsMappingClass(node)) { if (mapper.canIterate(node)) { result = true; } else if (mapper.isRecursive(node)) { result = true; } } } catch (Exception e) { PluginConstants.Util.log(e); } return result; } /** * used by buildMappingClassMap */ protected EObject addAttributeToMap( EObject node, EObject currentMappingClassStorageNode, Map classAttributeMap ) { Collection attributeNodes = null; if (currentMappingClassStorageNode == null) { // there is not yet a storage node for this attribute, so use this one EObject testNode = node; while (currentMappingClassStorageNode == null) { if (shouldContainMappingClass(testNode)) { currentMappingClassStorageNode = testNode; } else if (mapper.isTreeRoot(testNode)) { currentMappingClassStorageNode = testNode; } else { // next look at the parent of this node EObject parent = tree.getParent(testNode); if (parent != null && parent == tree.getTreeRoot()) { // we're at the top of the tree, so use this node currentMappingClassStorageNode = testNode; } else { testNode = parent; } } } } if (!classAttributeMap.keySet().contains(currentMappingClassStorageNode)) { attributeNodes = new ArrayList(); classAttributeMap.put(currentMappingClassStorageNode, attributeNodes); } else { // get the attribute list for this storage node attributeNodes = (Collection)classAttributeMap.get(currentMappingClassStorageNode); } // add this mappable document node to the attribute list for the currentMappingClassStorageNode attributeNodes.add(node); return currentMappingClassStorageNode; } }