/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.compare.examples.xml;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import java.text.MessageFormat;

import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.LocatorImpl;

import org.eclipse.core.runtime.CoreException;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;

import org.eclipse.compare.IEditableContent;
import org.eclipse.compare.IEncodedStreamContentAccessor;
import org.eclipse.compare.IStreamContentAccessor;
import org.eclipse.compare.structuremergeviewer.Differencer;
import org.eclipse.compare.structuremergeviewer.IDiffContainer;
import org.eclipse.compare.structuremergeviewer.IStructureComparator;
import org.eclipse.compare.structuremergeviewer.IStructureCreator;

/**
 * This structure analyzer builds a parse tree of an XML document found in a
 * <code>IByteContentAccessor</code> input by calling getStructure(Object)
 */
public class XMLStructureCreator implements IStructureCreator {

	protected static final boolean DEBUG_MODE= false;
	
	public static final String DEFAULT_NAME= XMLCompareMessages.XMLStructureCreator_pluginname; 

	public static final String USE_UNORDERED= XMLCompareMessages.XMLStructureCreator_unordered; 
	public static final String USE_ORDERED= XMLCompareMessages.XMLStructureCreator_ordered; 
	public static final String DEFAULT_IDMAP= USE_ORDERED;

	public static final String TYPE_ELEMENT= "element"; //$NON-NLS-1$
	public static final String TYPE_TEXT= "text"; //$NON-NLS-1$
	public static final String TYPE_ATTRIBUTE= "attribute"; //$NON-NLS-1$

	// for signatures
	public static final String ROOT_ID= "root"; //$NON-NLS-1$
	public static final char SIGN_SEPARATOR= '>';//'.'
	public static final char SIGN_ENCLOSING= '$';
	public static final String SIGN_ELEMENT= SIGN_ENCLOSING + TYPE_ELEMENT + SIGN_ENCLOSING;
	public static final String SIGN_TEXT= SIGN_ENCLOSING + TYPE_TEXT + SIGN_ENCLOSING;
	public static final String SIGN_ATTRIBUTE= SIGN_ENCLOSING + TYPE_ATTRIBUTE + SIGN_ENCLOSING;
	
	public static final String IDMAP_UNORDERED= XMLCompareMessages.XMLStructureCreator_idmap_unordered; 
	public static final char ID_SEPARATOR= '<';
	public static final char ID_TYPE_BODY= '<';

	private XMLNode fcurrentParent;
	private String fsignature;
	private Document fdoc;
	private boolean ignoreBodies= false;
	private HashMap fIdMapsInternal;
	private HashMap fIdMaps;
	private HashMap fIdExtensionToName;
	private HashMap fOrderedElementsInternal;
	private HashMap fOrderedElements;
	private HashMap idMap;
	private ArrayList fOrdered;
	private String fIdMapToUse;
	private boolean fUseIdMap;
	private String fFileExt;
	private boolean fFirstCall= true;
	private boolean fRemoveWhiteSpace;

	protected class XMLHandler extends DefaultHandler {

		protected Locator prevlocator; //previous locator
		protected Locator locator; //current locator

		@Override
		public void setDocumentLocator(Locator locator0) {
			this.locator= locator0;
		}

		// DocumentHandler methods
		
		/* Processing instruction. */
		@Override
		public void processingInstruction(String target, String data) {

			//    	System.out.println("target: " + target);
			//    	System.out.println("data: " + data);
			//        System.out.print("<?");
			//        System.out.print(target);
			//        if (data != null && data.length() > 0) {
			//            System.out.print(' ');
			//            System.out.print(data);
			//        }
			//        System.out.print("?>");
			//        System.out.flush();
			prevlocator= new LocatorImpl(locator);
		}

		/** Start document. */
		@Override
		public void startDocument() {
			prevlocator= new LocatorImpl(locator);
		}

