/** * Copyright (c) 2004-2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM - Initial API and implementation */ package org.eclipse.emf.ecore.xmi.impl; import java.util.HashMap; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.ExtendedMetaData; import org.eclipse.emf.ecore.xmi.DOMHandler; import org.eclipse.emf.ecore.xmi.DOMHelper; import org.w3c.dom.Attr; import org.w3c.dom.Node; /** * Implementation of the default {@link DOMHandler} and {@link DOMHelper} * @since 2.1.0 */ public class DefaultDOMHandlerImpl implements DOMHandler, DOMHelper { /** store node to actual value mapping */ protected final HashMap<Node, Object> nodeToObject = new HashMap<Node, Object>(); /** store node to containment feature mapping */ protected final HashMap<Node, EStructuralFeature> nodeToFeature = new HashMap<Node, EStructuralFeature>(); /** store node to container. used only to record some text/cdata nodes */ protected final HashMap<Node, EObject> nodeToContainer = new HashMap<Node, EObject>(); protected ExtendedMetaData extendedMetaData; void setExtendedMetaData(ExtendedMetaData extendedMetaData) { this.extendedMetaData = extendedMetaData; } public EObject getContainer(Node node) { short type = node.getNodeType(); switch (type) { case Node.ELEMENT_NODE: { Object o = nodeToObject.get(node); if (o != null && o instanceof EObject) { return ((EObject)o).eContainer(); } return (EObject)nodeToObject.get(node.getParentNode()); } case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: { Object o = nodeToContainer.get(node); if (o != null) { return (EObject)o; } return (EObject)nodeToObject.get(node.getParentNode().getParentNode()); } case Node.ATTRIBUTE_NODE: return (EObject)nodeToObject.get(((Attr)node).getOwnerElement()); default: return null; } } /* (non-Javadoc) * @see org.eclipse.emf.ecore.xmi.DOMHelper#getValue(org.w3c.dom.Node) */ public Object getValue(Node node) { Object value = nodeToObject.get(node); if (value == null) { if (node.getNodeType() == Node.TEXT_NODE) { value = nodeToObject.get(node.getParentNode()); } } return value; } public EStructuralFeature getEStructuralFeature(Node node) { short type = node.getNodeType(); switch (type) { case Node.ELEMENT_NODE: return nodeToFeature.get(node); case Node.ATTRIBUTE_NODE: { EObject obj = (EObject)nodeToObject.get(((Attr)node).getOwnerElement()); if (extendedMetaData == null) { return obj.eClass().getEStructuralFeature(node.getLocalName()); } else if (obj != null) { return extendedMetaData.getAttribute(obj.eClass(), node.getNamespaceURI(), node.getLocalName()); } } case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: { EStructuralFeature feature = nodeToFeature.get(node); if (feature == null) { feature = nodeToFeature.get(node.getParentNode()); } return feature; } default: return null; } } public void recordValues(Node node, EObject container, EStructuralFeature feature, Object value) { debug(node, container, feature, value); short type = node.getNodeType(); switch (type) { case Node.ELEMENT_NODE: { nodeToFeature.put(node, feature); // fall through } case Node.ATTRIBUTE_NODE: { if (value != null) { nodeToObject.put(node, value); } break; } case Node.TEXT_NODE: { if (nodeToObject.get(node.getParentNode()) == value) { break; } //fall through... } case Node.CDATA_SECTION_NODE: { nodeToFeature.put(node, feature); nodeToContainer.put(node, container); nodeToObject.put(node, value); } } } public DOMHelper getDOMHelper() { return this; } final static boolean DEBUG = false; private static final void debug(Node node, EObject container, EStructuralFeature feature, Object value) { if (DEBUG) { StringBuffer buf = new StringBuffer(); buf.append("recordValues( "); buf.append(" {"); switch (node.getNodeType()) { case Node.ELEMENT_NODE: buf.append("ELEMENT_NODE "); break; case Node.ATTRIBUTE_NODE: buf.append("ATTRIBUTE_NODE "); break; case Node.TEXT_NODE: buf.append("TEXT_NODE "); break; case Node.CDATA_SECTION_NODE: buf.append("CDATA_SECTION_NODE "); break; default: buf.append("UNKNOWN "); break; } buf.append(node.getNodeName()); buf.append("{ " + node.getNodeValue() + " }, "); if (container != null) { buf.append(container.eClass().getName() + ", "); } else { buf.append("null, "); } if (feature != null) { buf.append(feature.getName() + ", "); } else { buf.append("null, "); } if (value != null) { buf.append(value.getClass().getName() + ": " + value.toString() + ");"); } else { buf.append("null);"); } System.out.println(buf.toString()); } } }