/*******************************************************************************
 * Copyright (c) 2001, 2005 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.INodeAdapter;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.ui.internal.provisional.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.modelquery.ModelQuery;
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. Requires an adapter factory to create JFace
 * adapters for the nodes in the tree.
 */
public class XMLPropertySourceAdapter implements INodeAdapter, IPropertySource, IPropertySourceExtension, IPropertySource2 {
	protected final static String CATEGORY_ATTRIBUTES = XMLUIMessages.XMLPropertySourceAdapter_0; //$NON-NLS-1$

	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;
	private boolean fCaseSensitive = true;
	private IPropertyDescriptor[] fDescriptors = null;
	private Node fNode = null;

	private Stack fValuesBeingSet = new Stack();

	public XMLPropertySourceAdapter(INodeNotifier target) {
		super();
		fNode = (Node) target;
		if (fNode instanceof IDOMNode) {
			Document ownerDocument = fNode.getOwnerDocument();
			if (ownerDocument == null) {
				// if ownerDocument is null, then it must be the Document Node
				ownerDocument = (Document) fNode;
			}
			DocumentTypeAdapter adapter = (DocumentTypeAdapter) ((INodeNotifier) ownerDocument).getAdapterFor(DocumentTypeAdapter.class);
			if (adapter != null)
				fCaseSensitive = adapter.getTagNameCase() == DocumentTypeAdapter.STRICT_CASE;
		}
	}

	private String[] _getValidFixedStrings(CMAttributeDeclaration attrDecl, CMDataType helper) {
		String attributeName = attrDecl.getAttrName();
		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 = attrDecl.getAttrName();
		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
		EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrDecl.getAttrName(), attrDecl.getAttrName(), _getValidStrings(attrDecl, valuesHelper));
		descriptor.setCategory(getCategory(attrDecl));
		descriptor.setDescription(attrDecl.getAttrName());
		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
		EnumeratedStringPropertyDescriptor descriptor = new EnumeratedStringPropertyDescriptor(attrDecl.getNodeName(), attrDecl.getNodeName(), _getValidFixedStrings(attrDecl, helper));
		descriptor.setCategory(getCategory(attrDecl));
		descriptor.setDescription(attrDecl.getAttrName());
		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();
		}

		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
				if (attrDecl != null) {
					descriptor = createPropertyDescriptor(attrDecl);
					if (descriptor != null)
						names.add(attrDecl.getNodeName());
				}
				else {
					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);
				if (!names.contains(attrDecl.getAttrName())) {
					IPropertyDescriptor holdDescriptor = createPropertyDescriptor(attrDecl);
					if (holdDescriptor != null) {
						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) {
		TextPropertyDescriptor descriptor = new TextPropertyDescriptor(attrDecl.getAttrName(), attrDecl.getAttrName());
		descriptor.setCategory(getCategory(attrDecl));
		descriptor.setDescription(attrDecl.getAttrName());
		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 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;
	}

	/**
	 * Allowing the INodeAdapter to compare itself against the type allows it
	 * to return true in more than one case.
	 */
	public boolean isAdapterForType(Object type) {
		return type == IPropertySource.class;
	}

	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();
		}

		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;
	}

	public void notifyChanged(INodeNotifier notifier, int eventType, java.lang.Object changedFeature, java.lang.Object oldValue, java.lang.Object newValue, int pos) {
	}

	/**
	 * 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();
		}

		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();
		}
		// 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 = attrDecl.getAttrName();
				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 = attrDecl.getAttrName();
				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;
	}
}