		/* Start element. */
		@Override
		public void startElement(String uri, String local, String raw, Attributes attrs) {
			XMLNode currentElement;

			/* add root node for this element */

			if (XMLStructureCreator.DEBUG_MODE) {
				if (locator != null && prevlocator != null) {
					System.out.println("prevlocator: line " + prevlocator.getLineNumber() + "  column " + prevlocator.getColumnNumber() + "  id " + prevlocator.getPublicId()); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
					System.out.println("locator: line " + locator.getLineNumber() + "  column " + locator.getColumnNumber() + "  id " + locator.getPublicId()); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
				}
			}

			try {
				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("Node where children field accessed: " + fcurrentParent.getId()); //$NON-NLS-1$
				XMLChildren currentParent= (XMLChildren) fcurrentParent;
				currentParent.children++;
				String elementId;
				String elementName;
				IRegion r= fdoc.getLineInformation(prevlocator.getLineNumber() - 1);

				String parentSig= fsignature;
				fsignature= fsignature + raw + SIGN_SEPARATOR;

				if (isUseIdMap() && idMap.containsKey(fsignature)) {
					String attrName= (String) idMap.get(fsignature);
					elementId= raw + Character.valueOf(ID_SEPARATOR) + attrs.getValue(attrName);
					elementName= raw + " [" + attrName + "=" + attrs.getValue(attrName) + "]"; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
				} else {
					if (!currentParent.childElements.containsKey(raw)) {
						currentParent.childElements.put(raw, Integer.valueOf(1));
					} else {
						currentParent.childElements.put(raw, Integer.valueOf(currentParent.childElements.get(raw).intValue() + 1));
					}
					elementId= raw + Character.valueOf(ID_SEPARATOR) + "[" + currentParent.childElements.get(raw) + "]"; //$NON-NLS-2$ //$NON-NLS-1$
					elementName= MessageFormat.format("{0} [{1}]", raw, currentParent.childElements.get(raw).toString()); //$NON-NLS-1$
				}
				int start= r.getOffset() + prevlocator.getColumnNumber() - 1;
				if (start < 0)
					start= 0;
				currentElement= new XMLChildren(TYPE_ELEMENT, elementId, elementId, (fsignature + SIGN_ELEMENT), fdoc, start, 0);
				currentElement.setName(elementName);
				if (isUseIdMap() && idMap.containsKey(fsignature))
					currentElement.setUsesIDMAP(true);
				if (fOrdered != null && fOrdered.contains(parentSig))
					currentElement.setIsOrderedChild(true);

				fcurrentParent.addChild(currentElement);
				currentElement.setParent(fcurrentParent);
				fcurrentParent= currentElement;
				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("\nAdded Element " + raw + "  with offset " + r.getOffset()); //$NON-NLS-2$ //$NON-NLS-1$
				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("fcurrentParent1: " + fcurrentParent.getId()); //$NON-NLS-1$

				if (attrs != null) {
					if (XMLStructureCreator.DEBUG_MODE)
						System.out.println("attrs != null, fcurrentParent is " + fcurrentParent.getId()); //$NON-NLS-1$
					//attrs = sortAttributes(attrs);
					int len= attrs.getLength();
					int element_lines_length_size;
					int[] element_lines_length;
					int column_offset;
					String element_string;
					if (fcurrentParent.getParent().getId().equals(ROOT_ID)) {
						element_lines_length_size= locator.getLineNumber() - prevlocator.getLineNumber();
						element_lines_length= new int[element_lines_length_size];
						column_offset= 0;
						element_string= ""; //$NON-NLS-1$
						for (int i_ell= 0; i_ell < element_lines_length.length; i_ell++) {
							IRegion attr_r= fdoc.getLineInformation(i_ell + prevlocator.getLineNumber());
							element_lines_length[i_ell]= fdoc.get(attr_r.getOffset(), attr_r.getLength()).length() + 1;
							element_string= element_string + fdoc.get(attr_r.getOffset(), attr_r.getLength()) + " "; //$NON-NLS-1$
						}
					} else {
						element_lines_length_size= locator.getLineNumber() - prevlocator.getLineNumber() + 1;
						//if (element_lines_length_size < 1)
						// element_lines_length_size = 1;
						element_lines_length= new int[element_lines_length_size];
						IRegion first_line= fdoc.getLineInformation(prevlocator.getLineNumber() - 1);
						column_offset= prevlocator.getColumnNumber() - 1;
						int first_line_relevant_offset= first_line.getOffset() + column_offset;
						int first_line_relevant_length= first_line.getLength() - column_offset;
						element_string= fdoc.get(first_line_relevant_offset, first_line_relevant_length) + " "; //$NON-NLS-1$
						element_lines_length[0]= element_string.length();
						for (int i_ell= 1; i_ell < element_lines_length.length; i_ell++) {
							IRegion attr_r= fdoc.getLineInformation(i_ell + prevlocator.getLineNumber() - 1);
							element_lines_length[i_ell]= fdoc.get(attr_r.getOffset(), attr_r.getLength()).length() + 1;
							element_string= element_string + fdoc.get(attr_r.getOffset(), attr_r.getLength()) + " "; //$NON-NLS-1$
						}
					}

					for (int i_attr= 0; i_attr < len; i_attr++) {
						String attr_name= attrs.getQName(i_attr);
						String attr_value= attrs.getValue(i_attr);

						/*
						 * find range of attribute in doc; manually parses the
						 * line
						 */
						boolean found= false;
						int first_quotes= -1;
						int second_quotes= -1;
						int id_index= -1;
						while (!found) {
							first_quotes= element_string.indexOf("\"", second_quotes + 1); //$NON-NLS-1$
							second_quotes= element_string.indexOf("\"", first_quotes + 1); //$NON-NLS-1$
							String value;
							try {
								value= element_string.substring(first_quotes + 1, second_quotes);
							} catch (Exception e) {
								value= ""; //$NON-NLS-1$
							}
							if (value.equals("")) //$NON-NLS-1$
								found= true;
							else if (value.equals(attr_value)) {
								id_index= element_string.lastIndexOf(attr_name, first_quotes - 1);
								boolean wrong= false;
								boolean found_equal= false;
								for (int i_char= id_index + attr_name.length(); i_char < first_quotes && !wrong; i_char++) {
									if (element_string.charAt(i_char) == '=')
										if (!found_equal)
											found_equal= true;
										else
											wrong= true;
									else if (!Character.isWhitespace(element_string.charAt(i_char)))
										wrong= true;
								}
								if (!wrong)
									found= true;
							}
						}
						//id_index has one char missing for every line (the
						// final cr)
						int line_of_index= 0;
						for (line_of_index= 0; id_index > element_lines_length[line_of_index] - 1; line_of_index++)
							id_index-= (element_lines_length[line_of_index]);
						if (line_of_index == 0)
							id_index+= column_offset;
						if (fcurrentParent.getParent().getId().equals(ROOT_ID))
							line_of_index+= prevlocator.getLineNumber();
						else
							line_of_index+= prevlocator.getLineNumber() - 1;
						//index at line line_of_index, line offset id_index
						int line_of_end_of_value= 0;
						int end_of_value_index= second_quotes;
						for (line_of_end_of_value= 0; end_of_value_index > element_lines_length[line_of_end_of_value] - 1; line_of_end_of_value++)
							end_of_value_index-= (element_lines_length[line_of_end_of_value]);
						if (line_of_end_of_value == 0)
							end_of_value_index+= column_offset;
						if (fcurrentParent.getParent().getId().equals(ROOT_ID))
							line_of_end_of_value+= prevlocator.getLineNumber();
						else
							line_of_end_of_value+= prevlocator.getLineNumber() - 1;
						//end of value at line line_of_end_of_value, line
						// offset end_of_value_index

						int attr_start_doc_offset= fdoc.getLineInformation(line_of_index).getOffset() + id_index;
						//int attr_length_doc_offset =
						// fdoc.getLineInformation(line_of_value).getOffset()+value_index+attr_value.length()+1+(line_of_end_of_value-line_of_index)
						// - attr_start_doc_offset;
						int attr_length_doc_offset= fdoc.getLineInformation(line_of_end_of_value).getOffset() + end_of_value_index + 1 - attr_start_doc_offset;
						currentElement= new XMLNode(TYPE_ATTRIBUTE, attr_name, attr_value, (fsignature + attr_name + SIGN_SEPARATOR + SIGN_ATTRIBUTE), fdoc, attr_start_doc_offset, attr_length_doc_offset);
						currentElement.setName(attr_name);
						fcurrentParent.addChild(currentElement);
						currentElement.setParent(fcurrentParent);
						if (XMLStructureCreator.DEBUG_MODE)
							System.out.println("added attribute " + currentElement.getId() + " with value >" + currentElement.getValue() + "<" + " to element " + fcurrentParent.getId() + " which has parent " + fcurrentParent.getParent().getId()); //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
					}
				}
			} catch (BadLocationException ex) {
				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("BadLocationException in startElement(...) " + ex); //$NON-NLS-1$
				currentElement= new XMLChildren(TYPE_ELEMENT, raw + "_(" + ((XMLChildren) fcurrentParent).children + ")", raw + "_(" + ((XMLChildren) fcurrentParent).children + ")", (fsignature + SIGN_ELEMENT), fdoc, 0, 0); //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
			}
			if (XMLStructureCreator.DEBUG_MODE)
				System.out.println("At the end of startElement(...), fcurrentParent is " + fcurrentParent.getId()); //$NON-NLS-1$
			prevlocator= new LocatorImpl(locator);
		}

