/*******************************************************************************
 * Copyright (c) 2001, 2008 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.xml.ui.internal.properties;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySheetEntry;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.IPropertySource2;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.ui.views.properties.IPropertySourceExtension;
import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMNamespaceHelper;
import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.ui.internal.Logger;
import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * An IPropertySource implementation for a JFace viewer used to display
 * properties of DOM nodes.
 */
public class XMLPropertySource implements IPropertySource, IPropertySourceExtension, IPropertySource2 {
	protected final static String CATEGORY_ATTRIBUTES = XMLUIMessages.XMLPropertySourceAdapter_0;

	private static final boolean fSetExpertFilter = false;

	/**
	 * derive categories from CMDataTypes; disabled until display strings can
	 * be planned
	 */
	private final static boolean fShouldDeriveCategories = false;

	private final static boolean fSortEnumeratedValues = true;

	/**
	 * Note: we want the default fCaseSensitive to be true, but, to avoid
	 * meaningless double initialization, we leave default here, and set in
	 * constructor only.
	 */
	private boolean fCaseSensitive;
	private IPropertyDescriptor[] fDescriptors = null;
	private Node fNode = null;

	private Stack fValuesBeingSet = new Stack();

	public XMLPropertySource(INodeNotifier target) {
		super();
		fNode = initNode(target);
		fCaseSensitive = initCaseSensitive(fNode);

	}

	/** seperate method just to isolate error processing */
	private Node initNode(INodeNotifier target) {
		Node node = null;
		if (target instanceof Node) {
			node = (Node) target;
		}
		else {
			throw new IllegalArgumentException("XMLPropertySource is only for Nodes"); //$NON-NLS-1$
		}
		return node;
	}

	private boolean initCaseSensitive(Node node) {
		// almost all tags are case senstive, except that old HTML
		boolean caseSensitive = true;
		DocumentTypeAdapter adapter = null;
		if (node instanceof IDOMNode) {
			adapter = getDocTypeFromDOMNode(node);
		}
		if (adapter != null) {
			caseSensitive = (adapter.getTagNameCase() == DocumentTypeAdapter.STRICT_CASE);
		}
		return caseSensitive;
	}

	/**
	 * by "internal spec" the DOCTYPE adapter is only available from Document
	 * Node
	 * 
	 * @return {@link DocumentTypeAdapter}
	 */
	private DocumentTypeAdapter getDocTypeFromDOMNode(Node node) {
		DocumentTypeAdapter adapter = null;
		Document ownerDocument = node.getOwnerDocument();
		if (ownerDocument == null) {
			// if ownerDocument is null, then fNode must be the Document Node
			// [old, old comment]
			// hmmmm, guess not. See
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=130233
			// guess this is used for many INodeNotifiers, not just XML.
			// (and DTD's use IDOMNode? ... that doesn't sound quite right
			// ... but, maybe a separate issue).
			if (node instanceof Document) {
				ownerDocument = (Document) node;
			}
		}
		if (ownerDocument != null) {
			adapter = (DocumentTypeAdapter) ((INodeNotifier) ownerDocument).getAdapterFor(DocumentTypeAdapter.class);
		}

		return adapter;
	}

	private String[] _getValidFixedStrings(CMAttributeDeclaration attrDecl, CMDataType helper) {
		String attributeName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
		List values = new ArrayList(1);
		String impliedValue = helper.getImpliedValue();
		if (impliedValue != null) {
			values.add(impliedValue);
		}
		boolean checkIfCurrentValueIsIncluded = ((fNode.getAttributes() != null) && (fNode.getAttributes().getNamedItem(attributeName) != null) && (fNode.getAttributes().getNamedItem(attributeName).getNodeValue() != null));
		if (checkIfCurrentValueIsIncluded) {
			String currentValue = null;
			currentValue = fNode.getAttributes().getNamedItem(attributeName).getNodeValue();
			if (!currentValue.equals(impliedValue)) {
				values.add(currentValue);
			}
		}
		String[] validStrings = new String[values.size()];
		validStrings = (String[]) values.toArray(validStrings);
		return validStrings;
	}

