/* * Copyright (c) 2010, SQL Power Group Inc. * * This file is part of SQL Power Library. * * SQL Power Library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * SQL Power Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package ca.sqlpower.diff; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import ca.sqlpower.sqlobject.SQLObjectException; /** * This class is used to build a tree of DiffChunks, based on uuid/parent mapping. * It is used for the purpose of creating an ordered list of DiffChunks. */ public class DiffChunkTreeNode { private String uuid; private DiffChunk<DiffInfo> chunk; private HashMap<String, DiffChunkTreeNode> children; public DiffChunkTreeNode(String uuid, DiffChunk<DiffInfo> chunk) { this.uuid = uuid; this.chunk = chunk; children = new HashMap<String, DiffChunkTreeNode>(); } public void addChild(String uuid, DiffChunk<DiffInfo> chunk) { children.put(uuid, new DiffChunkTreeNode(uuid, chunk)); } /** * This method will add the given DiffChunk to this node if this * node is the one specified by nodeUUID. Otherwise, it will recursively * look for the descendant with the specified nodeUUID and the chunk will be * added there. * * @param childUUID * @param chunk * @param nodeUUID * @return Whether the object was added successfully somewhere within the tree */ public boolean addChildToNode(String childUUID, DiffChunk<DiffInfo> chunk, String nodeUUID) { if (this.uuid.equals(nodeUUID)) { addChild(childUUID, chunk); return true; } else { Iterator<String> keys = children.keySet().iterator(); while (keys.hasNext()) { if (children.get(keys.next()).addChildToNode(childUUID, chunk, nodeUUID)) { return true; } } return false; } } /** * Goes through the tree recursively, building a list of all the DiffChunks contained within. * The list is in the order of {first parent}, {children of first parent}, {second parent}, {children of second parent}, etc. * Sets the depth of all the DiffInfo items as it builds the list. */ public List<DiffChunk<DiffInfo>> buildOrderedList() { List<DiffChunk<DiffInfo>> diffChunks = new ArrayList<DiffChunk<DiffInfo>>(); buildOrderedList(diffChunks, -1); return diffChunks; } private void buildOrderedList(List<DiffChunk<DiffInfo>> diffChunks, int depth) { if (chunk != null) { chunk.getData().setDepth(depth); diffChunks.add(chunk); } Iterator<String> keys = children.keySet().iterator(); while (keys.hasNext()) { children.get(keys.next()).buildOrderedList(diffChunks, depth + 1); } } /** * Constructs a tree of the given DiffChunks using the * given parentMap to know the structure of the tree. * This instance of DiffChunkTreeNode will act as the root, * having all passed DiffChunks added below it, somewhere. * * @param diffChunks * @param parentMap * @throws SQLObjectException */ public void constructTree(Map<String, DiffChunk<DiffInfo>> diffChunks, Map<String, String> parentMap) throws SQLObjectException { Set<String> uuidsInTree = new HashSet<String>(); uuidsInTree.add(this.uuid); // Loop through all the uuids of the objects that were added/removed/changed. // Add each to the tree by adding all their ancestors if they are not already added, too. Iterator<String> uuids = parentMap.keySet().iterator(); while (uuids.hasNext()) { String uuid = uuids.next(); // Construct a list of ancestors that are not in the tree, but need to be. List<String> addToTree = new ArrayList<String>(); // Go through the ancestors of the object we intend to add // until we reach the root, or an object that is already in the tree. String nextUUID = uuid; while (!nextUUID.equals(this.uuid) && !uuidsInTree.contains(nextUUID)) { addToTree.add(nextUUID); nextUUID = parentMap.get(nextUUID); } // Add all the objects, starting from the oldest ancestor. for (int i = addToTree.size() - 1; i >= 0; i--) { String u = addToTree.get(i); if (this.addChildToNode(u, diffChunks.get(u), parentMap.get(u))) {; uuidsInTree.add(u); } else { throw new SQLObjectException("Error adding DiffChunks to tree"); } } } } }