		/* Characters. */
		@Override
		public void characters(char ch[], int start, int length) {
			if (!ignoreBodies) {
				//			String chars = (new String(ch, start, length)).trim();
				String chars= new String(ch, start, length);
				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("characters: >" + chars + "<"); //$NON-NLS-2$ //$NON-NLS-1$
				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("Body Location: line " + locator.getLineNumber() + "  column " + locator.getColumnNumber()); //$NON-NLS-2$ //$NON-NLS-1$

				//if text contains only white space, it will be ignored.
				if (!trimWhiteSpace(chars).equals("")) { //$NON-NLS-1$
					if (XMLStructureCreator.DEBUG_MODE)
						System.out.println("Adding body"); //$NON-NLS-1$
					try {
						IRegion r= fdoc.getLineInformation(locator.getLineNumber() - 1);
						//location returns the END of the characters
						//offset of BEGINNING of characters:
						int offset= r.getOffset() + locator.getColumnNumber() - 1 - length;
						fcurrentParent.bodies++;
						String body_value= new String(ch, start, length);
						if (fRemoveWhiteSpace) {
							body_value= removeWhiteSpace(body_value);
						}
						XMLNode bodynode= new XMLNode(TYPE_TEXT, "body_(" + fcurrentParent.bodies + ")", body_value, (fsignature + SIGN_TEXT), fdoc, offset, length); //$NON-NLS-2$ //$NON-NLS-1$
						bodynode.setName(MessageFormat.format("{0} ({1})", XMLCompareMessages.XMLStructureCreator_body, Integer.toString(fcurrentParent.bodies)));  //$NON-NLS-1$
						fcurrentParent.addChild(bodynode);
						bodynode.setParent(fcurrentParent);
						if (XMLStructureCreator.DEBUG_MODE)
							System.out.println("Created body " + fcurrentParent.bodies //$NON-NLS-1$
									+ " with offset " + offset + " and length " + length //$NON-NLS-2$ //$NON-NLS-1$
									+ " with parent " + bodynode.getParent().getId()); //$NON-NLS-1$
						//bodies as id attributes
						String popsig= fcurrentParent.getParent().getSignature(); //signature of parent of
						// parent
						popsig= popsig.substring(0, popsig.lastIndexOf(SIGN_ELEMENT));
						if (isUseIdMap() && fcurrentParent.bodies == 1 && idMap.containsKey(popsig)) {
							String pid= fcurrentParent.getId();//id of parent
							String pelementname= pid.substring(0, pid.indexOf("<")); //name of parent element //$NON-NLS-1$
							if (((String) idMap.get(popsig)).equals(ID_TYPE_BODY + pelementname)) {
								XMLNode pop= fcurrentParent.getParent();
								String popid= pop.getId();
								String popelementname= popid.substring(0, popid.indexOf("<")); //$NON-NLS-1$
								pop.setId(popelementname + "<" + body_value); //$NON-NLS-1$
								pop.setOrigId(popelementname + "<" + body_value); //$NON-NLS-1$
								pop.setName(MessageFormat.format("{0} [{1}={2}]", popelementname, pelementname, body_value)); //$NON-NLS-1$
								pop.setUsesIDMAP(true);
							}
						}
					} catch (BadLocationException ex) {
						if (XMLStructureCreator.DEBUG_MODE)
							System.out.println("BadLocationException in characters(...) " + ex); //$NON-NLS-1$
						fcurrentParent.addChild(new XMLNode(TYPE_TEXT, "body_(" + fcurrentParent.bodies + ")", new String(ch, start, length), (fsignature + SIGN_TEXT), fdoc, 0, 0)); //$NON-NLS-2$ //$NON-NLS-1$
					}
				}
			}
			prevlocator= new LocatorImpl(locator);
		}

