001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.xml.xdm.diff;
043:
044: import java.util.ArrayList;
045: import java.util.HashMap;
046: import java.util.List;
047: import org.netbeans.modules.xml.xdm.nodes.Attribute;
048: import org.netbeans.modules.xml.xdm.nodes.Element;
049: import org.netbeans.modules.xml.xdm.nodes.Node;
050: import org.w3c.dom.NamedNodeMap;
051:
052: /**
053: * This class represents node change between 2 DOM tree
054: *
055: * @author Ayub Khan
056: */
057: public class Change extends Difference {
058:
059: public enum Type {
060: TOKEN("token"), ATTRIBUTE("attribute"), POSITION("position"), UNKNOWN(
061: "unknown"), NO_CHANGE("noChange");
062:
063: String name;
064:
065: Type(String name) {
066: this .name = name;
067: }
068: }
069:
070: /** Creates a new instance of DiffEvent */
071: public Change(NodeInfo.NodeType nodeType, List<Node> ancestors1,
072: List<Node> ancestors2, Node n1, Node n2, int n1Pos,
073: int n2Pos, List<Type> changes) {
074: super (nodeType, ancestors1, ancestors2, n1, n2, n1Pos, n2Pos);
075: if (ancestors2.size() > 0) {
076: assert ancestors2.get(0).getIndexOfChild(n2) > -1;
077: }
078: assert changes != null && !changes.isEmpty();
079: this .changes = changes;
080:
081: if (changes.contains(Type.ATTRIBUTE)) {
082: if (n1 instanceof Element) {//find attr changes and add them
083: NamedNodeMap nm1 = n1.getAttributes();
084: NamedNodeMap nm2 = n2.getAttributes();
085: HashMap<Node, Integer> posMap = new HashMap<Node, Integer>();
086: List<String> allAttrNames = new ArrayList<String>();
087: for (int i = 0; i < nm1.getLength(); i++) {
088: Node oldAttr = (Node) nm1.item(i);
089: String name = oldAttr.getNodeName();
090: if (!allAttrNames.contains(name))
091: allAttrNames.add(name);
092: posMap.put(oldAttr, new Integer(i));
093: }
094: for (int i = 0; i < nm2.getLength(); i++) {
095: Node newAttr = (Node) nm2.item(i);
096: String name = newAttr.getNodeName();
097: if (!allAttrNames.contains(name))
098: allAttrNames.add(name);
099: posMap.put(newAttr, new Integer(i));
100: }
101: for (int i = 0; i < allAttrNames.size(); i++) {
102: String attrName = allAttrNames.get(i);
103: Node oldAttr = (Node) nm1.getNamedItem(attrName);
104: Node currAttr = (Node) nm2.getNamedItem(attrName);
105: int oldAttrPos = oldAttr != null ? posMap.get(
106: oldAttr).intValue() : -1;
107: int newAttrPos = currAttr != null ? posMap.get(
108: currAttr).intValue() : -1;
109: if (oldAttr != null) {
110: if (currAttr == null) {
111: AttributeDelete delete = new AttributeDelete(
112: (Attribute) oldAttr, oldAttrPos);
113: addAttrChanges(delete);
114: } else {
115: boolean tokenChange = new DiffFinder()
116: .checkChange(oldAttr, currAttr)
117: .size() > 0;
118: boolean posChange = oldAttrPos != newAttrPos;
119: if (tokenChange || posChange) {
120: AttributeChange change = new AttributeChange(
121: (Attribute) oldAttr,
122: (Attribute) currAttr,
123: oldAttrPos, newAttrPos,
124: tokenChange, posChange);
125: addAttrChanges(change);
126: }
127: }
128: } else if (currAttr != null) {
129: AttributeAdd add = new AttributeAdd(
130: (Attribute) currAttr, newAttrPos);
131: addAttrChanges(add);
132: }
133: }
134: }
135: }
136: }
137:
138: public List<AttributeDiff> getAttrChanges() {
139: return attrChanges;
140: }
141:
142: public void addAttrChanges(AttributeDiff attrDif) {
143: attrChanges.add(attrDif);
144: }
145:
146: public void removeAttrChanges(AttributeDiff attrDif) {
147: attrChanges.remove(attrDif);
148: }
149:
150: public boolean isTokenChanged() {
151: return changes.contains(Type.TOKEN);
152: }
153:
154: /**
155: * @return true if attribute list changes or attribute tokens change.
156: */
157: public boolean isAttributeChanged() {
158: return changes.contains(Type.ATTRIBUTE);
159: }
160:
161: public boolean isPositionChanged() {
162: return changes.contains(Type.POSITION);
163: }
164:
165: void setPositionChanged(boolean posChange) {
166: if (posChange && !changes.contains(Type.POSITION))
167: changes.add(Type.POSITION);
168: else if (!posChange && changes.contains(Type.POSITION))
169: changes.remove(Type.POSITION);
170: }
171:
172: public void setNewParent(Node parent2) {
173: if (parent2 == null)
174: return;
175: assert parent2.getId() == getOldNodeInfo().getParent().getId();
176: getOldNodeInfo().setNewParent(parent2);
177: getNewNodeInfo().setNewParent(parent2);
178: }
179:
180: public Node getNewParent() {
181: return getNewNodeInfo().getNewParent();
182: }
183:
184: public List<Node> getNewAncestors() {
185: return getNewNodeInfo().getNewAncestors();
186: }
187:
188: public boolean isValid() {
189: return !changes.isEmpty();
190: }
191:
192: public String toString() {
193: return "CHANGE" + changes + "(" + getOldNodeInfo() + ","
194: + getNewNodeInfo() + ")";
195: }
196:
197: ////////////////////////////////////////////////////////////////////////////////
198: // Member variables
199: ////////////////////////////////////////////////////////////////////////////////
200:
201: private List<Type> changes;
202: private List<AttributeDiff> attrChanges = new ArrayList<AttributeDiff>();
203:
204: public class AttributeAdd extends AttributeDiff {
205:
206: public AttributeAdd(Attribute newAttr, int newAttrPos) {
207: super (null, newAttr, -1, newAttrPos);
208: }
209: }
210:
211: public class AttributeDelete extends AttributeDiff {
212:
213: public AttributeDelete(Attribute oldAttr, int oldAttrPos) {
214: super (oldAttr, null, oldAttrPos, -1);
215: }
216: }
217:
218: public class AttributeChange extends AttributeDiff {
219:
220: private boolean posChanged;
221:
222: private boolean tokenChanged;
223:
224: public AttributeChange(Attribute oldAttr, Attribute newAttr,
225: int oldAttrPos, int newAttrPos, boolean tokenChanged,
226: boolean posChanged) {
227: super (oldAttr, newAttr, oldAttrPos, newAttrPos);
228: this .tokenChanged = tokenChanged;
229: this .posChanged = posChanged;
230: }
231:
232: public boolean isTokenChanged() {
233: return tokenChanged;
234: }
235:
236: public boolean isPositionChanged() {
237: return posChanged;
238: }
239: }
240:
241: public class AttributeDiff {
242:
243: private Attribute oldAttr;
244:
245: private Attribute newAttr;
246:
247: private int oldAttrPos;
248:
249: private int newAttrPos;
250:
251: public AttributeDiff(Attribute oldAttr, Attribute newAttr,
252: int oldAttrPos, int newAttrPos) {
253: this .oldAttr = oldAttr;
254: this .newAttr = newAttr;
255: this .oldAttrPos = oldAttrPos;
256: this .newAttrPos = newAttrPos;
257: }
258:
259: public Attribute getOldAttribute() {
260: return oldAttr;
261: }
262:
263: public Attribute getNewAttribute() {
264: return newAttr;
265: }
266:
267: public int getOldAttributePosition() {
268: return oldAttrPos;
269: }
270:
271: public int getNewAttributePosition() {
272: return newAttrPos;
273: }
274: }
275:
276: }
|