/*******************************************************************************
 * Copyright (c) 2001, 2004 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.reconcile;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.reconciler.IReconcileResult;
import org.eclipse.wst.common.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.common.contentmodel.CMDocument;
import org.eclipse.wst.common.contentmodel.CMElementDeclaration;
import org.eclipse.wst.common.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.common.contentmodel.CMNode;
import org.eclipse.wst.common.contentmodel.modelquery.CMDocumentManager;
import org.eclipse.wst.common.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.common.contentmodel.util.CMDocumentCache;
import org.eclipse.wst.common.contentmodel.util.CMDocumentCacheListener;
import org.eclipse.wst.sse.core.INodeNotifier;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.text.ITextRegion;
import org.eclipse.wst.sse.ui.IReleasable;
import org.eclipse.wst.sse.ui.StructuredTextReconciler;
import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
import org.eclipse.wst.sse.ui.internal.reconcile.ReconcileAnnotationKey;
import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
import org.eclipse.wst.xml.core.document.XMLAttr;
import org.eclipse.wst.xml.core.document.XMLElement;
import org.eclipse.wst.xml.core.document.XMLNode;
import org.eclipse.wst.xml.core.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.parser.XMLRegionContext;
import org.eclipse.wst.xml.ui.internal.Logger;
import org.eclipse.wst.xml.ui.internal.correction.ProblemIDsXML;
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;

/**
 * @deprecated moving toward reconcileValidator extension point
 */
public class ReconcileStepAdapterForXML extends AbstractReconcileStepAdapter implements CMDocumentCacheListener, IReleasable {

	/**
	 * Record of notification sent to this adapter. Will be queued up so
	 * they're not dealt with until reconciling is actually called from the
	 * reconciler thread.
	 */
	public class NotificationEvent {

		public Object changedFeature;

		public int eventType;

		public Object newValue;

		public INodeNotifier notifier;

		public Object oldValue;

		public int pos;

		public NotificationEvent(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {

			this.notifier = notifier;
			this.eventType = eventType;
			this.changedFeature = changedFeature;
			this.oldValue = oldValue;
			this.newValue = newValue;
			this.pos = pos;
		}

		// used (to see if notifications vector "contains()")
		// so we don't queue up "duplicate" events,
		// (indicates same eventType, notifier, and changedFeature)
		public boolean equals(Object o) {

			boolean result = false;
			if (o instanceof NotificationEvent) {
				NotificationEvent e2 = (NotificationEvent) o;
				if (this.notifier == null || e2.notifier == null || this.changedFeature == null || e2.changedFeature == null) {
					result = false;
				}
				result = (this.eventType == e2.eventType && this.notifier == e2.notifier && this.changedFeature == e2.changedFeature);
			}
			return result;
		}
	}

	protected boolean fCaseSensitive = true;
	protected CMDocumentCache fCMDocumentCache;
	protected DocumentType fDocumentTypeForRefresh;

	protected boolean fNeedsRefreshAll = false;

	// required for thread safety
	protected List fNotifications = new Vector();

	// these are used in conjunction w/ cacheUpdated() notification
	// in order to refresh the whole document
	protected IProgressMonitor fProgressMonitorForRefresh;

	// counter used for repeated reconcile opreations
	// to yield the thread control to the next thread
	// to improve workbench performance
	protected short fReconcileCount = 0;