		/* Ignorable whitespace. */
		@Override
		public void ignorableWhitespace(char ch[], int start, int length) {
			//
			//// characters(ch, start, length);
			//// System.out.flush();
			//
			prevlocator= new LocatorImpl(locator);
		}

		/* End element. */
		@Override
		public void endElement(String uri, String local, String raw) {
			if (XMLStructureCreator.DEBUG_MODE)
				System.out.println("\nExiting element " + fcurrentParent.getId()); //$NON-NLS-1$

			if (XMLStructureCreator.DEBUG_MODE)
				System.out.println("prevlocator: line " + prevlocator.getLineNumber() + "  column " + prevlocator.getColumnNumber() + "  id " + prevlocator.getPublicId()); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
			if (XMLStructureCreator.DEBUG_MODE)
				System.out.println("locator: line " + locator.getLineNumber() + "  column " + locator.getColumnNumber() + "  id " + locator.getPublicId()); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$

			if (fcurrentParent.getParent() != null) {
				try {
					IRegion r2= fdoc.getLineInformation(locator.getLineNumber() - 1);
					Position pos= fcurrentParent.getRange();

					int elem_length= r2.getOffset() + locator.getColumnNumber() - 1 - pos.getOffset();//length of element from
					// start tag to end tag
					fcurrentParent.setLength(elem_length);
					if (XMLStructureCreator.DEBUG_MODE)
						System.out.println("pos.getOffset: " + pos.getOffset() + "  elem_length: " + elem_length); //$NON-NLS-2$ //$NON-NLS-1$
					if (XMLStructureCreator.DEBUG_MODE)
						System.out.println("fdoc.get(pos.getOffset()+elem_length-5,4): >" + fdoc.get(pos.getOffset() + elem_length - 5, 4) + "<"); //$NON-NLS-2$ //$NON-NLS-1$
					//if (fdoc.get(pos.getOffset()+elem_length-2,1) != ">")
					// elem_length-=1;
					try {
						fcurrentParent.setValue(fdoc.get(pos.getOffset(), elem_length));
					} catch (BadLocationException ex) {
						try {
							fcurrentParent.setValue(fdoc.get(pos.getOffset(), elem_length - 1));
						} catch (BadLocationException ex2) {
							if (XMLStructureCreator.DEBUG_MODE) {
								System.out.println("BadLocationException in endElement(...) while attempting fcurrentParent.setValue(...): " + ex); //$NON-NLS-1$
								System.out.println("Attempt to correct BadLocationException failed: " + ex2); //$NON-NLS-1$
							}
						}
					}
					if (XMLStructureCreator.DEBUG_MODE)
						System.out.println("Value of " + fcurrentParent.getId() + "  is >" + fcurrentParent.getValue() + "<"); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$

					//going from ending element to parent element
					fcurrentParent= fcurrentParent.getParent();
					if (XMLStructureCreator.DEBUG_MODE)
						System.out.println("fcurrentParent = fcurrentParent.getParent();"); //$NON-NLS-1$
				} catch (BadLocationException ex) {
					if (XMLStructureCreator.DEBUG_MODE) {
						System.out.println("BadLocationException in endElement(...): " + ex); //$NON-NLS-1$
						System.out.println("fcurrentParent.getId(): " + fcurrentParent.getId()); //$NON-NLS-1$
					}
				}
			} else {
				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("Error: Cannot reach Parent of Parent"); //$NON-NLS-1$
			}
			if (XMLStructureCreator.DEBUG_MODE)
				System.out.println("fcurrentParent is now " + fcurrentParent.getId()); //$NON-NLS-1$

			prevlocator= new LocatorImpl(locator);
			if (XMLStructureCreator.DEBUG_MODE)
				System.out.println("Signature before cutting: " + fsignature); //$NON-NLS-1$
			int ssi= fsignature.lastIndexOf(SIGN_SEPARATOR);//fsignature
			// separator index
			ssi= fsignature.lastIndexOf(SIGN_SEPARATOR, ssi - 1);//second-last
			// ".", e.g. in
			// root.a.b. to
			// obtain
			// root.a.
			fsignature= fsignature.substring(0, ssi + 1);
			if (XMLStructureCreator.DEBUG_MODE)
				System.out.println("Signature after cutting: " + fsignature); //$NON-NLS-1$
		}

