| /******************************************************************************* |
| * Copyright (c) 2000, 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 |
| *******************************************************************************/ |
| 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.getString("XMLStructureCreator.pluginname"); //$NON-NLS-1$ |
| |
| 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; |
| |
| 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 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 |
| |
| 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); |
| } |
| |
| /** Start document. */ |
| public void startDocument() { |
| prevlocator= new LocatorImpl(locator); |
| } |
| |
| /* 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$ |
| } |
| 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. */ |
| 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); |
| } |
| |
| /* Ignorable whitespace. */ |
| public void ignorableWhitespace(char ch[], int start, int length) { |
| // |
| //// characters(ch, start, length); |
| //// System.out.flush(); |
| // |
| prevlocator= new LocatorImpl(locator); |
| } |
| |
| /* 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$ |
| } |
| |
| // |
| // 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(); |
| |
| } |
| } |
| |
| 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. |
| */ |
| 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); |
| 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 |
| } |
| |
| 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()); |
| } |
| } |
| } |
| |
| 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; |
| } |
| |
| 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 { |
| StringBuffer buffer= new StringBuffer(); |
| 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); |
| 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; |
| } |
| } |