/*******************************************************************************
 * Copyright (c) 2003, 2007 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 Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.common.internal.emf.resource;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.wst.common.internal.emf.plugin.EcoreUtilitiesPlugin;
import org.eclipse.wst.common.internal.emf.utilities.Assert;
import org.eclipse.wst.common.internal.emf.utilities.DOMUtilities;
import org.eclipse.wst.common.internal.emf.utilities.EtoolsCopySession;
import org.eclipse.wst.common.internal.emf.utilities.ExtendedEcoreUtil;
import org.eclipse.wst.common.internal.emf.utilities.FeatureValueConversionException;
import org.eclipse.wst.common.internal.emf.utilities.Revisit;
import org.eclipse.wst.common.internal.emf.utilities.StringUtil;
import org.eclipse.wst.common.internal.emf.utilities.TranslatorService;
import org.eclipse.wst.common.internal.emf.utilities.WFTUtilsResourceHandler;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;


public class EMF2DOMAdapterImpl extends AdapterImpl implements EMF2DOMAdapter {

	final protected static boolean fDebug = false;

	protected boolean fNotificationEnabled = true;

	protected Node fNode;

	protected Translator fTranslator;

	protected EMF2DOMRenderer fRenderer;

	protected Translator[] childTranslators;

	protected boolean isRoot = false;
	
	private static final String PLATFORM = "org.eclipse.core.runtime.Platform"; //$NON-NLS-1$
	private static final String ISRUNNING = "isRunning"; //$NON-NLS-1$

	private class DependencyAdapter extends org.eclipse.emf.common.notify.impl.AdapterImpl {

		static final String KEY = "EMF2DOMDependencyAdapter"; //$NON-NLS-1$

		@Override
		public void notifyChanged(Notification msg) {
			EMF2DOMAdapterImpl.this.notifyChanged(msg);
		}

		/**
		 * @see org.eclipse.emf.common.notify.impl.AdapterImpl#isAdapterForType(Object)
		 */
		@Override
		public boolean isAdapterForType(Object type) {
			return KEY.equals(type);
		}
	}

	/**
	 * Constructor for root adapters.
	 */
	public EMF2DOMAdapterImpl(TranslatorResource resource, Document document, EMF2DOMRenderer renderer, Translator translator) {
		this((Notifier) resource, (Node) document, renderer, translator);
		isRoot = true;
	}

	/**
	 * Construct an Adapter given an EObject and a node
	 */
	public EMF2DOMAdapterImpl(Notifier object, Node node, EMF2DOMRenderer renderer, Translator translator) {
		super();
		setTarget(object);
		fNode = node;
		fRenderer = renderer;
		fTranslator = translator;
		initChildTranslators();
		addEMFAdapter();
		addDOMAdapter();
		addDependencyAdapterIfNecessary();
	}

	/**
	 * Construct an adapter from a DOM Node. The EObject will be created
	 */
	public EMF2DOMAdapterImpl(Node node, EMF2DOMRenderer renderer, Translator translator) {
		fNode = node;
		fRenderer = renderer;
		fTranslator = translator;
		setTargetFromNode();
		initChildTranslators();
		addEMFAdapter();
		addDOMAdapter();
		addDependencyAdapterIfNecessary();

	}

	protected void addDependencyAdapterIfNecessary() {
		if (!fTranslator.isDependencyParent())
			return;
		EObject child = fTranslator.basicGetDependencyObject(getEObject());
		if (child != null)
			addDependencyAdapter(child);
	}

	protected void initChildTranslators() {
		List children = new ArrayList();
		boolean isRunning = false; //is the OSGI platform running ?
		try {
			// If the Platform class can be found, then continue to check if the OSGI platform is running
			Class clazz = Class.forName(PLATFORM);
			Method m = clazz.getMethod(ISRUNNING);
			isRunning = ((Boolean)m.invoke(clazz)).booleanValue();
		} catch (ClassNotFoundException e) {
		     // Ignore because this must be in a non_OSGI environment
		} catch (SecurityException e) {
			 // Ignore because this must be in a non_OSGI environment
		} catch (NoSuchMethodException e) {
			 // Ignore because this must be in a non_OSGI environment
		} catch (IllegalArgumentException e) {
			 // Ignore because this must be in a non_OSGI environment
		} catch (IllegalAccessException e) {
			 // Ignore because this must be in a non_OSGI environment
		} catch (InvocationTargetException e) {
			 // Ignore because this must be in a non_OSGI environment
		}	
		//Check for extended child translators because we are in OSGI mode
		if (isRunning) {
			Translator[] extendedChildren = TranslatorService.getInstance().getTranslators();
	        for (int i = 0; i < extendedChildren.length; i++) {
	        	if (extendedChildren[i] != null)
	            	children.add(extendedChildren[i]);
	        }
		}
		
		
		children.addAll(Arrays.asList(fTranslator.getChildren(getTarget(), fRenderer.getVersionID())));

		VariableTranslatorFactory factory = fTranslator.getVariableTranslatorFactory();
		if (factory != null) {
			String domName = null;
			NamedNodeMap map = fNode.getAttributes();

			if (map != null) {
				int length = map.getLength();
				for (int i = 0; i < length; i++) {
					Node attrNode = map.item(i);
					domName = attrNode.getNodeName();
					//Handle variable translators
					Translator t = fTranslator.findChild(domName, getTarget(), fRenderer.getVersionID());
					if (t != null && !children.contains(t))
						children.add(t);
				}
			}
			List childrenFromEMF = factory.create(getTarget());
			if (childrenFromEMF != null)
				children.addAll(childrenFromEMF);
		}

		childTranslators = (Translator[]) children.toArray(new Translator[children.size()]);
	}

	/**
	 * Set to false and notification of changes from both the DOM node and the MOF object will be
	 * ignored.
	 */
	public boolean isNotificationEnabled() {
		return fNotificationEnabled;
	}

	/**
	 * Set to false and notification of changes from both the DOM node and the MOF object will be
	 * ignored.
	 */
	public void setNotificationEnabled(boolean isEnabled) {
		fNotificationEnabled = isEnabled;
	}

	@Override
	public boolean isAdapterForType(Object type) {
		return EMF2DOMAdapter.ADAPTER_CLASS == type;
	}

	protected void addEMFAdapter() {
		target.eAdapters().add(this);
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append(shortClassName(this));
		sb.append('(');
		sb.append(getNode().getNodeName());
		sb.append(',');
		sb.append(shortClassName(getTarget()));
		sb.append(')');
		return sb.toString();
	}

	protected String shortClassName(Object o) {
		if (o != null) {
			String cn = o.getClass().getName();
			int i = cn.lastIndexOf('.');
			return cn.substring(i + 1, cn.length());
		}
		return null;
	}

	/*
	 * Prints out a MOF notification for debugging
	 */
	protected void debugMOFNotify(Notification msg) {
		if (fDebug) {
			String notifType = ""; //$NON-NLS-1$
			switch (msg.getEventType()) {
				case Notification.ADD :
					notifType = "ADD"; //$NON-NLS-1$
					break;
				case Notification.REMOVE :
					notifType = "REMOVE"; //$NON-NLS-1$
					break;
				case Notification.ADD_MANY :
					notifType = "ADD_MANY"; //$NON-NLS-1$
					break;
				case Notification.REMOVE_MANY :
					notifType = "REMOVE_MANY"; //$NON-NLS-1$
					break;
				case Notification.SET : {
					if (msg.getPosition() == Notification.NO_INDEX)
						notifType = "REPLACE"; //$NON-NLS-1$
					else
						notifType = "SET"; //$NON-NLS-1$
					break;
				}
				case Notification.UNSET :
					notifType = "UNSET"; //$NON-NLS-1$
					break;
			}

			EcoreUtilitiesPlugin.logError("MOF Change: " + notifType); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tnotifier      : " + msg.getNotifier()); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tchangedFeature: " + msg.getFeature()); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\toldValue      : " + msg.getOldValue()); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tnewValue      : " + msg.getNewValue()); //$NON-NLS-1$
		}
	}

	/*
	 * Override this method to create the feature maps for the adapter.
	 */
	protected Translator[] getChildTranslators() {
		return childTranslators;
	}

	protected Translator findTranslator(Notification not) {
		if (not.getFeature() == null)
			return null;
		Translator[] maps = getChildTranslators();
		for (int i = 0; i < maps.length; i++) {
			if (maps[i].isMapFor(not.getFeature(), not.getOldValue(), not.getNewValue()))
				return maps[i];
		}
		return null;
	}
	
	/**
	 * Checks to ensure that only one MOF node has been removed and will remove the dom equivalent.
	 * If multiple differences are found, will return the index of the first difference.
	 * 
	 * @param parent
	 * @param mofChildren
	 * @param domChildren
	 * @return
	 */
	private int updateDOMSingleRemove(Node parent, List mofChildren, List domChildren){
		int domIndex = 0;
		int firstDifference = -1;
		for (Object mofChild : mofChildren){
			EMF2DOMAdapter adapter = getExistingAdapter((EObject)mofChild);
			if(adapter.getNode() != domChildren.get(domIndex)){
				if(firstDifference != -1){
					//second difference; return
					return firstDifference;
				}
				//we found something that is different
				firstDifference = domIndex;
				//skip over one index and check against next
				domIndex ++;
				if(adapter.getNode() != domChildren.get(domIndex)){
					//if these are different then there are multiple changes
					return firstDifference;
				}
			}
			domIndex++;
		}
		if(firstDifference != -1){
			removeDOMChild(parent, (Element) domChildren.get(firstDifference));
			//if we are here, and firstDifference is not -1, that means we have iterated
			//through the entire mof list, and all elements have been processed. Return
			//domchildren.size, so that no more processing is done in calling method.
			return domChildren.size();
		}
		//if we are here, then firstDifference was -1. Our algo has failed. Let original algo run.
		return 0;
	}

	

	/**
	 * Update all the children of the target MOF object in the relationship described by
	 * 
	 * @map.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator Describes the mapping from the MOF
	 *            attribute name to the DOM node name
	 */
	protected void primUpdateDOMMultiFeature(Translator map, Node node, List mofChildren, List domChildren, Notifier owner) {

		int i = 0;
		Node parent = findDOMPath(node, map, false);
		if(domChildren.size() - mofChildren.size() == 1){
			//an emf object has been deleted. Remove it from the dom as well
			i = updateDOMSingleRemove(parent, mofChildren, domChildren);
		}
		//Used for inserting primitives
		List inorderDOMChildren = null;
		if(i < mofChildren.size()){
			if (!map.isObjectMap() || map.isManagedByParent()) {
				inorderDOMChildren = new ArrayList();
				inorderDOMChildren.addAll(domChildren);
			}
		}
		// Go though the MOF children checking to see if the corresponding
		// MOF Adapter children exists. If not, create the adapter.
		// Also handles reordering children that have moved.
		for (; i < mofChildren.size(); i++) {
			Object child = mofChildren.get(i);
			EObject mofChild = null;

			EMF2DOMAdapter adapter = null;

			// Check to see if the child is a MOF Object.
			if (!map.isManagedByParent() && child instanceof EObject) {
				mofChild = (EObject) mofChildren.get(i);
				adapter = getExistingAdapter(mofChild);
			}

			if (adapter != null && i < domChildren.size() && domChildren.get(i) == adapter.getNode())
				continue;
			if (adapter != null) {
				if (domChildren.isEmpty())
					continue;
				// A node has been reordered in the list
				Node reorderNode = adapter.getNode();
				Node insertBeforeNode = reorderNode;
				if (i < domChildren.size() && domChildren.get(i) != reorderNode) {
					insertBeforeNode = (Node) domChildren.get(i);
				}
				domChildren.remove(reorderNode);
				domChildren.add(i, reorderNode);
				if (reorderNode != insertBeforeNode) {
					reorderDOMChild(parent, reorderNode, insertBeforeNode, map);
				}
			} else {
				// A new node has been added, create it
				parent = createDOMPath(node, map);
				if (mofChild != null) {
					adapter = createAdapter(mofChild, map);
					Node newNode = adapter.getNode();
					Node insertBeforeNode = findInsertBeforeNode(parent, map, mofChildren, i, domChildren);
					DOMUtilities.insertBeforeNodeAndWhitespace(parent, newNode, insertBeforeNode);
					domChildren.add(i, newNode);
					boolean notificationFlag = adapter.isNotificationEnabled();
					adapter.setNotificationEnabled(false);
					try {
						indent(newNode, map);
					} finally {
						adapter.setNotificationEnabled(notificationFlag);
					}
					adapter.updateDOM();
				} else {
					// The mof feature is a collection of primitives.
					// create a new dom node and listen to it.
					Element newNode = createNewNode(null, map);
					Node insertBeforeNode = findInsertBeforeNode(parent, map, mofChildren, i, inorderDOMChildren);
					DOMUtilities.insertBeforeNodeAndWhitespace(parent, newNode, insertBeforeNode);
					indent(newNode, map);
					addDOMAdapter(newNode); // Hook up listeners
					domChildren.add(i, newNode);
					if(inorderDOMChildren != null){
						inorderDOMChildren.add(newNode);
					}
					Text newText = parent.getOwnerDocument().createTextNode(map.convertValueToString(child, (EObject) owner));
					DOMUtilities.insertBeforeNode(newNode, newText, null);
				}
			}
		}

		// Remove any remaining adapters.
		for (; i < domChildren.size(); i++) {
			removeDOMChild(parent, (Element) domChildren.get(i));
		}

		// If there are no MOF children, remove any unnecessary DOM node paths
		if (mofChildren.size() == 0 && map.hasDOMPath()) {
			if (map.shouldRenderEmptyDOMPath((EObject) owner))
				createDOMPath(node, map);
			else
				removeDOMPath(node, map);
		}

	}

	/**
	 * Update all the children of the target MOF object in the relationship described by
	 * 
	 * @map.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator Describes the mapping from the MOF
	 *            attribute name to the DOM node name
	 */
	protected void primUpdateMOFMultiFeature(Translator map, Node node, List mofChildren, List domChilren) {

		Hashtable nodeToAdapter = new Hashtable();

		for (int i = 0; i < mofChildren.size(); i++) {
			EMF2DOMAdapter adapter = getExistingAdapter((EObject) mofChildren.get(i));
			if (adapter != null)
				nodeToAdapter.put(adapter.getNode(), adapter);
		}

		// Go though the DOM children checking to see if the corresponding
		// MOF Adapter children exists. If not, create the adapter.
		// Also handles reordering children that have moved.
		int i = 0;
		int mofIndex = 0;
		List adaptersToUpdate = new ArrayList();
		for (; i < domChilren.size(); i++) {
			Element childNode = (Element) domChilren.get(i);
			EMF2DOMAdapter adapter = i < mofChildren.size() ? getExistingAdapter((EObject) mofChildren.get(i)) : null;
			if (adapter != null && !adapter.isMOFProxy() && adapter.getNode() == childNode) {
				// Because the adapter is processing STRUCTURE_CHANGED from the
				// DOM, we
				// must update all the way down the tree since anything under
				// the notifying
				// DOM node could have changed.
				adapter.updateMOF();
				mofIndex++;
				continue;
			}

			adapter = (EMF2DOMAdapter) nodeToAdapter.get(childNode);
			if (adapter != null) {
				reorderIfNecessary((EList) mofChildren, adapter.getEObject(), mofIndex);
				mofIndex++;
			} else {
				adapter = createAdapter(childNode, map);
				if (adapter != null) {
					try {
						//We don't want to push anything back to the child dom
						adapter.setNotificationEnabled(false);
						map.setMOFValue(getTarget(), adapter.getTarget(), mofIndex);
					} finally {
						adapter.setNotificationEnabled(true);
					}

					adaptersToUpdate.add(adapter);
					mofIndex++;
				}
			}
		}

		// Remove any remaining adapters.
		//make a copy so we remove all items - bug 192468 
				Object[] childrenArray = mofChildren.toArray();
				for (; i < childrenArray.length; i++) {
					removeMOFValue((EObject) childrenArray[i], map);
		 		}

		// The adapters cannot be updated as they created. We must wait until
		// all of the adapters are created and removed before updating,
		// otherwise
		// we can get in a state where there are adapters fighting with
		// eachother
		// (one for the old node and one for the new node).
		for (int j = 0; j < adaptersToUpdate.size(); j++) {
			((EMF2DOMAdapter) adaptersToUpdate.get(j)).updateMOF();
		}
	}

	/**
	 * Removes a feature's value.
	 * 
	 * @param childAdapter
	 *            com.ibm.etools.mof2dom.EMF2DOMAdapter The child to remove
	 * @param mofAttributeName
	 *            String The name of the mofAttribute to remove the child from.
	 */
	protected void removeMOFValue(EObject value, Translator translator) {

		if (value == null)
			return;

		EMF2DOMAdapter adapter = (EMF2DOMAdapter) EcoreUtil.getExistingAdapter(value, EMF2DOMAdapter.ADAPTER_CLASS);
		if (adapter != null) {
			// Remove the adapter from BOTH the MOF Object and the DOM Nodes
			removeAdapters(adapter.getNode());
			value.eAdapters().remove(adapter);
		}

		EStructuralFeature feature = translator.getFeature();
		boolean doUnload = feature == null || (translator.isObjectMap() && ((EReference) feature).isContainment());

		// translator.removeMOFValue() was here originally

		// Unload the objects.
		if (doUnload)
			ExtendedEcoreUtil.unload(value);

		// Remove the MOF value
		translator.removeMOFValue(getTarget(), value);
	}

	protected void reorderIfNecessary(EList emfChildren, EObject eObj, int emfIndex) {
		int currIndex = emfChildren.indexOf(eObj);
		if (currIndex > -1 && currIndex != emfIndex)
			emfChildren.move(emfIndex, eObj);
	}

	/**
	 * default is to do nothing; subclasses can override
	 */
	protected void indent(Node newNode, Translator map) {

	}

	protected Node findInsertBeforeNode(Node parentNode, Translator map, List mofList, int mofInx, List domList) {
		Node insertBeforeNode = null;

		// If there are no current dom children for this map, find the initial
		// insert pos.
		if (domList.size() == 0)
			return findInitialInsertBeforeNode(parentNode, map);

		// If some dom nodes then find the correct one to insert before.
		int i = mofInx + 1;
		while (i < mofList.size() && insertBeforeNode == null) {
			// Start at the mofInx passed in and look forward for the first
			// adapted
			// MOF object. Use that node as the insert before node.
			Object o = mofList.get(i);
			if (!map.isObjectMap() || map.isManagedByParent())
				break;
			EObject tMOFObject = (EObject) o;
			EMF2DOMAdapter tAdapter = (EMF2DOMAdapter) EcoreUtil.getExistingAdapter(tMOFObject, EMF2DOMAdapter.ADAPTER_CLASS);
			if (tAdapter != null) {
				insertBeforeNode = tAdapter.getNode();
			}
			i++;
		}

		// Handle inserting at the end of the list
		if (insertBeforeNode == null)
			insertBeforeNode = DOMUtilities.getNextNodeSibling((Node) domList.get(domList.size() - 1));
		if (insertBeforeNode == null)
			insertBeforeNode = ((Node) domList.get(domList.size() - 1)).getNextSibling();

		return insertBeforeNode;
	}

	protected Node findInitialInsertBeforeNode(Node parentNode, Translator mapNode) {
		Translator[] maps = getChildTranslators();

		// First, skip past all the maps in the ordered collection
		// of maps. We want to begin the search with this node.
		int i = 0;
		for (; i < maps.length; i++) {
			if (maps[i] == mapNode)
				break;
		}

		// Now search go through each map node until a child node matching
		// its DOM name is found.
		Node insertBeforeNode = null;
		for (int j = i; j < maps.length && insertBeforeNode == null; j++) {
			NodeList childNodes = parentNode.getChildNodes();
			Translator nodeToFindMap = maps[j];
			for (int k = 0; k < childNodes.getLength(); k++) {
				Node node = childNodes.item(k);
				if (nodeToFindMap.isMapFor(node.getNodeName())) {
					insertBeforeNode = node;
					break;
				}
			}
		}
		return insertBeforeNode;
	}

	/*
	 * Traverses the path that <map> specifies. Returns the last node of the path that was able to
	 * be traversed or null if the path could not be traversed. The <addAdapters> boolean is used to
	 * determine if the receiver is added as an adapter to every node found on the path.
	 */
	protected Node findDOMPath(Node parent, Translator map, boolean addAdapters) {

		String path = map.getDOMPath();
		Node curNode = parent;
		Iterator iter = DOMUtilities.createPathIterator(path);

		while (curNode != null && iter.hasNext()) {
			String nodeName = (String) iter.next();
			curNode = DOMUtilities.getNodeChild(curNode, nodeName);
			if (addAdapters && curNode != null) {
				addDOMAdapter(curNode);
			}
		}
		return curNode;
	}

	/**
	 * Return the list of DOM node children that currently exist with the specified tagname.
	 */
	protected List getDOMChildren(Node node, Translator map) {
		Node parent = findDOMPath(node, map, true);
		if (parent != null)
			return DOMUtilities.getNodeChildren(parent, map.getDOMNames());
		return new ArrayList();
	}

	protected EMF2DOMAdapter getExistingAdapter(EObject refObject) {
		EMF2DOMAdapter adapter = (EMF2DOMAdapter) EcoreUtil.getExistingAdapter(refObject, EMF2DOMAdapter.ADAPTER_CLASS);
		if (adapter != null && adapter.isMOFProxy()) {
			removeDOMAdapter(adapter.getNode(), adapter);
			refObject.eAdapters().remove(adapter);
			adapter = null;
		}
		return adapter;
	}

	protected void primAddDOMAdapter(Node aNode, EMF2DOMAdapter anAdapter) {
		fRenderer.registerDOMAdapter(aNode, anAdapter);
	}

	protected EMF2DOMAdapter primGetExistingAdapter(Node aNode) {
		return fRenderer.getExistingDOMAdapter(aNode);
	}

	protected void removeDOMAdapter(Node aNode, EMF2DOMAdapter anAdapter) {
		fRenderer.removeDOMAdapter(aNode, anAdapter);
	}

	protected void addDOMAdapter(Node childNode) {

		// Only add the adapter if this is an child node that will not be
		// adapted. For instance a subtree that maps to a MOF attribute
		// setting.
		if (childNode.getNodeType() == Node.ELEMENT_NODE) {
			EMF2DOMAdapter attrAdapter = primGetExistingAdapter(childNode);

			if (attrAdapter == null || attrAdapter.getNode() != getNode()) {
				// If the node is adapted, but not by this adapter then remove
				// it. This happens to non-object children when the parent tag
				// name is changed.
				removeDOMAdapter(childNode, attrAdapter);

				if (fDebug) {
					EcoreUtilitiesPlugin.logError("\tCHILD: Adding DOM adapter: " + this); //$NON-NLS-1$
					EcoreUtilitiesPlugin.logError("\t\tto: " + childNode); //$NON-NLS-1$
				}
				primAddDOMAdapter(childNode, this);
			}
		}
	}

	/**
	 * Reorder a child before a given node
	 */
	protected void reorderDOMChild(Node parentNode, Node childNode, Node insertBeforeNode, Translator map) {
		try {
			removeDOMChild(parentNode, childNode, false);
			parentNode.insertBefore(childNode, insertBeforeNode);
		} catch (Exception e) {
			EcoreUtilitiesPlugin.logError(e);
		}
	}

	protected String getNewlineString(Node node) {
		return DOMUtilities.NEWLINE_STRING;
	}

	protected String primGetIndentString(Node node) {
		return DOMUtilities.getIndentString(node);
	}

	/**
	 * Remove a child node
	 */
	protected void removeDOMChild(Node parentNode, Node childNode) {
		removeDOMChild(parentNode, childNode, true);
	}

	/**
	 * Remove a child node
	 */
	protected void removeDOMChild(Node parentNode, Node childNode, boolean removeAdapter) {
		try {
			if (childNode == null)
				return;
			// Look for any whitespace preceeding the node being
			// removed and remove it as well.
			Text prevText = DOMUtilities.getPreviousTextSibling(childNode);
			if (prevText != null && DOMUtilities.isWhitespace(prevText)) {
				parentNode.removeChild(prevText);
			}
			// Remove the node.
			if (removeAdapter)
				removeAdapters(childNode);
			parentNode.removeChild(childNode);
		} catch (Exception e) { 
			EcoreUtilitiesPlugin.logError(e);
		}
	}

	/**
	 * Remove the DOM adapters from the node AND all its child nodes, recursively.
	 */
	public void removeAdapters(Node node) {
		EMF2DOMAdapter adapter = primGetExistingAdapter(node);
		if (adapter != null) {
			// Remove the adapter from both the DOM node and the MOF Object.
			removeDOMAdapter(node, adapter);
			if (adapter.getNode() == node) {
				Notifier localTarget = adapter.getTarget();
				if (localTarget != null)
					localTarget.eAdapters().remove(adapter);
			}
		}
		NodeList nl = node.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node n = nl.item(i);
			removeAdapters(n);
		}
	}

	/**
	 * Creates the path specified by <map>under <node>. Only the portion of the path that does not
	 * exist (if any) is created
	 * 
	 * @param node
	 *            org.w3c.dom.Node
	 * @param map
	 *            com.ibm.etools.mof2dom.Translator
	 */
	protected Node createDOMPath(Node node, Translator map) {
		Iterator i = DOMUtilities.createPathIterator(map.getDOMPath());
		Node curNode = node;
		while (i.hasNext()) {
			String nodeName = (String) i.next();
			curNode = findOrCreateNode(node, map, nodeName);
		}
		return curNode;
	}

	protected Element findOrCreateNode(Node parent, Translator map, String segment) {
		Node node = DOMUtilities.getNodeChild(parent, segment);
		if (node == null) {
			// The node did not already exist, create it.
			Document doc = parent.getOwnerDocument();
			node = doc.createElement(segment);
			if (map.isEmptyTag())
				setEmptyTag((Element) node);

			Node insertBeforeNode = findInitialInsertBeforeNode(parent, map);
			DOMUtilities.insertBeforeNodeAndWhitespace(parent, node, insertBeforeNode);
			indent(node, map);
			addDOMAdapter(node); // Hook up listeners
		}
		return (Element) node;
	}

	/**
	 * Remove the node passed in if it has only whitespace nodes as children
	 * 
	 * @param node
	 *            org.w3c.dom.Node The node to check
	 */
	protected void removeIfEmpty(Node node) {
		NodeList nl = node.getChildNodes();

		// Run through all the nodes children. If a non-whitespace node
		// pis found, bail.
		for (int i = 0; i < nl.getLength(); i++) {
			Node childNode = nl.item(i);
			if (!DOMUtilities.isWhitespace(childNode))
				return;
		}

		// We only get here if there are no non-whitespace chars, so
		// simply remove the node.
		removeDOMChild(node.getParentNode(), node);
	}

	/**
	 * Remove the DOM path specified by <map>from <node>
	 */
	protected void removeDOMPath(Node node, Translator map) {
		Node childNode = findDOMPath(node, map, false);
		while (childNode != null && childNode != node) {
			removeIfEmpty(childNode);
			childNode = childNode.getParentNode();
		}
	}

	/**
	 * Create an adapter for a child DOM node
	 * 
	 * @param node
	 *            org.w3c.dom.Node The node to create the adapter for.
	 */
	protected EMF2DOMAdapter createAdapter(EObject mofObject, Translator childMap) {
		//	Assert.isNotNull(childMap.getChildAdapterClass());
		Assert.isNotNull(mofObject);

		EMF2DOMAdapter adapter = (EMF2DOMAdapter) EcoreUtil.getAdapter(mofObject.eAdapters(), EMF2DOMAdapter.ADAPTER_CLASS);

		if (adapter != null && adapter.isMOFProxy()) {
			removeAdapters(adapter.getNode());
			mofObject.eAdapters().remove(adapter);
			adapter = null;
		}
		if (adapter == null)
			adapter = primCreateAdapter(mofObject, childMap);
		return adapter;
	}

	/**
	 * Create an adapter for a child DOM node
	 * 
	 * @param node
	 *            org.w3c.dom.Node The node to create the adapter for.
	 */
	protected EMF2DOMAdapter primCreateAdapter(EObject mofObject, Translator childMap) {

		Element newNode = createNewNode(mofObject, childMap);
		return new EMF2DOMAdapterImpl(mofObject, newNode, fRenderer, childMap);
	}

	/**
	 * Create an adapter for a child DOM node
	 * 
	 * @param node
	 *            org.w3c.dom.Node The node to create the adapter for.
	 */
	protected EMF2DOMAdapter primCreateAdapter(Node node, Translator childMap) {
		return new EMF2DOMAdapterImpl(node, fRenderer, childMap);
	}

	/**
	 * Create an adapter for a child DOM node
	 * 
	 * @param node
	 *            org.w3c.dom.Node The node to create the adapter for.
	 */
	protected EMF2DOMAdapter createAdapter(Node node, Translator childMap) {

		//Assert.isNotNull(childMap.getChildAdapterClass());
		Assert.isNotNull(node);

		EMF2DOMAdapter adapter = primGetExistingAdapter(node);

		if (adapter != null) {
			if (adapter.isMOFProxy() || adapter.getTarget() == null) {
				removeDOMAdapter(node, adapter);
				if (adapter.getTarget() != null) {
					adapter.getTarget().eAdapters().remove(adapter);
				}
				adapter = null;
			}
		} else {
			adapter = primCreateAdapter(node, childMap);
		}
		return adapter;
	}

	protected Element createNewNode(EObject mofObject, Translator childMap) {
		Node node = getNode();
		Document doc = (node instanceof Document) ? (Document) node : node.getOwnerDocument();

		Element element = doc.createElement(childMap.getDOMName(mofObject));
		if (childMap.isEmptyTag())
			setEmptyTag(element);

		return element;
	}

	protected void setEmptyTag(Element element) {
		Revisit.toDo();
		//Need to figure out how to do this with pure DOM apis, if it is
		// possible
	}

	/*
	 * Return true if MOF object is a proxy.
	 */
	public boolean isMOFProxy() {
		if (isRoot || target == null)
			return false;
		return ((InternalEObject) target).eIsProxy();
	}

	public EObject getEObject() {
		if (isRoot)
			return null;
		return (EObject) target;
	}

	/**
	 * Return the DOM node that the target of this adapter maps to. If the target MOF object maps to
	 * more than one DOM node, this node is the top-most node.
	 */
	public Node getNode() {
		return fNode;
	}

	public void setNode(Node aNode) {
		fNode = aNode;
	}

	public void updateDOM() {
		if (!isNotificationEnabled())
			return;
		primUpdateDOM();
	}

	public void updateMOF() {
		if (!isNotificationEnabled())
			return;
		primUpdateMOF();
	}

	protected void primUpdateDOM() {
		if (isRoot)
			updateDOMRootFeature();
		else {
			Translator[] maps = getChildTranslators();
			for (int i = 0; i < maps.length; i++) {
				updateDOMFeature(maps[i], getNode(), getEObject());
			}
		}
	}

	public void primUpdateMOF() {
		if (isRoot)
			updateMOFRootFeature();
		else {
			Translator[] maps = getChildTranslators();
			for (int i = 0; i < maps.length; i++) {
				updateMOFFeature(maps[i], getNode(), getEObject());
			}
		}
	}

	protected void updateDOMRootFeature() {
		boolean notificationFlag = isNotificationEnabled();
		try {
			setNotificationEnabled(false);
			primUpdateDOMMultiFeature(fTranslator, fNode, getResourceContents(), getDOMChildren(fNode, fTranslator), null);
			updateDOMDocumentType();
		} finally {
			setNotificationEnabled(notificationFlag);
		}
	}

	protected void updateMOFRootFeature() {
		boolean notificationFlag = isNotificationEnabled();
		try {
			setNotificationEnabled(false);
			updateMOFDocumentType();
			primUpdateMOFMultiFeature(fTranslator, fNode, getResourceContents(), getDOMChildren(fNode, fTranslator));
		} finally {
			setNotificationEnabled(notificationFlag);
		}
	}

	protected DocumentType getDocumentType() {
		return ((Document) fNode).getDoctype();
	}

	protected TranslatorResource getResource() {
		return (TranslatorResource) getTarget();
	}

	protected EList getResourceContents() {
		if (!isRoot)
			throw new IllegalStateException();
		return ((Resource) getTarget()).getContents();
	}

	protected void updateDOMDocumentType() {

		DocumentType docType = getDocumentType();
		String publicId = null, systemId = null, oldPublicId, oldSystemId;
		oldPublicId = docType == null ? null : docType.getPublicId();
		oldSystemId = docType == null ? null : docType.getSystemId();
		TranslatorResource resource = getResource();
		if (resource != null) {
			publicId = resource.getPublicId();
			systemId = resource.getSystemId();
			if (!(StringUtil.stringsEqual(publicId, oldPublicId) && StringUtil.stringsEqual(systemId, oldSystemId)))
				fRenderer.replaceDocumentType(resource.getDoctype(), publicId, systemId);
		}
	}

	protected void updateDOMDocumentType(Notification msg) {
		if (msg.getFeature() == TranslatorResource.DOC_TYPE_FEATURE)
			updateDOMDocumentType();
	}

	protected void updateMOFDocumentType() {

		TranslatorResource resource = getResource();
		if (resource == null)
			return;

		String publicId = null, systemId = null;
		DocumentType docType = getDocumentType();

		if (docType != null) {
			publicId = docType.getPublicId();
			systemId = docType.getSystemId();
		}
		if ((!(StringUtil.stringsEqual(publicId, resource.getPublicId()) && StringUtil.stringsEqual(systemId, resource.getSystemId()))) || 
				((resource.getPublicId() == null) || resource.getSystemId() == null))
			resource.setDoctypeValues(publicId, systemId);
	}

	@Override
	public void notifyChanged(Notification msg) {

		if (isRoot) {
			notifyChangedForRoot(msg);
			return;
		}
		if (isDependencyFeature(msg))
			handleDependencyFeature(msg);

		if (!isNotificationEnabled())
			return;

		debugMOFNotify(msg);

		switch (msg.getEventType()) {
			case Notification.ADD :
			case Notification.REMOVE :
			case Notification.ADD_MANY :
			case Notification.REMOVE_MANY :
			case Notification.SET :
			case Notification.UNSET :
			case Notification.MOVE :
				Translator translator = findTranslator(msg);
				if (translator == null)
					translator = addVariableTranslatorIfNecessary(msg);
				if (translator != null)
					updateDOMFeature(translator, getNode(), getEObject());
				break;
		}
	}

	protected void notifyChangedForRoot(Notification msg) {
		if (!isNotificationEnabled())
			return;

		debugMOFNotify(msg);

		switch (msg.getEventType()) {
			case Notification.ADD :
			case Notification.REMOVE :
			case Notification.ADD_MANY :
			case Notification.REMOVE_MANY :
				primUpdateDOM();
				break;
			case Notification.SET :
				updateDOMDocumentType(msg);
				break;
			case EtoolsCopySession.RESOURCE_COPIED :
				updateDOM();
				break;
		}
	}

	protected void addDependencyAdapter(EObject child) {
		Adapter existing = EcoreUtil.getExistingAdapter(child, DependencyAdapter.KEY);
		if (existing != null)
			return;
		DependencyAdapter forwarder = new DependencyAdapter();
		child.eAdapters().add(forwarder);
		forwarder.setTarget(child);
	}

	protected void addDOMAdapter() {

		primAddDOMAdapter(fNode, this);
		if (fDebug) {
			EcoreUtilitiesPlugin.logError("Adding DOM adapter: " + this); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tto: " + fNode); //$NON-NLS-1$
		}

		// Go through the maps. All of the DOM nodes that are not listened
		// to by another DOM Node adapter, must be listened to by this adapter.
		NodeList childNodes = fNode.getChildNodes();
		for (int j = 0; j < childNodes.getLength(); j++) {
			Node childNode = childNodes.item(j);
			int nodeType = childNode.getNodeType();
			if (!DOMUtilities.isTextNode(childNode) && nodeType != Node.COMMENT_NODE) {
				Translator map = findTranslator(childNode.getNodeName(), false);
				if (map != null && map.isManagedByParent())
					addDOMAdapter(childNode);
			}
		}
	}

	protected Translator addVariableTranslatorIfNecessary(Notification msg) {
		VariableTranslatorFactory fact = fTranslator.getVariableTranslatorFactory();
		Translator trans = null;
		if (fact != null && fact.accepts(msg)) {
			trans = fact.create(msg);
			if (trans != null)
				childTranslators = (Translator[]) Translator.concat(childTranslators, trans);
		}
		return trans;
	}

	protected Text createTextNode(Document doc, Translator map, String text) {
		String nonnulltext = (text != null) ? text : ""; //$NON-NLS-1$
		return map.isCDATAContent() ? doc.createCDATASection(nonnulltext) : doc.createTextNode(nonnulltext);
	}

	protected String extractReadAheadName() {
		if (!fTranslator.hasReadAheadNames())
			return null;
		String readAheadName = null;

		ReadAheadHelper helper = fTranslator.getReadAheadHelper(fNode.getNodeName());
		if (helper == null)
			return null;

		Node child = null;
		String[] names = helper.getValues();
		if (helper.getChildDOMName() == null) {
			for (int i = 0; i < names.length; i++) {
				child = DOMUtilities.getNodeChild(fNode, names[i]);
				if (child != null) {
					readAheadName = names[i];
					break;
				}
			}
		} else {
			child = DOMUtilities.getNodeChild(fNode, helper.getChildDOMName());
			if (child != null)
				readAheadName = DOMUtilities.getChildText(child);
		}
		if (readAheadName == null)
			readAheadName = names[0];
		return readAheadName;
	}

	/**
	 * Extracts the text from <node>and converts it to an object suitable for setting into <feature>
	 */
	protected Object extractValue(Node node, Translator map, EObject emfObject) {

		// Extract the value from the text child
		Node textNode = DOMUtilities.getChildTextNode(node);
		String trimmedValue = null;
		if (textNode != null)
			trimmedValue = textNode.getNodeValue();
		try {
			return map.convertStringToValue(trimmedValue, emfObject);
		} catch (FeatureValueConversionException ex) {
			handleFeatureValueConversionException(ex);
			return null;
		}
	}

	/**
	 * @param ex
	 */
	protected void handleFeatureValueConversionException(FeatureValueConversionException ex) {
		throw ex;

	}

	/*
	 * Finds the child node that <map> specifies. If there is more than one child that satisfies
	 * <map> then the first one is returned.
	 * 
	 * This method traverses past the domPath if one is specified in the <map>.
	 */
	protected Node findDOMNode(Node parent, Translator map) {
		return findDOMNode(parent, map, false);
	}

	/*
	 * Finds the child node that <map> specifies. If there is more than one child that satisfies
	 * <map> then the first one is returned. The <addAdapters> boolean is used to determine if the
	 * receiver is added as an adapter to every node found on the path.
	 * 
	 * This method traverses past the domPath if one is specified in the <map>.
	 */
	protected Node findDOMNode(Node parent, Translator map, boolean addAdapters) {

		// First, trace down the path
		Node curNode = findDOMPath(parent, map, addAdapters);
		if (map.isDOMTextValue() || map.isDOMAttribute() || curNode == null)
			return curNode;

		// Now look for the first DOM name we can find
		String[] domNames = map.getDOMNames();
		Node node = null;
		for (int i = 0; i < domNames.length; i++) {
			String nodeName = domNames[i];
			List nodes = DOMUtilities.getNodeChildren(curNode, nodeName);
			if (nodes != null && !nodes.isEmpty()) {
				if (nodes.size() > 1)
					handleInvalidMultiNodes(nodeName);
				node = (Node) nodes.get(0);
				if (node != null) {
					if (addAdapters)
						addDOMAdapter(curNode);
					break;
				}
			}
		}
		return node;
	}

	protected void handleInvalidMultiNodes(String nodeName) {
		throw new IllegalStateException(WFTUtilsResourceHandler.getString(WFTUtilsResourceHandler.EMF2DOMAdapterImpl_ERROR_0, new Object[]{nodeName}));
	}

	/**
	 * Creates the path specified by <map>under <node>. Only the portion of the path that does not
	 * exist (if any) is created
	 * 
	 * @param node
	 *            org.w3c.dom.Node
	 * @param map
	 *            com.ibm.etools.mof2dom.Translator
	 */
	protected Text findOrCreateTextNode(Node parent, Translator map, String text) {
		Text textNode = DOMUtilities.getChildTextNode(parent);
		if (textNode != null) {
			textNode.setData(text);
		} else {
			if (!isEmptyTag((Element) parent)) {
				Text newNode = createTextNode(parent.getOwnerDocument(), map, text);
				DOMUtilities.insertBeforeNode(parent, newNode, null);
				return newNode;
			}
		}
		return textNode;
	}

	protected Translator findTranslator(String tagName, boolean attributeMap) {
		Translator[] maps = getChildTranslators();
		for (int i = 0; i < maps.length; i++) {
			Translator map = maps[i];
			if (map.isMapFor(tagName) && attributeMap == map.isDOMAttribute())
				return maps[i];
		}

		return null;
	}

	protected EMF2DOMAdapter getExistingAdapter(Node aNode) {
		EMF2DOMAdapter adapter = primGetExistingAdapter(aNode);
		if (adapter != null && adapter.isMOFProxy()) {
			removeDOMAdapter(aNode, adapter);
			adapter.getTarget().eAdapters().remove(adapter);
			adapter = null;
		}
		return adapter;
	}

	protected void handleDependencyFeature(Notification msg) {
		if (msg.getOldValue() != null)
			removeDependencyAdapter((EObject) msg.getOldValue());
		if (msg.getNewValue() != null)
			addDependencyAdapter((EObject) msg.getNewValue());
	}

	protected boolean isDependencyFeature(Notification msg) {
		switch (msg.getEventType()) {
			case Notification.SET :
				return fTranslator.isDependencyParent() && fTranslator.getDependencyFeature() == msg.getFeature();
			default :
				return false;
		}
	}

	protected boolean isEmptyTag(Element parent) {
		Revisit.toDo();
		//Determine how to implement this with pure DOM apis, if possible.
		return false;
	}

	protected void postUpdateDOMFeature(Translator map, Node node, EObject mofObject) {
	}

	protected void preUpdateDOMFeature(Translator map, Node node, EObject mofObject) {
	}

	/**
	 * Update an attribute of the target DOM object from with the values currently stored in the MOF
	 * object. The
	 * 
	 * @map specifies the name of the MOF attribute to update and the name of the DOM node.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator
	 */
	protected void primUpdateDOMFeature(Translator map, Node node, EObject mofObject) {
		Object attrValue = null;
		boolean isSet = false;
		if (map.isIDMap()) {
			try {
				attrValue = map.getMOFValue(mofObject);
			} catch (IDTranslator.NoResourceException ex) {
				//If the object has been removed from the resource,
				//No need to update
				return;
			}
			isSet = attrValue != null;
		} else {
			attrValue = map.getMOFValue(mofObject);
			isSet = map.isSetMOFValue(mofObject);
		}

		if (map.isDOMAttribute()) {
			// An attribute of the MOF object maps to an attribute of the
			// DOM node. Get the value of the MOF attribute and set it
			// into DOM node.
			Element e = (Element) createDOMPath(node, map);
			if (attrValue != null && isSet)
				e.setAttribute(map.getDOMName(mofObject), map.convertValueToString(attrValue, mofObject));
			else
				e.removeAttribute(map.getDOMName(mofObject));
		} else {
			updateDOMSubtree(map, node, mofObject, attrValue);
		}
	}

	/**
	 * Update an attribute of the target DOM object from with the values currently stored in the MOF
	 * object. The
	 * 
	 * @map specifies the name of the MOF attribute to update and the name of the DOM node.
	 */
	protected void primUpdateDOMLinkFeature(Translator map, Node node, EObject mofObject) {
		LinkUpdaterTarget.INSTANCE.updateDOM(map, node, mofObject);

	}

	/**
	 * Update all the children of the target MOF object in the relationship described by
	 * 
	 * @map.
	 */
	protected void primUpdateDOMMultiFeature(Translator map, Node node, EObject mofObject) {

		List mofChildren = map.getMOFChildren(mofObject);
		List domChildren = getDOMChildren(node, map);

		primUpdateDOMMultiFeature(map, node, mofChildren, domChildren, mofObject);
	}

	/**
	 * Update an attribute of the target MOF object from the DOM node subtree. The
	 * 
	 * @map specifies the name of the MOF attribute to update and the name of the DOM node.
	 */
	protected boolean primUpdateMOFFeature(Translator map, Node node, EObject mofObject) {
		if (!map.featureExists(mofObject))
			return false;
		Object domValue = null;
		boolean updateMOFAttAdapter = false;
		boolean isUnset = false;
		EMF2DOMAdapter attrAdapter = null;

		Node child = findDOMNode(node, map, true);

		if (map.isDOMAttribute() && child != null) {
			// An attribute of the MOF object maps to an attribute of the
			// DOM node. Get the value of the DOM attribute and set it
			// into the MOF object.

			Attr domAttr = (Attr) child.getAttributes().getNamedItem(map.getDOMName(mofObject));
			if (domAttr != null) {
				domValue = domAttr.getValue();
				domValue = map.convertStringToValue((String) domValue, mofObject);
			} else
				isUnset = true;
		} else {
			// An attribute of the MOF object is actually a sub-element
			// of the DOM node. Search for the first sub-element with
			// the correct name to use as an attribute.
			if (child != null) {
				// Check to see if this is a single valued attribute that has
				// a MOF object as its value
				if (!map.isManagedByParent()) {
					attrAdapter = createAdapter(child, map);
					updateMOFAttAdapter = true;
					domValue = attrAdapter.getTarget();
				} else {
					// Check to make sure the child is adapted. If not, adapt
					// it.
					addDOMAdapter(child);

					// Extract the value from the text child
					domValue = extractValue(child, map, mofObject);
				}
			} else
				isUnset = true;
		}

		// Set the attribute extracted from the DOM to the MOF object.
		boolean hasChanged = true;
		try {
			if (map.isIDMap())
				map.setMOFValue(mofObject, domValue);
			else {
				Object oldValue = null;
				oldValue = map.getMOFValue(mofObject);
				boolean isSet = map.isSetMOFValue(mofObject);
				//In the case of enums with default values, we need to trip
				// the attribute from
				//default to a set value
				if (oldValue == domValue) {
					if (oldValue == null || isSet)
						hasChanged = false;
				} else if (domValue == null && !isSet)
					//If the domValue is null and the feature is not set, then
					// we don't need
					//to do anything
					hasChanged = false;
				else if (oldValue != null && oldValue.equals(domValue) && isSet)
					hasChanged = false;
				if (oldValue == null && domValue == null && map.isSetMOFValue(mofObject) == isUnset)
					hasChanged = true;
				if (hasChanged) {
					if (!(map.isDataType()) && !map.isShared())
						removeMOFValue((EObject) oldValue, map);
					if (domValue == null)
						map.unSetMOFValue(mofObject);
					else
						map.setMOFValue(mofObject, domValue);

					if ((domValue == null && !(map.isEnumFeature())) || isUnset)
						map.unSetMOFValue(mofObject); //unset
					// null
					// for
					// non
					// enum
					// features

					if (updateMOFAttAdapter && attrAdapter != null)
						attrAdapter.updateMOF();
				}
			}
		} catch (FeatureValueConversionException ex) {
			handleFeatureValueConversionException(ex);
			map.unSetMOFValue(mofObject);
		}
		return hasChanged;
	}

	/**
	 * Update an attribute of the target MOF object from the DOM node subtree. This method is only
	 * called if the DOM node changes and the map is an object link map. The
	 * 
	 * @map specifies the name of the MOF attribute to update and the name of the DOM node.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator
	 * @return Return true if the MOF feature was updated, false if no update was done.
	 */
	protected void primUpdateMOFLinkFeature(Translator map, Node node, EObject mofObject) {
		LinkUpdaterTarget.INSTANCE.updateMOF(map, node, mofObject);
	}

	/**
	 * Update all the children of the target MOF object in the relationship described by
	 * 
	 * @map.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator Describes the mapping from the MOF
	 *            attribute name to the DOM node name
	 */
	protected void primUpdateMOFMultiFeature(Translator map, Node node, EObject mofObject) {
		// If the feature is a collection of strings or ints, call a special
		// method
		// that handles this.
		if (map.isManagedByParent()) {
			updateMOFMultiPrimitiveFeature(map, node, mofObject);
			return;
		}

		List nodeChildren = getDOMChildren(node, map);
		List mofChildren = map.getMOFChildren(mofObject);

		primUpdateMOFMultiFeature(map, node, mofChildren, nodeChildren);
	}

	protected void removeDependencyAdapter(EObject obj) {
		Adapter existing = EcoreUtil.getExistingAdapter(obj, DependencyAdapter.KEY);
		if (existing != null)
			obj.eAdapters().remove(existing);
	}

	/**
	 * Removes all the DOM children from <parent>that are represented by <map>.
	 */
	protected void removeDOMChildren(Node parent, Translator map) {
		String[] domNames = map.getDOMNames();
		HashSet domNamesSet = new HashSet(domNames.length);
		for (int i = 0; i < domNames.length; i++)
			domNamesSet.add(domNames[i]);

		// Walk through all the children and find any that match the map.
		NodeList nl = parent.getChildNodes();
		List toRemove = new ArrayList();
		for (int i = 0; i < nl.getLength(); i++) {
			Node childNode = nl.item(i);
			if (domNamesSet.contains(childNode.getNodeName()))
				toRemove.add(childNode);
		}

		// Remove any children that were found.
		for (int i = 0; i < toRemove.size(); i++) {
			Node childNode = (Node) toRemove.get(i);
			removeDOMChild(parent, childNode, true);
		}
	}

	protected void setTargetFromNode() {
		setTarget(fTranslator.createEMFObject(fNode.getNodeName(), extractReadAheadName()));
	}

	/**
	 * Update an attribute of the target DOM object from with the values currently stored in the MOF
	 * object. The
	 * 
	 * @map specifies the name of the MOF attribute to update and the name of the DOM node.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator
	 */
	final public void updateDOMFeature(Translator map, Node node, EObject mofObject) {
		if (!isNotificationEnabled())
			return;
		try {
			preUpdateDOMFeature(map, node, mofObject);
			if (map.isMultiValued()) {
				updateDOMMultiFeature(map, node, mofObject);
				return;
			}

			if (fDebug) {
				EcoreUtilitiesPlugin.logError("Updating DOM Node: " + node); //$NON-NLS-1$
				EcoreUtilitiesPlugin.logError("\tfrom: " + mofObject); //$NON-NLS-1$
				EcoreUtilitiesPlugin.logError("\tmap : " + map); //$NON-NLS-1$
			}
			boolean notificationFlag = isNotificationEnabled();
			try {
				setNotificationEnabled(false);
				primUpdateDOMFeature(map, node, mofObject);
			} finally {
				setNotificationEnabled(notificationFlag);
			}

			if (map.isTargetLinkMap()) {
				updateDOMLinkFeature(map, node, mofObject);
			}
		} finally {
			postUpdateDOMFeature(map, node, mofObject);
		}
	}

	/**
	 * Update an attribute of the target DOM object from the values currently stored in the MOF
	 * object. The
	 * 
	 * @map specifies the name of the MOF attribute to update and the name of the DOM node.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator
	 */
	final protected void updateDOMLinkFeature(Translator map, Node node, EObject mofObject) {
		if (fDebug) {
			EcoreUtilitiesPlugin.logError("Updating DOM Node (link): " + node); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tfrom: " + mofObject); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tmap : " + map); //$NON-NLS-1$
		}
		primUpdateDOMLinkFeature(map, node, mofObject);
	}

	/**
	 * Update all the children of the target MOF object in the relationship described by
	 * 
	 * @map.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator Describes the mapping from the MOF
	 *            attribute name to the DOM node name
	 */
	final protected void updateDOMMultiFeature(Translator map, Node node, EObject mofObject) {
		if (fDebug) {
			EcoreUtilitiesPlugin.logError("Updating DOM Node (multi): " + node); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tfrom: " + mofObject); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tmap : " + map); //$NON-NLS-1$
		}
		boolean notificationFlag = isNotificationEnabled();
		try {
			setNotificationEnabled(false);
			primUpdateDOMMultiFeature(map, node, mofObject);
		} finally {
			setNotificationEnabled(notificationFlag);
		}
	}

	/**
	 * Update a DOM subtree to reflect the mofObject and map passed in. The subtree is of <node>is
	 * updated.
	 */
	protected void updateDOMSubtree(Translator map, Node node, EObject mofObject, Object attrValue) {
		Object innerAttrValue = attrValue;
		if (map.featureExists(mofObject)) {
			if ((map.isEnumFeature() || map.isBooleanFeature()) && (map.isUnsettable() && !map.isSetMOFValue(mofObject)))
				innerAttrValue = null;
		} else
			innerAttrValue = map.extractStringValue(mofObject);

		// Create and/or update the DOM subtree
		if (innerAttrValue != null) {
			Node parent = createDOMPath(node, map);
			if (map.isManagedByParent()) {
				// Handle the case where the mof value is not another
				// mof object (primitive)
				if (map.getDOMName(mofObject) != null && map.getDOMName(mofObject).startsWith("#")) //$NON-NLS-1$
					return;

				Element child = map.isDOMTextValue() ? (Element) parent : findOrCreateNode(parent, map, map.getDOMName(mofObject));

				findOrCreateTextNode(child, map, map.convertValueToString(innerAttrValue, mofObject));
			} else {
				// Handle the case were the mof value is a mof object.
				EObject mofValue = (EObject) innerAttrValue;
				EMF2DOMAdapter valueAdapter = (EMF2DOMAdapter) EcoreUtil.getExistingAdapter(mofValue, EMF2DOMAdapter.ADAPTER_CLASS);
				if (valueAdapter != null)
					valueAdapter.updateDOM();
				else {
					removeDOMChildren(parent, map);
					EMF2DOMAdapter adapter = createAdapter(mofValue, map);
					List mofChildren = map.getMOFChildren(mofObject);
					List domChildren = getDOMChildren(parent, map);

					Node insertBeforeNode = findInsertBeforeNode(parent, map, mofChildren, 0, domChildren);
					DOMUtilities.insertBeforeNodeAndWhitespace(parent, adapter.getNode(), insertBeforeNode);
					boolean notificationFlag = adapter.isNotificationEnabled();
					adapter.setNotificationEnabled(false);
					try {
						indent(adapter.getNode(), map);
					} finally {
						adapter.setNotificationEnabled(notificationFlag);
					}
					adapter.updateDOM();
				}
			}
		} else {
			// The attribute value was set to null or unset. Remove any
			// existing DOM nodes.
			Node child = findDOMNode(node, map);
			if (child != null)
				removeDOMChild(child.getParentNode(), child);
		}
	}

	/**
	 * Update a feature that is set by linking to another existing object. This method is called
	 * when the MOF object is updated in order to update DOM nodes.
	 */
	final protected void updateMOFLinkFeature(Translator map, Node node, EObject mofObject) {
		if (fDebug) {
			EcoreUtilitiesPlugin.logError("Updating MOFObject (link): " + mofObject); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tfrom: " + node); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tmap : " + map); //$NON-NLS-1$
		}
		boolean notificationFlag = isNotificationEnabled();
		try {
			setNotificationEnabled(false);
			primUpdateMOFLinkFeature(map, node, mofObject);
		} finally {
			setNotificationEnabled(notificationFlag);
		}
	}

	/**
	 * Update all the children of the target MOF object in the relationship described by
	 * 
	 * @map.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator Describes the mapping from the MOF
	 *            attribute name to the DOM node name
	 */
	final protected void updateMOFMultiFeature(Translator map, Node node, EObject mofObject) {
		if (fDebug) {
			EcoreUtilitiesPlugin.logError("Updating MOFObject (multi): " + mofObject); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tfrom: " + node); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tmap : " + map); //$NON-NLS-1$
		}
		boolean notificationFlag = isNotificationEnabled();
		try {
			setNotificationEnabled(false);
			primUpdateMOFMultiFeature(map, node, mofObject);
		} finally {
			setNotificationEnabled(notificationFlag);
		}
	}

	/**
	 * Update all the children of the target MOF object in the relationship described by
	 * 
	 * @map. The relationship MUST BE a collection of string for this method to work.
	 */
	protected void updateMOFMultiPrimitiveFeature(Translator map, Node node, EObject mofObject) {
		List nodeChildren = getDOMChildren(node, map);

		map.clearList(mofObject);

		// Go through the list of nodes and update the MOF collection
		int addIndex = 0;
		for (int i = 0; i < nodeChildren.size(); i++) {
			Node child = (Node) nodeChildren.get(i);
			Object attributeValue = extractValue(child, map, mofObject);
			boolean advanceAddIndex = true;
			if (attributeValue != null){
				if(map.getFeature() != null && map.getFeature().isUnique() && mofObject.eGet(map.getFeature()) != null && mofObject.eGet(map.getFeature()) instanceof List && ((List) mofObject.eGet(map.getFeature())).contains(attributeValue)){
					advanceAddIndex = false;
					String domName = map.domNameAndPath != null ? map.domNameAndPath : "attribute"; //$NON-NLS-1$
					EcoreUtilitiesPlugin.logError(new IllegalArgumentException("The 'no duplicates' constraint is violated by "+domName+" = "+attributeValue)); //$NON-NLS-1$ //$NON-NLS-2$
					handleInvalidMultiNodes(child.getNodeName());
				} else {
					map.setMOFValue(mofObject, attributeValue, addIndex);
				}
				if(advanceAddIndex){
					addIndex ++;
				}
			}
			
			// Adapt the node so update will occur.
			addDOMAdapter(child);
		}
		if (map.hasDOMPath() && nodeChildren.isEmpty() && findDOMPath(node, map, false) != null)
			map.setMOFValueFromEmptyDOMPath(mofObject);
	}

	/**
	 * Update an attribute of the target MOF object from the DOM node subtree. The
	 * 
	 * @map specifies the name of the MOF attribute to update and the name of the DOM node.
	 * 
	 * @param map
	 *            com.ibm.etools.mof2dom.AttributeTranslator
	 */
	public void updateMOFFeature(Translator map, Node node, EObject mofObject) {
		if (!isNotificationEnabled())
			return;
		if (map.isMultiValued()) {
			updateMOFMultiFeature(map, node, mofObject);
			return;
		} else if (map.isComment()) {
			updateMOFCommentFeature(map, node, mofObject);
			return;
		}

		// TODO MDE Add a map.isComment() and updateMOFCommentFeature(map, node, mofObject);

		if (fDebug) {
			EcoreUtilitiesPlugin.logError("Updating MOFObject: " + mofObject); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tfrom: " + node); //$NON-NLS-1$
			EcoreUtilitiesPlugin.logError("\tmap : " + map); //$NON-NLS-1$
		}
		boolean notificationFlag = isNotificationEnabled();
		boolean hasChanged = false;
		try {
			setNotificationEnabled(false);
			hasChanged = primUpdateMOFFeature(map, node, mofObject);
		} finally {
			setNotificationEnabled(notificationFlag);
		}

		if (map.isTargetLinkMap() && hasChanged)
			updateMOFLinkFeature(map, node, mofObject);
	}

	/**
	 * @param map
	 * @param node
	 * @param mofObject
	 */
	public void updateMOFCommentFeature(Translator map, Node node, EObject mofObject) {
		Node commentNode = node;
		/* scan up the dom to find the first comment node before this node */
		while ((commentNode = commentNode.getPreviousSibling()) != null && commentNode.getNodeType() != Node.COMMENT_NODE) {
			/* no comment available */
			if (commentNode.getNodeType() == Node.ELEMENT_NODE)
				return;
		}
		if (commentNode != null)
			map.setMOFValue(mofObject, commentNode.getNodeValue());

	}

}