		//
		// ErrorHandler methods
		//

		/* Warning. */
		@Override
		public void warning(SAXParseException ex) {
			System.err.println("[Warning] " + //$NON-NLS-1$
					getLocationString(ex) + ": " + //$NON-NLS-1$
					ex.getMessage());
		}

		/* Error. */
		@Override
		public void error(SAXParseException ex) {
			System.err.println("[Error] " + //$NON-NLS-1$
					getLocationString(ex) + ": " + //$NON-NLS-1$
					ex.getMessage());
		}

		/* Fatal error. */
		@Override
		public void fatalError(SAXParseException ex) throws SAXException {
			System.err.println("[Fatal Error] " + //$NON-NLS-1$
					getLocationString(ex) + ": " + //$NON-NLS-1$
					ex.getMessage());
			//System.out.println(ex);
			//throw ex;
		}

		/* Returns a string of the location. */
		private String getLocationString(SAXParseException ex) {
			StringBuilder str= new StringBuilder();

			String systemId= ex.getSystemId();
			if (systemId != null) {
				int index= systemId.lastIndexOf('/');
				if (index != -1)
					systemId= systemId.substring(index + 1);
				str.append(systemId);
			}
			str.append(':');
			str.append(ex.getLineNumber());
			str.append(':');
			str.append(ex.getColumnNumber());

			return str.toString();

		}
	}