	private String[] _getValidStrings(CMAttributeDeclaration attrDecl, CMDataType valuesHelper) {
		String attributeName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
		List values = new ArrayList(1);
		boolean currentValueKnown = false;
		boolean checkIfCurrentValueIsKnown = ((fNode.getAttributes() != null) && (fNode.getAttributes().getNamedItem(attributeName) != null) && (fNode.getAttributes().getNamedItem(attributeName).getNodeValue() != null));
		String currentValue = null;
		if (checkIfCurrentValueIsKnown) {
			currentValue = fNode.getAttributes().getNamedItem(attributeName).getNodeValue();
		}

		if ((valuesHelper.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED) && (valuesHelper.getImpliedValue() != null)) {
			// FIXED value
			currentValueKnown = (currentValue != null) && valuesHelper.getImpliedValue().equals(currentValue);
			values.add(valuesHelper.getImpliedValue());
		}
		else {
			// ENUMERATED values
			String[] valueStrings = null;
			// valueStrings = valuesHelper.getEnumeratedValues();
			ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument());
			if ((modelQuery != null) && (fNode.getNodeType() == Node.ELEMENT_NODE)) {
				valueStrings = modelQuery.getPossibleDataTypeValues((Element) fNode, attrDecl);
			}
			else {
				valueStrings = attrDecl.getAttrType().getEnumeratedValues();
			}
			if (valueStrings != null) {
				for (int i = 0; i < valueStrings.length; i++) {
					if (checkIfCurrentValueIsKnown && valueStrings[i].equals(currentValue)) {
						currentValueKnown = true;
					}
					values.add(valueStrings[i]);
				}
			}
		}
		if ((valuesHelper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE) && (valuesHelper.getImpliedValue() != null)) {
			if (!values.contains(valuesHelper.getImpliedValue())) {
				values.add(valuesHelper.getImpliedValue());
			}
		}

