/******************************************************************************* * 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.io.PrintWriter; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.isi.karma.controller.command.selection.SuperSelection; /** * @author szekely * */ public class Row extends RepEntity implements Neighbor { private static Logger logger = LoggerFactory.getLogger(Row.class .getSimpleName()); // My nodes, columns containing cells or nested tables, a map from HNode ids // to Node. private final Map<String, Node> nodes = new HashMap<>(); // mariam /** * The table that this row belongs to */ private Table belongsToTable; Row(String id) { super(id); } public Node getNode(String hNodeId) { return nodes.get(hNodeId); } // mariam public void removeNode(String hNodeId) { nodes.remove(hNodeId); for (Node n : nodes.values()) { Table nestedTable = n.getNestedTable(); if (nestedTable != null) { nestedTable.removeNodeFromDataTable(hNodeId); } } } public Collection<Node> getNodes() { return nodes.values(); } // mariam /** * Returns all nodes and associated HNodeIds. * * @return all nodes and associated HNodeIds. */ public Map<String, Node> getNodesMap() { return nodes; } public void setBelongsToTable(Table t) { belongsToTable = t; } public Table getBelongsToTable() { return belongsToTable; } public String getWorksheetId() { return belongsToTable.getWorksheetId(); } // /////////////// void addNode(Node node) { nodes.put(node.getHNodeId(), node); // mariam node.setBelongsToRow(this); } /** * @param hNodeId * @param value * @param status * @return the row containing the modified node. */ public Row setValue(String hNodeId, CellValue value, Node.NodeStatus status, RepFactory factory) { getNode(hNodeId).setValue(value, status, factory); return this; } /** * Convenience method to set values in nodes in rows. * * @param hNodeId * @param value * @param status * specifies the status of the value * @return the row containing the modified node. */ public Row setValue(String hNodeId, String value, Node.NodeStatus status, RepFactory factory) { getNode(hNodeId).setValue(value, status, factory); return this; } /** * Convenience method to set values with status = original. * * @param hNodeId * @param value * @return the row containing the modified node. */ public Row setValue(String hNodeId, String value, RepFactory factory) { return setValue(hNodeId, value, Node.NodeStatus.original, factory); } /** * Convenience method to add nested rows * * @param hNodeId * , that contains the nested table where we want to add a row. * @param factory * @return the added row. */ public Row addNestedRow(String hNodeId, RepFactory factory) { return getNode(hNodeId).getNestedTable().addRow(factory); } @Override public void prettyPrint(String prefix, PrintWriter pw, RepFactory factory) { pw.print(prefix + "__"); pw.println("/" + id); for (Node n : nodes.values()) { n.prettyPrint(prefix, pw, factory); } } // mariam public String toString() { String s = "ROW:\n"; for (Node n : nodes.values()) { s += n.toString(); } return s; } void addNodeToDataTable(HNode newHNode, Table table, RepFactory factory) { HTable ht = factory.getHTable(table.getHTableId()); if (ht.contains(newHNode)) { Node newNode = factory.createNode(newHNode.getId(), getWorksheetId()); addNode(newNode); } else { // We don't know where the nested table is, so we have to // try all of them. for (Node n : nodes.values()) { Table nestedTable = n.getNestedTable(); if (nestedTable != null) { nestedTable.addNodeToDataTable(newHNode, factory); } } } } public void addNestedTableToDataTable(HNode hNode, Table table, RepFactory factory) { Node node = getNode(hNode.getId()); if (node != null) { // This table does contain this hNode. Table nestedTable = factory.createTable(hNode.getNestedTable() .getId(), getWorksheetId()); node.setNestedTable(nestedTable, factory); // If the node has a value, we have to move the value to the // nestedTable given that we cannot have both. if (!node.getValue().isEmptyValue()) { logger.info("While adding nested table, found that column '" + factory.getColumnName(hNode.getId()) + "' has a value: '" + node.getValue().asString() + "'."); logger.info("Emptying value in node and trying to move it to the nested table."); nestedTable.addOrphanValue(node.getValue(), node.getHNodeId(), factory); } } else { // The node may be in one of the nested tables. We have to look for // it. for (Node n : nodes.values()) { Table nestedTable = n.getNestedTable(); if (nestedTable != null) { nestedTable.addNestedTableToDataTable(hNode, factory); } } } } @Override public boolean canReachNeighbor(String hNodeId) { return nodes.containsKey(hNodeId) || (belongsToTable.getNestedTableInNode() != null && belongsToTable .getNestedTableInNode().canReachNeighbor(hNodeId)); } @Override public Node getNeighbor(String hNodeId) { if (nodes.containsKey(hNodeId)) { return nodes.get(hNodeId); } else if (belongsToTable.getNestedTableInNode() != null) { return belongsToTable.getNestedTableInNode().getNeighbor(hNodeId); } return null; } @Override public Node getNeighborByColumnName(String columnName, RepFactory factory) { String hTableId = belongsToTable.getHTableId(); HTable hTable = factory.getHTable(hTableId); String hNodeId = hTable.getHNodeIdFromColumnName(columnName); if (null != hNodeId) { return getNeighbor(hNodeId); } else if (belongsToTable.getNestedTableInNode() != null) { return belongsToTable.getNestedTableInNode() .getNeighborByColumnName(columnName, factory); } return null; } public Node getNeighborWithNestedColumnByIndex(String hNodeId, RepFactory factory, String nestedColumnName, int index) { if (nodes.containsKey(hNodeId)) { Node nodeWithNestedColumn = nodes.get(hNodeId); Table nestedTable = nodeWithNestedColumn.getNestedTable(); if(nestedTable != null) { String [] nestedColumnPath = nestedColumnName.split("/"); String nestedHNodeId = factory.getHTable(nestedTable.getHTableId()).getHNodeIdFromColumnName(nestedColumnPath[0]); if (null != nestedHNodeId && nestedColumnPath.length ==1) { Row r = nestedTable.getRow(index); if(r != null) { return r.getNeighbor(nestedHNodeId); } } else { return nestedTable.getRow(0).getNeighborWithNestedColumnByIndex(nestedHNodeId, factory, nestedColumnName.substring(nestedColumnName.indexOf("/")+1), index); } } } return null; } public Node getNeighborByColumnNameWithNestedColumnByRowIndex(String columnName, RepFactory factory, String nestedColumnName, int index) { String hTableId = belongsToTable.getHTableId(); HTable hTable = factory.getHTable(hTableId); String hNodeId = hTable.getHNodeIdFromColumnName(columnName); if (null != hNodeId) { return getNeighborWithNestedColumnByIndex(hNodeId, factory, nestedColumnName, index); } else if (belongsToTable.getNestedTableInNode() != null) { return belongsToTable.getNestedTableInNode() .getNeighborByColumnNameWithNestedColumnByRowIndex(columnName, factory, nestedColumnName, index); } return null; } public boolean collectNodes(HNodePath path, Collection<Node> nodes, SuperSelection sel) { if(path == null || path.getFirst() == null) return false; Node n = getNode(path.getFirst().getId()); if (n == null) { return false; } // Check if the path has only one HNode if (path.getRest() == null || path.getRest().isEmpty()) { nodes.add(n); return true; } // Check if the node has a nested table HNodePath rest = path.getRest(); if (n.hasNestedTable()) { int numRows = n.getNestedTable().getNumRows(); if (numRows != 0) { List<Row> rowsNestedTable = n.getNestedTable().getRows(0, numRows, sel); if (rowsNestedTable != null && !rowsNestedTable.isEmpty()) { List<Row> rows = n.getNestedTable().getRows(0, 1, sel); if(!rows.isEmpty() && rows.get(0).getNode(rest.getFirst().getId()) != null) { return n.getNestedTable().collectNodes(path.getRest(), nodes, sel); } } } } if(n.getBelongsToRow().getNode(rest.getFirst().getId()) != null) { return n.getBelongsToRow().collectNodes(rest, nodes, sel); } if(n.getBelongsToRow().getBelongsToTable().getNestedTableInNode() != null) { return n.getBelongsToRow().getBelongsToTable().getNestedTableInNode().getBelongsToRow().collectNodes(rest, nodes, sel); } return false; } }