	public XMLStructureCreator() {
		//set default idmap
		fIdMapToUse= DEFAULT_IDMAP;
		fUseIdMap= false;
		XMLPlugin plugin= XMLPlugin.getDefault();
		//if statement required for tests
		if (plugin != null) {
			fIdMaps= plugin.getIdMaps();
			fIdMapsInternal= plugin.getIdMapsInternal();
			fIdExtensionToName= plugin.getIdExtensionToName();
			fOrderedElements= plugin.getOrderedElements();
			fOrderedElementsInternal= plugin.getOrderedElementsInternal();
		}
		fRemoveWhiteSpace= false;
	}

	/*
	 * This title will be shown in the title bar of the structure compare pane.
	 */
	@Override
	public String getName() {
		return DEFAULT_NAME;
	}

	/*
	 * Set File extension of the parsed file. This extension will be used to choose an Id Map scheme.
	 */
	public void setFileExtension(String ext) {
		fFileExt= ext;
	}

	/**
	 * Initialize the Id Mappings for the Id Mapping Scheme and the Ordered Elements
	 * This method must be called before getStructure(Object) is called on the two/three inputs of the compare
	 */
	public void initIdMaps() {
		if (fFirstCall && fFileExt != null) {
			fFirstCall= false;
			String fileExtLower= fFileExt.toLowerCase();
			if (fIdExtensionToName.containsKey(fileExtLower))
				setIdMap((String) fIdExtensionToName.get(fileExtLower));
		}

		setUseIdMap();
		fOrdered= null;
		if (!isUseIdMap())
			idMap= null;
		else if (fIdMaps.containsKey(fIdMapToUse)) {
			idMap= (HashMap) fIdMaps.get(fIdMapToUse);
		} else if (fIdMapsInternal.containsKey(fIdMapToUse)) {
			idMap= (HashMap) fIdMapsInternal.get(fIdMapToUse);
		}

		if (fOrderedElements != null)
			fOrdered= (ArrayList) fOrderedElements.get(fIdMapToUse);
		if (fOrdered == null && fOrderedElementsInternal != null)
			fOrdered= (ArrayList) fOrderedElementsInternal.get(fIdMapToUse);
	}

