/******************************************************************************* * Copyright 2012 University of Southern California * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This code was developed by the Information Integration Group as part * of the Karma project at the Information Sciences Institute of the * University of Southern California. For more information, publications, * and related projects, please see: http://www.isi.edu/integration ******************************************************************************/ /** * */ package edu.isi.karma.rep; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author szekely * */ public class HNodePath { private static final Logger LOG = LoggerFactory.getLogger(HNodePath.class); private List<HNode> hNodes = new LinkedList<>(); private Object msger = null;//used for holding session cleaning data private Object dpp = null; // data preprocessing for cleaning public HNodePath() { } public HNodePath(HNode hNode) { hNodes.add(hNode); } public HNodePath(List<HNode> hNodes) { this.hNodes = hNodes; } public HNodePath(HNodePath path) { for (HNode hn : path.hNodes) { this.hNodes.add(hn); } } /** * Adds an HNode to this path. * @param n * @author mariam */ public void addHNode(HNode n){ hNodes.add(n); } /** * Adds an HNodePath to this path. * @param np * @author mariam */ public void addHNodePath(HNodePath np){ hNodes.addAll(np.hNodes); } public boolean isEmpty() { return hNodes.isEmpty(); } public HNode getFirst() { return hNodes.get(0); } public HNode getLeaf() { return hNodes.get(hNodes.size() - 1); } public HNodePath getRest() { return new HNodePath(hNodes.subList(1, hNodes.size())); } public HNodePath reverse() { HNodePath reversedPath = new HNodePath(); ListIterator<HNode> pathIterator = hNodes.listIterator(hNodes.size()); while(pathIterator.hasPrevious()) { reversedPath.addHNode(pathIterator.previous()); } return reversedPath; } public boolean contains(HNode hNode) { return hNodes.contains(hNode); } public String toString() { StringBuffer b = new StringBuffer(); Iterator<HNode> it = hNodes.iterator(); while (it.hasNext()) { b.append(it.next().getId()); if (it.hasNext()){ b.append("/"); } } return b.toString(); } //mariam /** * Returns the HNodePath as a String containing the column name of the child node at the end. * @return * the HNodePath as a String containing the column name of the child node at the end. * Example: * HN1/HN2/ColumnName */ public String addColumnName() { String path = toString() + "/"; //get the last node HNode n = hNodes.get(hNodes.size()-1); path += n.getColumnName(); return path; } /** * Returns the HNodePath as a String containing column names instead of HnodeIds * @return * the HNodePath as a String containing column names instead of HnodeIds. * Example: * ColumnName1/ColumnName2 */ public String toColumnNamePath() { StringBuffer b = new StringBuffer(); Iterator<HNode> it = hNodes.iterator(); while (it.hasNext()) { b.append(it.next().getColumnName()); if (it.hasNext()){ b.append("/"); } } return b.toString(); } public static HNodePath concatenate(HNodePath prefix, HNodePath suffix) { HNodePath result = new HNodePath(prefix); for (HNode hn : suffix.hNodes){ result.hNodes.add(hn); } return result; } public static HNodePath findCommon(HNodePath path1, HNodePath path2) { HNodePath newPath = new HNodePath(); HNodePath path1Temp = path1; HNodePath path2Temp = path2; while((path1Temp != null && path2Temp != null) && (!path1Temp.isEmpty() && !path2Temp.isEmpty())&& path1Temp.getFirst() == path2Temp.getFirst()) { newPath.addHNode(path1Temp.getFirst()); path1Temp = path1Temp.getRest(); path2Temp = path2Temp.getRest(); } return newPath; } public static HNodePath removeCommon(HNodePath target, HNodePath toRemove) { HNodePath path1Temp = target; HNodePath path2Temp = toRemove; while((path1Temp != null && path2Temp != null) && (!path1Temp.isEmpty() && !path2Temp.isEmpty())&& path1Temp.getFirst() == path2Temp.getFirst()) { path1Temp = path1Temp.getRest(); path2Temp = path2Temp.getRest(); } return path1Temp; } public static HNodePath findPathBetweenLeavesWithCommonHead(HNodePath start, HNodePath finish) { HNodePath newPath = new HNodePath(); if(start == null || finish == null) { LOG.error("Attempted to find path between null path"); return newPath; } if(start.getLeaf() == finish.getLeaf()) { newPath.addHNode(start.getLeaf()); return newPath; } HNodePath commonPath = findCommon(start, finish); if(commonPath.isEmpty()) { newPath.addHNodePath(start.reverse()); newPath.addHNodePath(finish); } else { HNodePath truncatedStartPath = removeCommon(start, commonPath); HNodePath truncatedFinishPath = removeCommon(finish, commonPath); //TODO one path is nested on the other if(commonPath.getLeaf() == start.getLeaf() || commonPath.getLeaf() == finish.getLeaf()) { if(truncatedStartPath.isEmpty()) { newPath.addHNode(start.getLeaf()); newPath.addHNodePath(truncatedFinishPath); } else { newPath.addHNode(finish.getLeaf()); newPath.addHNodePath(truncatedStartPath.reverse()); } } else { newPath.addHNodePath(truncatedStartPath.reverse()); newPath.addHNodePath(truncatedFinishPath); } } return newPath; } public int length() { return hNodes.size(); } }