	// will not attempt to validate attribute names starting with the
	// following:
	protected String[] ignoreAttributeNamesStartingWith = new String[]{"xmlns", "xsi:", "xml:"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

	// changing these elements may have an impact on the current content model
	// (which suggests to mark everything dirty)
	protected String[] mayImpactContentModel = new String[]{"DOCTYPE", "xmlns", "xsi", "xmlns:xsi", "xmlns:xsl", "xsi:schemaLocation", "taglib"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
	protected String SEVERITY_MISSING_REQUIRED_ATTR = TemporaryAnnotation.ANNOT_WARNING;

	// severities for the problems discoverable by this reconciler; possibly
	// user configurable later
	protected String SEVERITY_STRUCTURE = TemporaryAnnotation.ANNOT_ERROR;
	protected String SEVERITY_UNKNOWN_ATTR = TemporaryAnnotation.ANNOT_ERROR;
	protected String SEVERITY_UNKNOWN_ELEMENT = TemporaryAnnotation.ANNOT_ERROR;

	public ReconcileStepAdapterForXML() {

		super();
	}

	public void cacheCleared(CMDocumentCache arg0) {
		// do nothing
	}

	public void cacheUpdated(CMDocumentCache arg0, String arg1, int arg2, int arg3, CMDocument arg4) {

		// revalidate all
		if (Logger.isTracing(StructuredTextReconciler.TRACE_FILTER)) {
			String message = "[trace reconciler] >  \r\n====================" + "\n cache updated:" + "\n arg0 :" + arg0 + "\n arg1 :" + arg1 + "\n arg3 :" + arg3 + "\n arg4 :" + arg4; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
			Logger.trace(StructuredTextReconciler.TRACE_FILTER, message);
		}
		if (arg3 == CMDocumentCache.STATUS_LOADED) {
			Logger.trace(StructuredTextReconciler.TRACE_FILTER, "CMDocument finished loading :" + arg1); //$NON-NLS-1$
			doRefreshAll((INodeNotifier) fDocumentTypeForRefresh, fProgressMonitorForRefresh);
		}
	}

	protected IReconcileResult[] doRefreshAll(INodeNotifier notifier, IProgressMonitor monitor) {

		Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] > refreshing all"); //$NON-NLS-1$

		synchronized (fDirtyElements) {
			fDirtyElements.clear();
		}
		Document doc = (((Node) notifier).getNodeType() != Node.DOCUMENT_NODE) ? ((Node) notifier).getOwnerDocument() : (Document) notifier;
		return reconcileSubtree((INodeNotifier) doc, monitor);
	}

	protected ModelQuery getModelQuery(Node node) {

		return (node.getNodeType() == Node.DOCUMENT_NODE) ? ModelQueryUtil.getModelQuery((Document) node) : ModelQueryUtil.getModelQuery(node.getOwnerDocument());
	}

	/**
	 * returns a list of required CMAttributeDeclarations for the given
	 * element.
	 * 
	 * @param elementDecl
	 * 
	 */
	protected List getRequiredAttributes(CMElementDeclaration elementDecl) {

		CMNamedNodeMap attrMap = elementDecl.getAttributes();
		Iterator it = attrMap.iterator();
		CMAttributeDeclaration attr = null;
		List result = new ArrayList();
		while (it.hasNext()) {
			attr = (CMAttributeDeclaration) it.next();
			if (attr.getUsage() == CMAttributeDeclaration.REQUIRED) {
				result.add(attr);
			}
		}
		return result;
	}

	/**
	 * Determine if this Document is an XML/XHTML Document and whether to be
	 * case sensitive
	 */
	protected boolean isCaseSensitive(Node node) {

		return true;
	}

	// CMVC 254838
	/**
	 * Indicates if the element is not in the ContentModel (if it's not in the
	 * ContentModel, but its parent is)
	 * 
	 * @param element
	 * @param modelQuery
	 * @return whether or not the element is unknown according to its
	 *         associated ContentModel.
	 */
	protected boolean isUnknown(Element element, ModelQuery modelQuery) {

		boolean result = false;
		CMElementDeclaration ed = modelQuery.getCMElementDeclaration(element);
		if (ed == null) {
			// make sure parent declaration exists, and is not inferred
			Node parentNode = element.getParentNode();
			if (parentNode != null && parentNode.getNodeType() == Node.ELEMENT_NODE) {
				CMElementDeclaration parentEd = modelQuery.getCMElementDeclaration((Element) parentNode);
				// 2/19/04 porting iFix for lax schema suppport
				result = (parentEd != null) && !Boolean.TRUE.equals(parentEd.getProperty("isInferred")) //$NON-NLS-1$
							&& !Boolean.TRUE.equals(parentEd.getProperty("isLax")); //$NON-NLS-1$
			}
			// need one error for the root at least
			// to indicate the document is wrong...
			Document ownerDoc = element.getOwnerDocument();
			if (ownerDoc != null && ownerDoc.getDocumentElement() == element) {
				CMDocument cmDoc = modelQuery.getCorrespondingCMDocument(ownerDoc);
				result = (cmDoc != null && cmDoc.getElements().getLength() > 0);
			}
		} else {
			if (ed.getProperty("isInferred") != null && Boolean.TRUE.equals(ed.getProperty("isInferred")) //$NON-NLS-1$ //$NON-NLS-2$
						|| (ed.getProperty("partialContentModel") != null && Boolean.TRUE.equals(ed.getProperty("partialContentModel")))) { //$NON-NLS-1$ //$NON-NLS-2$
				result = false;
			}
		}
		return result;
	}

	/**
	 * Checks if name matches any mayImpactContentModel[] strings
	 * 
	 * @param name
	 * @return if a match is found, return true, else return false
	 */
	private boolean mayAffectContentModel(String name) {

		// TODO (pa) may need to be smarter if the attribute name is broken...
		StringTokenizer st = new StringTokenizer(name, ":", false); //$NON-NLS-1$
		String prefix = ""; //$NON-NLS-1$
		if (st.hasMoreTokens())
			prefix = st.nextToken();
		for (int i = 0; i < mayImpactContentModel.length; i++) {
			if (mayImpactContentModel[i].indexOf(name) != -1 || mayImpactContentModel[i].startsWith(prefix))
				return true;
		}
		return false;
	}

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

		synchronized (fNotifications) {
			NotificationEvent newEvent = new NotificationEvent(notifier, eventType, changedFeature, oldValue, newValue, pos);
			if (!fNotifications.contains(newEvent))
				fNotifications.add(newEvent);
		}
	}