	/*
	 * Returns the XML parse tree of the input.
	 */
	@Override
	public IStructureComparator getStructure(Object input) {
		if (XMLStructureCreator.DEBUG_MODE)
			System.out.println("Starting parse"); //$NON-NLS-1$

		if (!(input instanceof IStreamContentAccessor))
			return null;

		IStreamContentAccessor sca= (IStreamContentAccessor) input;

		try {
			// Input parsed with parser.parse(new InputSource(sca.getContents));	

			String contents= readString(sca);
			if (contents == null)
				contents= ""; //$NON-NLS-1$
			fdoc= new Document(contents);

			fsignature= ROOT_ID + SIGN_SEPARATOR;
			XMLChildren root= new XMLChildren(TYPE_ELEMENT, ROOT_ID, "", (fsignature + SIGN_ELEMENT), fdoc, 0, fdoc.getLength()); //$NON-NLS-1$
			fcurrentParent= root;

			XMLHandler handler= new XMLHandler();

			try {
				//            	/* original xerces code
				//            	SAXParser parser = (SAXParser)Class.forName(parserName).newInstance();
				//            	*/
				//				XMLReader parser = XMLReaderFactory.createXMLReader(parserName);
				//				
				//	            parser.setFeature( "http://xml.org/sax/features/validation", setValidation); //$NON-NLS-1$
				//    	        parser.setFeature( "http://xml.org/sax/features/namespaces", setNameSpaces ); //$NON-NLS-1$
				//    	        /*
				//    	        parser.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
				//        	    parser.setFeature( "http://apache.org/xml/features/validation/schema", setSchemaSupport ); //$NON-NLS-1$
				//	            parser.setFeature( "http://apache.org/xml/features/validation/schema-full-checking", setSchemaFullSupport); //$NON-NLS-1$
				//	           	*/
				//	            parser.setContentHandler(handler);
				//	            parser.setErrorHandler(handler);
				//	            
				//	            parser.parse(new InputSource(sca.getContents()));

				SAXParserFactory factory= SAXParserFactory.newInstance();
				factory.setNamespaceAware(true);
				SAXParser parser= factory.newSAXParser();
				parser.parse(new InputSource(new StringReader(contents)), handler);

				if (XMLStructureCreator.DEBUG_MODE)
					System.out.println("End of parse"); //$NON-NLS-1$
			} catch (SAXParseException e) {
				XMLPlugin.log(e);
				return null;
			} catch (Exception e) {
				//				MessageDialog.openError(XMLPlugin.getActiveWorkbenchShell(),"Error in XML parser","An error occured in the XML parser.\nNo structured compare can be shown");
				XMLPlugin.log(e);
				return null;
			}
			return root;
		} catch (CoreException ex) {
			XMLPlugin.log(ex);
		}
		return null;
	}

	public boolean canSave() {
		return true;
	}

	public boolean canRewriteTree() {
		return false;
	}

	public void rewriteTree(Differencer differencer, IDiffContainer root) {
			// nothing to do
	}

	@Override
	public void save(IStructureComparator structure, Object input) {
		if (input instanceof IEditableContent && structure instanceof XMLNode) {
			IDocument document= ((XMLNode) structure).getDocument();
			IEditableContent bca= (IEditableContent) input;
			String contents= document.get();
			String encoding= null;
			if (input instanceof IEncodedStreamContentAccessor) {
				try {
					encoding= ((IEncodedStreamContentAccessor)input).getCharset();
				} catch (CoreException e1) {
					// ignore
				}
			}
			if (encoding == null)
				encoding= "UTF-8"; //$NON-NLS-1$
			try {
				bca.setContent(contents.getBytes(encoding));
			} catch (UnsupportedEncodingException e) {
				bca.setContent(contents.getBytes());	
			}
		}
	}

