blob: b879996c0875185b9f37ccbf98abd4ada585cb90 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-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.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.xerces.parsers.SAXParser;
import org.eclipse.compare.IEditableContent;
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;
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.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;
/**
* 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;
private XMLNode fcurrentParent;
private String fsignature;
private Document fdoc;
private boolean ignoreBodies = false;
//private String fName;
public static final String DEFAULT_NAME = XMLCompareMessages.getString("XMLStructureCreator.pluginname"); //$NON-NLS-1$
private HashMap fIdMapsInternal;
private HashMap fIdMaps;
private HashMap fIdExtensionToName;
private HashMap fOrderedElementsInternal;
private HashMap fOrderedElements;
private HashMap idMap;
private ArrayList fOrdered;
public static final String USE_UNORDERED = XMLCompareMessages.getString("XMLStructureCreator.unordered"); //$NON-NLS-1$
public static final String USE_ORDERED = XMLCompareMessages.getString("XMLStructureCreator.ordered"); //$NON-NLS-1$
public static final String DEFAULT_IDMAP= USE_ORDERED;
private String fIdMapToUse;
private boolean fUseIdMap;
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.getString("XMLStructureCreator.idmap_unordered"); //$NON-NLS-1$
public static final char ID_SEPARATOR = '<';
public static final char ID_TYPE_BODY = '<';
private static final String parserName = "org.apache.xerces.parsers.SAXParser"; //$NON-NLS-1$
private static boolean setValidation = false; //defaults
private static boolean setNameSpaces = true;
private static boolean setSchemaSupport = true;
private static boolean setSchemaFullSupport = false;
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
public void setDocumentLocator (Locator locator0) {
this.locator = locator0;
}
//
// DocumentHandler methods
//
/** Processing instruction. */
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);
} // processingInstruction(String,String)
/** Start document. */
public void startDocument() {
prevlocator = new LocatorImpl(locator);
} // startDocument()
/** Start element. */
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 + new Character(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,new Integer(1));
} else {
currentParent.childElements.put(raw,new Integer(((Integer)currentParent.childElements.get(raw)).intValue()+1));
}
elementId = raw+new Character(ID_SEPARATOR)+"["+currentParent.childElements.get(raw)+"]"; //$NON-NLS-2$ //$NON-NLS-1$
elementName = MessageFormat.format("{0} [{1}]",new String[] {raw,currentParent.childElements.get(raw).toString()}); //$NON-NLS-2$ //$NON-NLS-1$
}
currentElement = new XMLChildren(TYPE_ELEMENT,elementId,elementId,(fsignature+SIGN_ELEMENT),fdoc,r.getOffset()+prevlocator.getColumnNumber()-1,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);
} // startElement(String,String,String,Attributes)
/** Characters. */
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})",new String[] {XMLCompareMessages.getString("XMLStructureCreator.body"),Integer.toString(fcurrentParent.bodies)})); //$NON-NLS-2$ //$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}]",new String[] {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);
} // characters(char[],int,int);
/** Ignorable whitespace. */
public void ignorableWhitespace(char ch[], int start, int length) {
//
//// characters(ch, start, length);
//// System.out.flush();
//
prevlocator = new LocatorImpl(locator);
} // ignorableWhitespace(char[],int,int);
/** End element. */
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$
} // endElement(String)
//
// ErrorHandler methods
//
/** Warning. */
public void warning(SAXParseException ex) {
System.err.println("[Warning] "+ //$NON-NLS-1$
getLocationString(ex)+": "+ //$NON-NLS-1$
ex.getMessage());
}
/** Error. */
public void error(SAXParseException ex) {
System.err.println("[Error] "+ //$NON-NLS-1$
getLocationString(ex)+": "+ //$NON-NLS-1$
ex.getMessage());
}
/** Fatal error. */
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) {
StringBuffer str = new StringBuffer();
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();
} // getLocationString(SAXParseException):String
}
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;
}
// public void setNameScheme(String idmap_name) {
// fName = MessageFormat.format("{0} ({1})", new String[] {DEFAULT_NAME,idmap_name}); //$NON-NLS-1$
// }
//
/**
* This title will be shown in the title bar of the structure compare pane.
*/
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.
*/
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.getContents());
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 {
SAXParser parser = (SAXParser)Class.forName(parserName).newInstance();
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()));
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) {
}
public void save(IStructureComparator structure, Object input) {
if (input instanceof IEditableContent && structure instanceof XMLNode) {
IDocument doc= ((XMLNode)structure).getDocument();
IEditableContent bca= (IEditableContent) input;
String c= doc.get();
bca.setContent(c.getBytes());
}
}
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;
}
public IStructureComparator locate(Object path, Object source) {
return null;
}
/**
* Returns null if an error occurred.
*/
static String readString(InputStream is) {
if (is == null)
return null;
BufferedReader reader= null;
try {
StringBuffer buffer= new StringBuffer();
char[] part= new char[2048];
int read= 0;
reader= new BufferedReader(new InputStreamReader(is));
while ((read= reader.read(part)) != -1)
buffer.append(part, 0, read);
return buffer.toString();
} catch (IOException ex) {
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
}
}
}
return null;
}
/** Returns a sorted list of attributes. */
/* Taken from SAX2Writer sample of xerces */
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;
} // sortAttributes(AttributeList):AttributeList
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);
StringBuffer retStr= new StringBuffer();
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;
}
}