	public void processNotification(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos, IProgressMonitor monitor) {

		if (isCanceled(monitor))
			return;

		// (nsd) pa_TODO: we need to mark more or widen the scope affected by
		// the next reconcile() call
		// TODO: Handle multi-Node changes from Doctype Declarations, Taglib
		// directives,
		// and schema and namespace related attributes (DOCTYPE, taglib,
		// xmlns,
		// xsi...)
		// ** we currently don't get a notify on changed taglib...

		// we're going to validate everything again anyways after
		// proccessNotifications() has completed (in reconcile():
		// processNotifications() > refreshAll()),
		// no sense to do it here if we refreshingAll
		if (fNeedsRefreshAll)
			return;
		if (eventType == INodeNotifier.CHANGE || eventType == INodeNotifier.REMOVE) {
			if (changedFeature instanceof Node && ((Node) changedFeature).getNodeType() == Node.ATTRIBUTE_NODE) {
				if (mayAffectContentModel(((Node) changedFeature).getNodeName())) {
					fNeedsRefreshAll = true;
				}
			} else if (changedFeature instanceof Node && ((Node) changedFeature).getNodeType() == Node.DOCUMENT_TYPE_NODE) {
				fNeedsRefreshAll = true;
			} else if (notifier instanceof Node && ((Node) notifier).getNodeType() == Node.DOCUMENT_TYPE_NODE) {
				fNeedsRefreshAll = true;
			} else {
				// pa_TODO need to handle taglib definition changes...
				// if(mayAffectContentModel(((Node)changedFeature).getNodeName()))
				// {
				// System.out.println("dunno what changed > " +
				// changedFeature);
				// fNeedsRefreshAll = true;
				// }
			}
			if (isCanceled(monitor))
				return;
			fNeedsRefreshAll = true;
		}
		if (eventType == INodeNotifier.CHANGE && changedFeature instanceof Element) {
			markForReconciling(changedFeature);
		} else if (eventType == INodeNotifier.ADD && newValue instanceof Node) {
			Node newNode = (Node) newValue;
			if (newNode.getNodeType() == Node.DOCUMENT_TYPE_NODE || newNode.getNodeName().equals("jsp:directive.taglib")) { // $NON-NLS-1$
				// //$NON-NLS-1$
				fNeedsRefreshAll = true;
			} else {
				markForReconciling(newNode);
			}
		}
		markForReconciling(notifier);
	}