	@Override
	public String getContents(Object node, boolean ignoreWhitespace) {
		if (node instanceof XMLNode) {
			String s= ((XMLNode) node).getValue();
			if (ignoreWhitespace)
				s= s.trim();
			return s;
		}
		return null;
	}

	@Override
	public IStructureComparator locate(Object path, Object source) {
		return null;
	}

	static String readString(IStreamContentAccessor sa) throws CoreException {
		InputStream is= sa.getContents();
		String encoding= null;
		if (sa instanceof IEncodedStreamContentAccessor)
			encoding= ((IEncodedStreamContentAccessor) sa).getCharset();
		if (encoding == null)
			encoding= "UTF-8"; //$NON-NLS-1$
		return readString(is, encoding);
	}

	/*
	 * Returns null if an error occurred.
	 */
	private static String readString(InputStream is, String encoding) {
		if (is == null)
			return null;
		BufferedReader reader= null;
		try {
			StringBuilder buffer= new StringBuilder();
			char[] part= new char[2048];
			int read= 0;
			reader= new BufferedReader(new InputStreamReader(is, encoding));

			while ((read= reader.read(part)) != -1)
				buffer.append(part, 0, read);

			return buffer.toString();

		} catch (IOException ex) {
			// NeedWork
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException ex) {
					// silently ignored
				}
			}
		}
		return null;
	}

	/* Returns a sorted list of attributes.
	 */
	protected Attributes sortAttributes(Attributes attrs) {

		AttributesImpl attributes= new AttributesImpl();
		int len= (attrs != null) ? attrs.getLength() : 0;
		for (int i= 0; i < len; i++) {
			String name= attrs.getQName(i);
			int count= attributes.getLength();
			int j= 0;
			while (j < count) {
				if (name.compareTo(attributes.getQName(j)) < 0)
					break;
				j++;
			}
			attributes.insertAttributeAt(j, name, attrs.getType(i), attrs.getValue(i));
		}

		return attributes;

	}

	public void setIdMap(String idmap_name) {
		fIdMapToUse= idmap_name;
	}

	/*
	 * Returns the name of the IdMap Scheme that will be used to set ids.
	 */
	public String getIdMap() {
		return fIdMapToUse;
	}

	public void setUseIdMap() {
		if (fIdMaps != null && fIdMapsInternal != null)
			fUseIdMap= fIdMaps.containsKey(fIdMapToUse) || fIdMapsInternal.containsKey(fIdMapToUse);
	}

	public boolean isUseIdMap() {
		return fUseIdMap;
	}

	public void updateIdMaps() {
		fIdMaps= XMLPlugin.getDefault().getIdMaps();
		fOrderedElements= XMLPlugin.getDefault().getOrderedElements();
	}

	protected boolean isWhiteSpace(char c) {
		return c == '\t' || c == '\n' || c == '\r' || c == ' ';
	}

	protected String removeWhiteSpace(String str) {
		str= trimWhiteSpace(str);
		StringBuilder retStr= new StringBuilder();
		int start= 0, end= 0;
		outer_while: while (true) {
			while (end < str.length() && !isWhiteSpace(str.charAt(end))) {
				end++;
			}
			if (end > str.length())
				break outer_while;
			if (start != 0)
				retStr.append(' ');
			retStr.append(str.substring(start, end));
			end++;
			while (end < str.length() && isWhiteSpace(str.charAt(end))) {
				end++;
			}
			start= end;
		}
		return retStr.toString();
	}

	protected String trimWhiteSpace(String str) {
		int start= 0, end= str.length() - 1;
		while (start < str.length() && isWhiteSpace(str.charAt(start))) {
			start++;
		}
		if (start == str.length())
			return ""; //$NON-NLS-1$
		while (end >= 0 && isWhiteSpace(str.charAt(end))) {
			end--;
		}
		return str.substring(start, end + 1);
	}

	public void setRemoveWhiteSpace(boolean removeWhiteSpace) {
		fRemoveWhiteSpace= removeWhiteSpace;
	}

	public boolean getRemoveWhiteSpace() {
		return fRemoveWhiteSpace;
	}
}
