blob: bf86f6eb8d7d0d80a58e8e5ad16f4af519843cf5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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
*******************************************************************************/
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(((Integer) 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;
}
}