	protected void processNotifications(IProgressMonitor monitor) {

		fProgressMonitorForRefresh = monitor;
		NotificationEvent[] events = null;
		synchronized (fNotifications) {
			if (fNotifications.isEmpty()) {
				return;
			}
			events = (NotificationEvent[]) fNotifications.toArray(new NotificationEvent[0]);
			fNotifications.clear();
		}
		for (int i = 0; i < events.length; i++) {
			processNotification(events[i].notifier, events[i].eventType, events[i].changedFeature, events[i].oldValue, events[i].newValue, events[i].pos, monitor);
		}
	}


	public IReconcileResult[] reconcile(IProgressMonitor monitor, XMLNode xmlNode) {

		processNotifications(monitor);
		IReconcileResult[] results = EMPTY_RECONCILE_RESULT_SET;
		if (fNeedsRefreshAll) {
			results = doRefreshAll(xmlNode, monitor);
			fNeedsRefreshAll = false;
		} else {
			results = super.reconcile(monitor, xmlNode);
		}
		return results;
	}

	/**
	 * Called by super.reconcile(IAnnotationModel) on each Notifier
	 * 
	 */
	protected IReconcileResult[] reconcile(Object o, IProgressMonitor monitor) {

		super.reconcile(o, monitor);
		ModelQuery mq = null;
		if (o instanceof XMLNode) {
			XMLNode xmlNode = (XMLNode) o;
			mq = getModelQuery(xmlNode);
			if (mq != null) {
				fCaseSensitive = isCaseSensitive(xmlNode);
				return validate(mq, xmlNode);
			}
		}

		// if we are in a large reconciling loop (like when reconciling the
		// entire doc), this ensures
		// that other Threads have a chance to run.
		yieldIfNeeded();
		return EMPTY_RECONCILE_RESULT_SET;
	}

	/**
	 * Reconcile the Node and all children of the Notifier passed in.
	 * 
	 * @param notifier
	 * @param monitor
	 */
	protected IReconcileResult[] reconcileSubtree(INodeNotifier notifier, IProgressMonitor monitor) {

		IReconcileResult[] temp = EMPTY_RECONCILE_RESULT_SET;
		List results = new ArrayList();
		if (!isCanceled(monitor)) {
			if (notifier != null && notifier instanceof XMLNode) {
				XMLNode current = (XMLNode) notifier;
				// loop siblings
				while (current != null) {
					// mark whatever type nodes we wanna make dirty
					if (current.getNodeType() == Node.ELEMENT_NODE || current.getNodeType() == Node.DOCUMENT_TYPE_NODE || current.getNodeType() == Node.DOCUMENT_NODE || current.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
						temp = reconcile(current, monitor);
						for (int i = 0; i < temp.length; i++)
							results.add(temp[i]);
					}
					// drop one level deeper if necessary
					if (current.getFirstChild() != null) {
						temp = reconcileSubtree((INodeNotifier) current.getFirstChild(), monitor);
						for (int i = 0; i < temp.length; i++)
							results.add(temp[i]);
					}
					current = (XMLNode) current.getNextSibling();
				}
			}
			temp = new IReconcileResult[results.size()];
			System.arraycopy(results.toArray(), 0, temp, 0, results.size());
		}
		return temp;
	}