		if (checkIfCurrentValueIsKnown && !currentValueKnown && (currentValue != null) && (currentValue.length() > 0)) {
			values.add(currentValue);
		}
		String[] validStrings = new String[values.size()];
		validStrings = (String[]) values.toArray(validStrings);
		return validStrings;
	}

	private IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName) {
		return createDefaultPropertyDescriptor(attributeName, false);
	}

	private IPropertyDescriptor createDefaultPropertyDescriptor(String attributeName, boolean hideOnFilter) {
		// The descriptor class used here is also used in
		// updatePropertyDescriptors()
		TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attributeName, attributeName);
		descriptor.setCategory(getCategory(null));
		descriptor.setDescription(attributeName);
		if (hideOnFilter && fSetExpertFilter) {
			descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
		}
		return descriptor;
	}

	/**
	 * Creates a property descriptor for an attribute with ENUMERATED values -
	 * if the value does not exist, an editable combo box is returned - if the
	 * value exists but is not one in the enumerated list of value, a combo
	 * box featuring the current and correct values is returned - if the value
	 * exists and it is a valid value, a combo box featuring the correct
	 * values with the current one visible is returned
	 */
	private IPropertyDescriptor createEnumeratedPropertyDescriptor(CMAttributeDeclaration attrDecl, CMDataType valuesHelper) {
		// the displayName MUST be set
		String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
		EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrName, attrName, _getValidStrings(attrDecl, valuesHelper));
		descriptor.setCategory(getCategory(attrDecl));
		descriptor.setDescription(attrName);
		if ((attrDecl.getUsage() != CMAttributeDeclaration.REQUIRED) && fSetExpertFilter) {
			descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
		}
		return descriptor;
	}

	/**
	 * Creates a property descriptor for an attribute with a FIXED value - if
	 * the value does not exist, an editable combo box is returned - if the
	 * value exists but is not the fixed/default value, a combo box featuring
	 * the current and correct value is returned - if the value exists and it
	 * is the fixed/default value, no cell editor is provided "locking" the
	 * value in
	 */
	private IPropertyDescriptor createFixedPropertyDescriptor(CMAttributeDeclaration attrDecl, CMDataType helper) {
		// the displayName MUST be set
		String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
		EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrName, attrName, _getValidFixedStrings(attrDecl, helper));
		descriptor.setCategory(getCategory(attrDecl));
		descriptor.setDescription(DOMNamespaceHelper.computeName(attrDecl, fNode, null));
		return descriptor;
	}

	protected IPropertyDescriptor createPropertyDescriptor(CMAttributeDeclaration attrDecl) {
		IPropertyDescriptor descriptor = null;
		CMDataType attrType = attrDecl.getAttrType();

		if (attrType != null) {
			// handle declarations that provide FIXED/ENUMERATED values
			if ((attrType.getEnumeratedValues() != null) && (attrType.getEnumeratedValues().length > 0)) {
				descriptor = createEnumeratedPropertyDescriptor(attrDecl, attrType);
			}
			else if (((attrDecl.getUsage() == CMAttributeDeclaration.FIXED) || (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED)) && (attrType.getImpliedValue() != null)) {
				descriptor = createFixedPropertyDescriptor(attrDecl, attrType);
			}
			else {
				// plain text
				descriptor = createTextPropertyDescriptor(attrDecl);
			}
		}
		else {
			// no extra information given
			descriptor = createTextPropertyDescriptor(attrDecl);
		}
		return descriptor;
	}

	/**
	 * Returns the current collection of property descriptors.
	 * 
	 * @return all valid descriptors.
	 */
	private IPropertyDescriptor[] createPropertyDescriptors() {
		CMNamedNodeMap attrMap = null;
		CMElementDeclaration ed = getDeclaration();
		if (ed != null) {
			attrMap = ed.getAttributes();
			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrMap);
			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
			for (int k = 0; k < nodes.size(); k++) {
				CMNode cmnode = (CMNode) nodes.get(k);
				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
					allAttributes.put(cmnode);
				}
			}
			attrMap = allAttributes;
		}

		List descriptorList = new ArrayList();
		List names = new ArrayList();
		IPropertyDescriptor descriptor;

		CMAttributeDeclaration attrDecl = null;

		// add descriptors for existing attributes
		NamedNodeMap attributes = fNode.getAttributes();
		if (attributes != null) {
			for (int i = 0; i < attributes.getLength(); i++) {
				Attr attr = (Attr) attributes.item(i);
				// if metainfo is present for this attribute, use the
				// CMAttributeDeclaration to derive a descriptor
				if (attrMap != null) {
					String attrName = attr.getName();
					if (fCaseSensitive) {
						attrDecl = (CMAttributeDeclaration) attrMap.getNamedItem(attrName);
					}
					else {
						attrDecl = null;
						for (int j = 0; j < attrMap.getLength(); j++) {
							if (!fCaseSensitive && attrMap.item(j).getNodeName().equalsIgnoreCase(attrName)) {
								attrDecl = (CMAttributeDeclaration) attrMap.item(j);
								break;
							}
						}
					}
				}
				// be consistent: if there's metainfo, use *that* as the
				// descriptor ID
				descriptor = null;
				if (attrDecl != null) {
					String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
					if (!names.contains(attrName)) {
						descriptor = createPropertyDescriptor(attrDecl);
						if (descriptor != null)
							names.add(attrName);
					}
				}
				else {
					if (!names.contains(attr.getName())) {
						descriptor = createDefaultPropertyDescriptor(attr.getName());
						if (descriptor != null)
							names.add(attr.getName());
					}
				}
				if (descriptor != null) {
					descriptorList.add(descriptor);
				}
			}
		}

		// add descriptors from the metainfo that are not yet listed
		if (attrMap != null) {
			for (int i = 0; i < attrMap.getLength(); i++) {
				attrDecl = (CMAttributeDeclaration) attrMap.item(i);
				String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
				if (!names.contains(attrName)) {
					IPropertyDescriptor holdDescriptor = createPropertyDescriptor(attrDecl);
					if (holdDescriptor != null) {
						names.add(attrName);
						descriptorList.add(holdDescriptor);
					}
				}
			}
		}

		// add MQE-based descriptors
		if (ed != null && fNode.getNodeType() == Node.ELEMENT_NODE) {
			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
			for (int i = 0; i < nodes.size(); i++) {
				CMNode node = (CMNode) nodes.get(i);
				if (node.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
					attrDecl = (CMAttributeDeclaration) node;
					String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
					if (!names.contains(attrName)) {
						IPropertyDescriptor holdDescriptor = createPropertyDescriptor(attrDecl);
						if (holdDescriptor != null) {
							names.add(attrName);
							descriptorList.add(holdDescriptor);
						}
					}
				}
			}
		}


		IPropertyDescriptor[] descriptors = new IPropertyDescriptor[descriptorList.size()];
		for (int i = 0; i < descriptors.length; i++) {
			descriptors[i] = (IPropertyDescriptor) descriptorList.get(i);
		}
		return descriptors;
	}

	private IPropertyDescriptor createTextPropertyDescriptor(CMAttributeDeclaration attrDecl) {
		String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
		TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attrName, attrName);
		descriptor.setCategory(getCategory(attrDecl));
		descriptor.setDescription(attrName);
		if ((attrDecl.getUsage() != CMAttributeDeclaration.REQUIRED) && fSetExpertFilter) {
			descriptor.setFilterFlags(new String[]{IPropertySheetEntry.FILTER_ID_EXPERT});
		}
		return descriptor;
	}

	private String getCategory(CMAttributeDeclaration attrDecl) {
		if (attrDecl != null) {
			if (attrDecl.supports("category")) { //$NON-NLS-1$
				return (String) attrDecl.getProperty("category"); //$NON-NLS-1$
			}
			if (fShouldDeriveCategories && (attrDecl.getAttrType() != null) && (attrDecl.getAttrType().getNodeName() != null) && (attrDecl.getAttrType().getNodeName().length() > 0)) {
				return attrDecl.getAttrType().getDataTypeName();
			}
		}
		return CATEGORY_ATTRIBUTES;
	}

	private CMElementDeclaration getDeclaration() {
		if ((fNode == null) || (fNode.getNodeType() != Node.ELEMENT_NODE)) {
			return null;
		}
		ModelQuery modelQuery = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument());
		if (modelQuery != null) {
			return modelQuery.getCMElementDeclaration((Element) fNode);
		}
		return null;
	}

	private Display getDisplay() {

		return PlatformUI.getWorkbench().getDisplay();
	}

	/**
	 * Returns a value for this Node that can be editted in a property sheet.
	 * 
	 * @return a value that can be editted
	 */
	public Object getEditableValue() {
		return null;
	}

	/**
	 * Returns the current collection of property descriptors.
	 * 
	 * @return all valid descriptors.
	 */
	public final IPropertyDescriptor[] getPropertyDescriptors() {
		if ((fDescriptors == null) || (fDescriptors.length == 0)) {
			fDescriptors = createPropertyDescriptors();
		}
		else {
			updatePropertyDescriptors();
		}
		return fDescriptors;
	}

	/**
	 * Returns the current value for the named property.
	 * 
	 */
	public Object getPropertyValue(Object nameObject) {
		String name = nameObject.toString();
		String returnedValue = null;
		NamedNodeMap attrMap = fNode.getAttributes();
		if (attrMap != null) {
			Node attribute = attrMap.getNamedItem(name);
			if (attribute != null) {
				if (attribute instanceof IDOMNode) {
					returnedValue = ((IDOMNode) attribute).getValueSource();
				}
				else {
					returnedValue = attribute.getNodeValue();
				}
			}
		}
		if (returnedValue == null) {
			returnedValue = ""; //$NON-NLS-1$
		}
		return returnedValue;
	}

	private String[] getValidValues(CMAttributeDeclaration attrDecl) {
		if (attrDecl == null) {
			return new String[0];
		}

		String[] validValues = null;
		CMDataType attrType = attrDecl.getAttrType();
		if (attrType != null) {
			validValues = _getValidStrings(attrDecl, attrType);
			if (fSortEnumeratedValues) {
				Arrays.sort(validValues);
			}
		}
		if (validValues == null) {
			validValues = new String[0];
		}
		return validValues;
	}

	public boolean isPropertyRemovable(Object id) {
		return true;
	}

	public boolean isPropertyResettable(Object id) {
		boolean resettable = false;
		String property = id.toString();
		CMNamedNodeMap attrDecls = null;

		CMElementDeclaration ed = getDeclaration();
		if (ed != null) {
			attrDecls = ed.getAttributes();
			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrDecls);
			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
			for (int k = 0; k < nodes.size(); k++) {
				CMNode cmnode = (CMNode) nodes.get(k);
				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
					allAttributes.put(cmnode);
				}
			}
			attrDecls = allAttributes;
		}

		if (attrDecls != null) {
			CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attrDecls.getNamedItem(property);
			if (attrDecl != null) {
				if (attrDecl.getAttrType() != null) {
					CMDataType helper = attrDecl.getAttrType();
					if ((helper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE) && (helper.getImpliedValue() != null)) {
						resettable = true;
					}
				}
			}
		}
		return resettable;
	}

	/**
	 * Returns whether the property value has changed from the default.
	 * 
	 * @return <code>true</code> if the value of the specified property has
	 *         changed from its original default value; <code>false</code>
	 *         otherwise.
	 */
	public boolean isPropertySet(Object propertyObject) {
		String property = propertyObject.toString();

		NamedNodeMap attrMap = fNode.getAttributes();
		if (attrMap != null) {
			return attrMap.getNamedItem(property) != null;
		}
		return false;
	}

	/**
	 * Remove the given attribute from the Node
	 * 
	 * @param propertyObject
	 */
	public void removeProperty(Object propertyObject) {
		NamedNodeMap attrMap = fNode.getAttributes();
		if (attrMap != null) {
			Node attribute = attrMap.getNamedItem(propertyObject.toString());
			if (attribute != null) {
				try {
					attrMap.removeNamedItem(propertyObject.toString());
				}
				catch (DOMException e) {
					if (e.code != DOMException.INVALID_MODIFICATION_ERR) {
						Logger.logException(e);
					}
				}
			}
		}
	}

	/**
	 * Resets the specified property's value to its default value.
	 * 
	 */
	public void resetPropertyValue(Object propertyObject) {
		String property = propertyObject.toString();
		CMNamedNodeMap attrDecls = null;

		CMElementDeclaration ed = getDeclaration();
		if (ed != null) {
			attrDecls = ed.getAttributes();
			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrDecls);
			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
			for (int k = 0; k < nodes.size(); k++) {
				CMNode cmnode = (CMNode) nodes.get(k);
				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
					allAttributes.put(cmnode);
				}
			}
			attrDecls = allAttributes;
		}

		NamedNodeMap attrMap = fNode.getAttributes();
		if (attrDecls != null) {
			CMAttributeDeclaration attrDecl = (CMAttributeDeclaration) attrDecls.getNamedItem(property);
			String defValue = null;
			if (attrDecl != null) {
				if (attrDecl.getAttrType() != null) {
					CMDataType helper = attrDecl.getAttrType();
					if ((helper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE) && (helper.getImpliedValue() != null)) {
						defValue = helper.getImpliedValue();
					}
				}
			}
			if ((defValue != null) && (defValue.length() > 0)) {
				((Attr) attrMap.getNamedItem(property)).setValue(defValue);
			}
			else {
				attrMap.removeNamedItem(property);
			}
		}
		else {
			attrMap.removeNamedItem(property);
		}
	}

	/**
	 * Sets the named property to the given value.
	 * 
	 */
	public void setPropertyValue(Object nameObject, Object value) {
		// Avoid cycling - can happen if a closing cell editor causes a
		// refresh
		// on the PropertySheet page and the setInput again asks the editor to
		// close; besides, why apply the same value twice?
		if (!fValuesBeingSet.isEmpty() && (fValuesBeingSet.peek() == nameObject)) {
			return;
		}
		fValuesBeingSet.push(nameObject);
		String name = nameObject.toString();
		String valueString = null;
		if (value != null) {
			valueString = value.toString();
		}
		NamedNodeMap attrMap = fNode.getAttributes();
		try {
			if (attrMap != null) {
				Attr attr = (Attr) attrMap.getNamedItem(name);
				if (attr != null) {
					// EXISTING VALUE
					// potential out of control loop if updating the value
					// triggers a viewer update, forcing the
					// active cell editor to save its value and causing the
					// loop to continue
					if ((attr.getValue() == null) || !attr.getValue().equals(valueString)) {
						if (attr instanceof IDOMNode) {
							((IDOMNode) attr).setValueSource(valueString);
						}
						else {
							attr.setValue(valueString);
						}
					}
				}
				else {
					// NEW(?) value
					if (value != null) { // never create an empty attribute
						Attr newAttr = fNode.getOwnerDocument().createAttribute(name);
						if (newAttr instanceof IDOMNode) {
							((IDOMNode) newAttr).setValueSource(valueString);
						}
						else {
							newAttr.setValue(valueString);
						}
						attrMap.setNamedItem(newAttr);
					}
				}
			}
			else {
				if (fNode instanceof Element) {
					((Element) fNode).setAttribute(name, valueString);
				}
			}
		}
		catch (DOMException e) {
			Display d = getDisplay();
			if (d != null) {
				d.beep();
			}
		}
		fValuesBeingSet.pop();
	}

	protected void updatePropertyDescriptors() {
		if ((fDescriptors == null) || (fDescriptors.length == 0)) {
			// Nothing to update
			return;
		}

		// List of all names encountered in the tag and defined by the element
		List declaredNames = new ArrayList();
		// New descriptor list that will become fDescriptors after all
		// processing is done
		List descriptors = new ArrayList();
		// Names of the descriptors in the above List
		List descriptorNames = new ArrayList();

		// Update any descriptors derived from the metainfo
		CMElementDeclaration ed = getDeclaration();
		CMNamedNodeMap attrMap = null;
		if (ed != null) {
			attrMap = ed.getAttributes();
			CMNamedNodeMapImpl allAttributes = new CMNamedNodeMapImpl(attrMap);
			List nodes = ModelQueryUtil.getModelQuery(fNode.getOwnerDocument()).getAvailableContent((Element) fNode, ed, ModelQuery.INCLUDE_ATTRIBUTES);
			for (int k = 0; k < nodes.size(); k++) {
				CMNode cmnode = (CMNode) nodes.get(k);
				if (cmnode.getNodeType() == CMNode.ATTRIBUTE_DECLARATION) {
					allAttributes.put(cmnode);
				}
			}
			attrMap = allAttributes;
		}
		// Update exiting descriptors; not added to the final list here
		if (attrMap != null) {
			// Update existing descriptor types based on metainfo
			CMAttributeDeclaration attrDecl = null;
			for (int i = 0; i < attrMap.getLength(); i++) {
				attrDecl = (CMAttributeDeclaration) attrMap.item(i);
				String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
				if (!declaredNames.contains(attrName)) {
					declaredNames.add(attrName);
				}
				for (int j = 0; j < fDescriptors.length; j++) {
					boolean sameName = (fCaseSensitive && fDescriptors[j].getId().equals(attrDecl.getNodeName())) || (!fCaseSensitive && attrDecl.getNodeName().equals(fDescriptors[j].getId().toString()));
					if (sameName) {
						String[] validValues = getValidValues(attrDecl);
						// Update the descriptor for this
						// CMAttributeDeclaration (only enumerated values get
						// updated for now)
						if (fDescriptors[j] instanceof EnumeratedStringPropertyDescriptor) {
							((EnumeratedStringPropertyDescriptor) fDescriptors[j]).updateValues(validValues);
						}
						// Replace with better descriptor
						else if ((validValues != null) && (validValues.length > 0)) {
							fDescriptors[j] = createPropertyDescriptor(attrDecl);
						}
					}
				}
			}
		}
		else {
			// Update existing descriptors based on not having any metainfo
			for (int j = 0; j < fDescriptors.length; j++) {
				// Replace with basic descriptor
				if (!(fDescriptors[j] instanceof TextPropertyDescriptor)) {
					fDescriptors[j] = createDefaultPropertyDescriptor((String) fDescriptors[j].getId());
				}
			}
		}

		NamedNodeMap attributes = fNode.getAttributes();

		// Remove descriptors for attributes that aren't present AND aren't
		// known through metainfo,
		// do this by only reusing existing descriptors for attributes that
		// are present or declared
		for (int i = 0; i < fDescriptors.length; i++) {
			if (fDescriptors[i] != null) {
				String descriptorName = fDescriptors[i].getId().toString();
				if ((declaredNames.contains(descriptorName) || (attributes.getNamedItem(descriptorName) != null)) && !descriptorNames.contains(descriptorName)) {
					descriptorNames.add(descriptorName);
					descriptors.add(fDescriptors[i]);
				}
			}
		}

		// Add descriptors for declared attributes that don't already have one
		if (attrMap != null) {
			// Update existing descriptor types based on metainfo
			CMAttributeDeclaration attrDecl = null;
			for (int i = 0; i < attrMap.getLength(); i++) {
				attrDecl = (CMAttributeDeclaration) attrMap.item(i);
				String attrName = DOMNamespaceHelper.computeName(attrDecl, fNode, null);
				if (fCaseSensitive) {
					if (!descriptorNames.contains(attrName)) {
						IPropertyDescriptor descriptor = createPropertyDescriptor(attrDecl);
						if (descriptor != null) {
							descriptorNames.add(attrName);
							descriptors.add(descriptor);
						}
					}
				}
				else {
					boolean exists = false;
					for (int j = 0; j < descriptorNames.size(); j++) {
						exists = (descriptorNames.get(j).toString().equalsIgnoreCase(attrName)) || exists;
					}
					if (!exists) {
						descriptorNames.add(attrName);
						IPropertyDescriptor descriptor = createPropertyDescriptor(attrDecl);
						if (descriptor != null) {
							descriptorNames.add(attrName);
							descriptors.add(descriptor);
						}
					}
				}
			}
		}

		// Add descriptors for existing attributes that don't already have one
		if (attributes != null) {
			for (int i = 0; i < attributes.getLength(); i++) {
				Attr attr = (Attr) attributes.item(i);
				String attrName = attr.getName();
				if (fCaseSensitive) {
					if (!descriptorNames.contains(attrName)) {
						descriptorNames.add(attrName);
						descriptors.add(createDefaultPropertyDescriptor(attrName));
					}
				}
				else {
					boolean exists = false;
					for (int j = 0; j < descriptorNames.size(); j++) {
						exists = (descriptorNames.get(j).toString().equalsIgnoreCase(attrName)) || exists;
					}
					if (!exists) {
						descriptorNames.add(attrName);
						descriptors.add(createDefaultPropertyDescriptor(attrName));
					}
				}
			}
		}

		// Update fDescriptors
		IPropertyDescriptor[] newDescriptors = new IPropertyDescriptor[descriptors.size()];
		for (int i = 0; i < newDescriptors.length; i++) {
			newDescriptors[i] = (IPropertyDescriptor) descriptors.get(i);
		}
		fDescriptors = newDescriptors;
	}
}
