blob: df7d097b65240d43525ebf174eb30d3d0b845baa [file] [log] [blame]
/*******************************************************************************
* 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.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;
import org.eclipse.core.runtime.IProgressMonitor;
public class OrderedMatching extends AbstractMatching {
public OrderedMatching() {
super();
}
protected int orderedMath(XMLNode x, XMLNode y) {
//assumes x and y have children
Object[] xc= x.getChildren();
Object[] yc= y.getChildren();
ArrayList xc_elementsAL= new ArrayList();
ArrayList xc_attrsAL= new ArrayList();
ArrayList yc_elementsAL= new ArrayList();
ArrayList yc_attrsAL= new ArrayList();
//find attributes and elements and put them in xc_elementsAL and xc_attrsAL, respectively
for (int i= 0; i < xc.length; i++) {
XMLNode x_i= (XMLNode) xc[i];
if (x_i.getXMLType().equals(XMLStructureCreator.TYPE_ELEMENT)) {
xc_elementsAL.add(x_i);
} else if (
x_i.getXMLType().equals(XMLStructureCreator.TYPE_ATTRIBUTE)) {
xc_attrsAL.add(x_i);
}
}
//do the same for yc
for (int i= 0; i < yc.length; i++) {
XMLNode y_i= (XMLNode) yc[i];
if (y_i.getXMLType().equals(XMLStructureCreator.TYPE_ELEMENT)) {
yc_elementsAL.add(y_i);
} else if (
y_i.getXMLType().equals(XMLStructureCreator.TYPE_ATTRIBUTE)) {
yc_attrsAL.add(y_i);
}
}
Object[] xc_elements= xc_elementsAL.toArray();
Object[] yc_elements= yc_elementsAL.toArray();
ArrayList DTMatching= new ArrayList();
// Matching to be added to Entry in fDT_Matchings
int distance= 0; //distance to be added to entry in fDT
// perform unordered matching on attributes
// this updates fDT and fDT_Matchings
if (xc_attrsAL.size() > 0 || yc_attrsAL.size() > 0) {
if (xc_attrsAL.size() == 0)
distance += yc_attrsAL.size();
else if (yc_attrsAL.size() == 0)
distance += xc_attrsAL.size();
else {
//unorderedMatch(x, y, xc_attrs, yc_attrs);
// distance += fDT[indexOfLN(x)][indexOfRN(y)];
// DTMatching= fDT_Matchings[indexOfLN(x)][indexOfRN(y)];
distance= handleAttributes(xc_attrsAL, yc_attrsAL, DTMatching);
}
}
//perform ordered matching on element children, i.e. number them in order of appearance
/* start new */
distance=
handleRangeDifferencer(
xc_elements,
yc_elements,
DTMatching,
distance);
/* end new */
/* start: Naive ordered compare /*
// int minlength= (xc_elements.length > yc_elements.length)?yc_elements.length:xc_elements.length;
// for (int i= 0; i < minlength; i++) {
// distance += dist((XMLNode) xc_elements[i], (XMLNode) yc_elements[i]);
// DTMatching.add(new Match( (XMLNode)xc_elements[i], (XMLNode)yc_elements[i]));
// }
// if (xc_elements.length > yc_elements.length) {
// for (int i= minlength; i < xc_elements.length; i++) {
// distance += countNodes((XMLNode) xc_elements[i]);
// }
// } else if (xc_elements.length < yc_elements.length) {
// for (int i= minlength; i < yc_elements.length; i++) {
// distance += countNodes((XMLNode) yc_elements[i]);
// }
// }
/* end: Naive ordered compare */
fDT[indexOfLN(x)][indexOfRN(y)]= distance;
fDT_Matchings[indexOfLN(x)][indexOfRN(y)]= DTMatching;
return distance;
}
/* matches two trees according to paper "X-Diff", p. 16 */
public void match(
XMLNode LeftTree,
XMLNode RightTree,
boolean rightTreeIsAncestor,
IProgressMonitor monitor)
throws InterruptedException {
fNLeft= new Vector();
//numbering LeftTree: Mapping nodes in LeftTree to numbers to be used as array indexes
fNRight= new Vector();
//numbering RightTree: Mapping nodes in RightTree to numbers to be used as array indexes
numberNodes(LeftTree, fNLeft);
numberNodes(RightTree, fNRight);
fDT= new int[fNLeft.size()][fNRight.size()];
fDT_Matchings= new ArrayList[fNLeft.size()][fNRight.size()];
for (int i= 0; i < fDT.length; i++) {
fDT[i]= new int[fNRight.size()];
for (int j= 0; j < fDT[0].length; j++) {
fDT[i][j]= NO_ENTRY;
}
}
dist(LeftTree, RightTree);
// /* mark matchings on LeftTree and RightTree */
fMatches= new Vector();
if (!LeftTree.getSignature().equals(RightTree.getSignature())) {
//matching is empty
} else {
fMatches.add(new Match(LeftTree, RightTree));
for (int i_M= 0; i_M < fMatches.size(); i_M++) {
Match m= (Match) fMatches.elementAt(i_M);
if (!isLeaf(m.fx) && !isLeaf(m.fy)) {
// if (fDT_Matchings[ indexOfLN(m.fx) ][ indexOfRN(m.fy) ] == null)
// System.out.println("Error: ID not unique for " + m.fx.getId());
// else
// fMatches.addAll(fDT_Matchings[ indexOfLN(m.fx) ][ indexOfRN(m.fy) ]);
if (fDT_Matchings[indexOfLN(m.fx)][indexOfRN(m.fy)]
!= null)
fMatches.addAll(
fDT_Matchings[indexOfLN(m.fx)][indexOfRN(m.fy)]);
}
}
}
//end of Step2
/* Renumber Id of Nodes to follow Matches. Or for ancestor, copy over Id to ancestor */
if (rightTreeIsAncestor) {
for (ListIterator it_M= fMatches.listIterator(); it_M.hasNext();) {
Match m= (Match) it_M.next();
if (m.fx != null && m.fy != null)
m.fy.setId(m.fx.getId());
}
} else {
int newId= 0;
for (ListIterator it_M= fMatches.listIterator();
it_M.hasNext();
newId++) {
Match m= (Match) it_M.next();
if (m.fx != null)
m.fx.setId(Integer.toString(newId));
if (m.fy != null)
m.fy.setId(Integer.toString(newId));
// System.out.println("Matching: "+ ((m.fx != null)?m.fx.getOrigId():"null")+" -> "+((m.fx != null)?m.fx.getId():"null")+" , "+((m.fy != null)?m.fy.getOrigId():"null")+" -> "+((m.fy != null)?m.fy.getId():"null")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
}
//if (monitor != null) monitor.done();
}
public int handleAttributes(
ArrayList xc_attrs,
ArrayList yc_attrs,
ArrayList DTMatching) {
int distance= 0;
x_for : for (
Iterator iter_xc= xc_attrs.iterator(); iter_xc.hasNext();) {
XMLNode x_attr= (XMLNode) iter_xc.next();
String x_attr_name= x_attr.getName();
for (Iterator iter_yc= yc_attrs.iterator(); iter_yc.hasNext();) {
XMLNode y_attr= (XMLNode) iter_yc.next();
if (y_attr.getName().equals(x_attr_name)) {
if (!y_attr.getValue().equals(x_attr.getValue()))
distance += 1;
DTMatching.add(new Match(x_attr, y_attr));
yc_attrs.remove(y_attr);
continue x_for;
}
}
DTMatching.add(new Match(x_attr, null));
distance += 1;
}
for (Iterator iter_yc= yc_attrs.iterator(); iter_yc.hasNext();) {
DTMatching.add(new Match(null, (XMLNode) iter_yc.next()));
distance += 1;
}
return distance;
}
protected int handleXandYnotLeaves(XMLNode x, XMLNode y) {
/* handle entries as ordered*/
return orderedMath(x, y);
}
}