	/**
	 * Called from the ReconcileAdapterFactory
	 * 
	 */
	public void release() {

		if (fCMDocumentCache != null) {
			fCMDocumentCache.removeListener(this);
			fCMDocumentCache = null;
		}
	}

	/**
	 * Determines whether the given Attr should not be validated according to
	 * the ignoreAttributeNamesStartingWith array
	 * 
	 * @param attr
	 */
	protected boolean shouldIgnore(Attr attr) {

		boolean result = false;
		String name = attr.getNodeName();
		for (int i = 0; i < ignoreAttributeNamesStartingWith.length; i++) {
			if (fCaseSensitive) {
				if (name.startsWith(ignoreAttributeNamesStartingWith[i]))
					result = true;
			} else {
				try {
					if (name.length() >= ignoreAttributeNamesStartingWith[i].length() && ignoreAttributeNamesStartingWith[i].equalsIgnoreCase(name.substring(0, ignoreAttributeNamesStartingWith[i].length())))
						result = true;
				} catch (StringIndexOutOfBoundsException e) {
					result = true;
				}
			}
		}
		return result;
	}

	private void updateCMDocumentCache(ModelQuery mq, XMLNode xmlNode) {

		if (mq != null) {
			CMDocumentManager cmDocManager = mq.getCMDocumentManager();
			if (cmDocManager != null) {
				CMDocumentCache newCache = cmDocManager.getCMDocumentCache();
				if (newCache != null) {
					if (fCMDocumentCache == null) {
						// create fCMDocCache if necessary
						fCMDocumentCache = newCache;
						fCMDocumentCache.addListener(this);
						fDocumentTypeForRefresh = (DocumentType) xmlNode;
					} else if (fCMDocumentCache != newCache) {
						fCMDocumentCache.removeListener(this);
						fCMDocumentCache = newCache;
						fCMDocumentCache.addListener(this);
						fDocumentTypeForRefresh = (DocumentType) xmlNode;
					}
				}
			}
		}
	}

	/**
	 * Called by reconcile(IAnnotationModel, Object) when the Object is a
	 * Notifier
	 * 
	 */
	protected IReconcileResult[] validate(ModelQuery mq, XMLNode xmlNode) {

		List results = new ArrayList();
		if (xmlNode == null || !(xmlNode.getNodeType() == Node.ELEMENT_NODE || xmlNode.getNodeType() == Node.DOCUMENT_TYPE_NODE))
			return EMPTY_RECONCILE_RESULT_SET;
		// return early if the Node has gone stale
		if (xmlNode.getParentNode() == null || xmlNode.getOwnerDocument() == null) {
			return EMPTY_RECONCILE_RESULT_SET;
		}
		if (xmlNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
			// sets CMDocumentCacheListener (this)
			updateCMDocumentCache(mq, xmlNode);
		}
		CMDocument doc = mq.getCorrespondingCMDocument(xmlNode.getOwnerDocument());
		// looks like this is a bad check to do... I thought we took it out
		// before
		// if(doc == null)
		// return EMPTY_RECONCILE_RESULT_SET;
		if (doc != null && doc.getElements().getLength() == 0) {
			// an empty document
			return EMPTY_RECONCILE_RESULT_SET;
		}
		// continue on null or FALSE; inferred grammars aren't predefined so
		// there's no point in continuing
		if (doc != null && doc.getProperty("isInferred") != null && Boolean.TRUE.equals(doc.getProperty("isInferred"))) { //$NON-NLS-1$ //$NON-NLS-2$
			return EMPTY_RECONCILE_RESULT_SET;
		}

		// if xmlNode is DOCTYPE, skip to the first element
		// if there are no elements, return (don't validate)
		XMLNode elementNode = xmlNode;
		if (xmlNode.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
			boolean elementFound = false;
			while ((elementNode = (XMLNode) elementNode.getNextSibling()) != null) {
				if (elementNode.getNodeType() == Node.ELEMENT_NODE) {
					elementFound = true;
					break;
				}
			}
			if (!elementFound)
				return EMPTY_RECONCILE_RESULT_SET;
		}
		XMLElement element = (XMLElement) elementNode;
		// boolean needsEndTag = true;

		// test for a known element, if it's known, continue validating it
		CMElementDeclaration elementDecl = mq.getCMElementDeclaration(element);
		if (elementDecl != null) {
			// needsEndTag = needsEndTag(elementNode, elementDecl);
			NamedNodeMap attrs = element.getAttributes();
			List reqAttrList = getRequiredAttributes(elementDecl);
			for (int i = 0; i < attrs.getLength(); i++) {
				XMLAttr attr = (XMLAttr) attrs.item(i);
				if (!shouldIgnore(attr)) {

					// iFix V511i
					// CMVC 272647, attributes with namespace prefix get
					// marked
					// as error (even though they aren't)
					// CMNode attrDecl =
					// elementDecl.getAttributes().getNamedItem(attr.getNodeName());
					CMNode attrDecl = elementDecl.getAttributes().getNamedItem(attr.getLocalName());

					// test for a known attribute
					if (attrDecl != null) {
						// test for a known value (if there is an enumerated
						// list of them)
						String[] values = mq.getPossibleDataTypeValues(element, attrDecl);
						String currentValue = attr.getValue();
						boolean found = valueMatch(values, currentValue);
						if (!found) {
							int start = attr.getValueRegionStartOffset();
							int length = attr.getValueRegion().getTextLength();
							Object[] args = {currentValue.trim()};
							String message = SSEUIPlugin.getResourceString("%Invalid_value_{0}", args);
							Position p = new Position(start, length);
							ReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), ReconcileAnnotationKey.PARTIAL);
							results.add(new TemporaryAnnotation(p, SEVERITY_UNKNOWN_ATTR, message, key));
						}
						// remove from known required attribute list
						reqAttrList.remove(attrDecl);
					} else {
						Object[] args = {attr.getName()};
						String message = SSEUIPlugin.getResourceString("%Unknown_attribute_{0}", args);
						int start = attr.getNameRegionStartOffset();
						int length = attr.getNameRegion().getTextLength();
						Position p = new Position(start, length);
						ReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), ReconcileAnnotationKey.PARTIAL);
						results.add(new TemporaryAnnotation(p, SEVERITY_UNKNOWN_ATTR, message, key, ProblemIDsXML.UnknownAttr));
					}
				} else {
					// remove so we don't flag "ignored" attributes as missing
					reqAttrList.remove(elementDecl.getAttributes().getNamedItem(attr.getNodeName()));
				}
			}
			// if there are missing required attributes, create annotations
			// for
			// them
			if (reqAttrList != null && !reqAttrList.isEmpty()) {
				Iterator it = reqAttrList.iterator();
				int start = 0;
				int length = 1;
				CMAttributeDeclaration attr = null;
				while (it.hasNext()) {
					attr = (CMAttributeDeclaration) it.next();
					// sometimes getFirstStructuredDocumentRegion can return
					// null, this is a safety
					start = (element.getFirstStructuredDocumentRegion() != null) ? element.getFirstStructuredDocumentRegion().getStartOffset() : element.getStartOffset();
					length = (element.getFirstStructuredDocumentRegion() != null) ? element.getFirstStructuredDocumentRegion().getLength() : 1;

					Object[] args = {attr.getAttrName()};
					String message = SSEUIPlugin.getResourceString("%Missing_required_attribute_{0}", args);

					Position p = new Position(start, length);
					ReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), ReconcileAnnotationKey.PARTIAL);
					TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_MISSING_REQUIRED_ATTR, message, key, ProblemIDsXML.MissingRequiredAttr);

					IStructuredDocumentRegion startStructuredDocumentRegion = element.getStartStructuredDocumentRegion();
					if (startStructuredDocumentRegion != null) {
						String requiredAttrName = attr.getAttrName();
						String defaultAttrValue = attr.getDefaultValue();
						String insertString;
						if (defaultAttrValue == null)
							insertString = requiredAttrName + "=\"" + requiredAttrName + "\""; //$NON-NLS-1$ //$NON-NLS-2$
						else
							insertString = requiredAttrName + "=\"" + defaultAttrValue + "\""; //$NON-NLS-1$ //$NON-NLS-2$

						ITextRegion lastRegion = startStructuredDocumentRegion.getLastRegion();
						int insertOffset = lastRegion.getEnd();
						if (lastRegion.getEnd() == lastRegion.getTextEnd())
							insertString = " " + insertString; //$NON-NLS-1$
						if (lastRegion.getType() == XMLRegionContext.XML_TAG_CLOSE)
							insertOffset = lastRegion.getStart();
						Object[] additionalFixInfo = {insertString, new Integer(insertOffset)};
						annotation.setAdditionalFixInfo(additionalFixInfo);
						results.add(annotation);
					}
				}
			}
		} else if (isUnknown(element, mq)) { // CMVC 254838
			int start = element.getStartOffset();
			int length = element.getEndOffset() - element.getStartOffset();
			if (element.getStartStructuredDocumentRegion() != null && element.getStartStructuredDocumentRegion().getNumberOfRegions() > 1) {
				ITextRegion name = element.getStartStructuredDocumentRegion().getRegions().get(1);
				start = element.getStartStructuredDocumentRegion().getStartOffset(name);
				length = name.getTextLength();
			}
			Object[] args = {element.getNodeName()};
			String message = SSEUIPlugin.getResourceString("%Unknown_element_{0}", args);
			Position p = new Position(start, length);
			ReconcileAnnotationKey key = createKey(elementNode.getFirstStructuredDocumentRegion(), ReconcileAnnotationKey.PARTIAL);
			TemporaryAnnotation annotation = new TemporaryAnnotation(p, SEVERITY_UNKNOWN_ELEMENT, message, key, ProblemIDsXML.UnknownElement);

			// quick fix info
			int startTagOffset = -1, startTagLength = -1, endTagOffset = -1, endTagLength = -1;
			if (element.getStartStructuredDocumentRegion() != null) {
				startTagOffset = element.getStartStructuredDocumentRegion().getStartOffset();
				startTagLength = element.getStartStructuredDocumentRegion().getLength();
			}
			if (element.getEndStructuredDocumentRegion() != null) {
				endTagOffset = element.getEndStructuredDocumentRegion().getStartOffset();
				endTagLength = element.getEndStructuredDocumentRegion().getLength();
			}
			Object[] additionalFixInfo = {new Integer(startTagOffset), new Integer(startTagLength), new Integer(endTagOffset), new Integer(endTagLength)};

			annotation.setAdditionalFixInfo(additionalFixInfo);
			results.add(annotation);
		}
		IReconcileResult[] reconcileResults = new IReconcileResult[results.size()];
		System.arraycopy(results.toArray(), 0, reconcileResults, 0, results.size());
		return reconcileResults;
	}

	/**
	 * Determines if String value is within the values array given the current
	 * case sensitivity
	 * 
	 * @param values
	 * @param value
	 */
	protected boolean valueMatch(String[] values, String value) {

		boolean found = (values == null || values.length == 0 || value.length() == 0);
		for (int j = 0; j < values.length && !found; j++) {
			if (fCaseSensitive) {
				if (values[j].equals(value))
					found = true;
			} else if (values[j].equalsIgnoreCase(value))
				found = true;
		}
		return found;
	}

	// CMVC 255301
	// If we are in a large reconciling loop, this ensures
	// that other Threads have a chance to run.
	protected void yieldIfNeeded() {

		// 100 is arbitrary, may need a better number
		if (fReconcileCount >= 100) {
			Thread.yield();
			fReconcileCount = 0;
		} else {
			fReconcileCount++;
		}
	}
}
