/******************************************************************************* * Copyright (c) 2014 EURA NOVA. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v2.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * Aldemar Reynaga - initial API and implementation * Salim Jouili - initial API and implementation ******************************************************************************/ package com.steffi.model; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; import com.steffi.storage.CellSequence; import com.steffi.storage.CellTransaction; import com.steffi.storage.CellTransactionThread; import com.steffi.storage.EdgeAddressesUpdater; import com.steffi.storage.StorageTools; /** * @author Aldemar Reynaga * Defines a vertex based on the basic cell structure */ public class SteffiVertex extends Cell { /** * */ private static final long serialVersionUID = -7593264602525689457L; private SteffiIndexedEdges[] edgesAddresses; private List<SteffiEdge> edges; public SteffiVertex(Long id, String name, boolean transactionSupport) { super(id, name); cellType = CellType.VERTEX; edges = new ArrayList<SteffiEdge>(); edgesAddresses = new SteffiIndexedEdges[SteffiGraph.getInstance().getNumberOfMembers()]; if (transactionSupport) CellTransactionThread.get().createCell(this); } public SteffiVertex(Long id, String name) { this(id, name, true); } protected SteffiVertex(Long id, String cellType, String name, SteffiGraph parentGraph, List<SteffiEdge> edges) { super(id, name); this.cellType = CellType.VERTEX; this.edges = edges; } public SteffiIndexedEdges[] getEdgeAddresses() { return edgesAddresses; } @Override public void trimToSize() { super.trimToSize(); ((ArrayList)edges).trimToSize(); for (SteffiIndexedEdges em : edgesAddresses) if (em != null) em.trimToSize(); } private SteffiIndexedEdges getEdgeMap(String address) { int addressIndex = SteffiGraph.getInstance().getMemberIndex(address); return edgesAddresses[addressIndex]; } public void addEdgeAddress(SteffiEdge edge, String address) { SteffiIndexedEdges adrEdges; int addressIndex = SteffiGraph.getInstance().getMemberIndex(address); adrEdges = edgesAddresses[addressIndex]; if (adrEdges == null) { adrEdges = new SteffiMapEdges(); edgesAddresses[addressIndex] = adrEdges; } adrEdges.addEdge(edge); } public void removeEdgeAddress(SteffiEdge edge, String address) { int addressIndex = SteffiGraph.getInstance().getMemberIndex(address); edgesAddresses[addressIndex].remove(edge); } public SteffiEdge addEdge(SteffiVertex vertex, boolean isDirected, String name) { SteffiGraph.getInstance().validateEdgeName(name); long edgeCellId = CellSequence.getNewCellId(); SteffiEdge relOut = new ExtSteffiEdge(this.getId(), vertex.getId(), (isDirected)?EdgeType.OUT:EdgeType.UNDIRECTED, name, edgeCellId); SteffiEdge relIn = new ExtSteffiEdge(vertex.getId(), this.getId(), (isDirected)?EdgeType.IN:EdgeType.UNDIRECTED, name, edgeCellId); this.edges.add(relOut); EdgeAddressesUpdater.updateEdgeAddress(this, relOut); vertex.edges.add(relIn); EdgeAddressesUpdater.updateEdgeAddress(vertex, relIn); CellTransactionThread.get().addEdge(this, relOut); CellTransactionThread.get().addEdge(vertex, relIn); return relOut; } public void addImgEdge(SteffiEdge imgEdge) { edges.add(imgEdge); } public SteffiEdge addPartialEdge(long vertexId, EdgeType edgeType, String name) { return addPartialEdge(vertexId, edgeType, name, true); } public SteffiEdge addPartialEdge(long vertexId, EdgeType edgeType, String name, boolean transactionSupport) { SteffiGraph.getInstance().validateEdgeName(name); long edgeCellId = CellSequence.getNewCellId(); SteffiEdge edge = new ExtSteffiEdge(this.getId(), vertexId, edgeType, name, edgeCellId); this.edges.add(edge); EdgeAddressesUpdater.updateEdgeAddress(this, edge); if (transactionSupport) CellTransactionThread.get().addEdge(this, edge); return edge; } public void markNeighborFlags(int addressIndex, long destId, String name) { for (SteffiEdge extEdge : edgesAddresses[addressIndex].getEdgesByName(name)) if (extEdge.getDestCellId() == destId) ((ExtSteffiEdge)extEdge).setNeighborFlag((byte) 1); } public SteffiEdge getEdge(long edgeId) { for (SteffiEdge edge : edges) if (edge.getId() == edgeId) return edge; return null; } public SteffiEdge getEdge(long destId, EdgeType edgeType, String name) { return getEdge(destId, edgeType, name, null); } private SteffiEdge searchEdgeByDestCellId(Collection<SteffiEdge> edgeCollection, long destId) { if (edgeCollection != null) { for (SteffiEdge edge : edgeCollection) if (edge.getDestCellId() == destId ) return edge; } return null; } public SteffiEdge getEdge(long destId, EdgeType edgeType, String name, Integer addressIndex) { if (addressIndex != null) { return searchEdgeByDestCellId(edgesAddresses[addressIndex].getEdgesByTypeName(edgeType, name), destId); } for (SteffiIndexedEdges edgeMap : edgesAddresses) { if (edgeMap != null) { SteffiEdge searchedEdge = searchEdgeByDestCellId(edgeMap.getEdgesByTypeName(edgeType, name), destId); if (searchedEdge != null) return searchedEdge; } } return null; } public void remove() { SteffiEdge[] edgesToRemove = new SteffiEdge[edges.size()]; for (int i=0; i<edges.size(); i++) edgesToRemove[i] = edges.get(i); for (SteffiEdge edge : edgesToRemove) removeEdge(edge); CellTransactionThread.get().removeCell(this); } public void removeEdge(SteffiEdge edge) { if (!SteffiEdge.removeEdgeFromCollection(edge, this.edges)) throw new RuntimeException("The edge with id " + edge.getId() + " does not exist in vertex " + this.getId()); this.removeEdgeAddress(edge, StorageTools.getCellAddress(edge.getDestCellId())); SteffiVertex destVertex = (SteffiVertex) SteffiGraph.getInstance().retrieveCell(edge.getDestCellId()); int addressIndex = SteffiGraph.getInstance().getMemberIndex(StorageTools.getCellAddress(edge.getSourceCellId())); SteffiEdge invertedEdge = destVertex.getEdge(edge.getSourceCellId(), EdgeType.invertType(edge.getEdgeType()), getName(), addressIndex); SteffiEdge.removeEdgeFromCollection(invertedEdge, destVertex.edges); destVertex.removeEdgeAddress(invertedEdge, StorageTools.getCellAddress(invertedEdge.getSourceCellId())); CellTransaction cellTransaction = CellTransactionThread.get(); cellTransaction.removeEdge(this, edge); cellTransaction.removeEdge(destVertex, invertedEdge); } public List<SteffiEdge> getEdges() { return edges; } public Iterable<SteffiEdge> getEdges(EdgeType edgeType) { return getEdges(edgeType, new String[0]); } public List<SteffiEdge> getEdgesByType(EdgeType edgeType) { List<SteffiEdge> unionEdges = new ArrayList<SteffiEdge>(); Collection<SteffiEdge> tempEdges = null; for (SteffiIndexedEdges em : edgesAddresses) { if (em != null) { tempEdges = em.getEdgesByType(edgeType); if (tempEdges != null) unionEdges.addAll(tempEdges); } } return unionEdges; } public List<SteffiEdge> getEdgesByTypeName(EdgeType edgeType, String name) { List<SteffiEdge> unionEdges = new ArrayList<SteffiEdge>(); Collection<SteffiEdge> tempEdges = null; for (SteffiIndexedEdges em : edgesAddresses) { if (em != null) { tempEdges = em.getEdgesByTypeName(edgeType, name); if (tempEdges != null) unionEdges.addAll(tempEdges); } } return unionEdges; } public Iterable<SteffiEdge> getEdges(final EdgeType edgeType, final String labels[]) { return new Iterable<SteffiEdge>() { @Override public Iterator<SteffiEdge> iterator() { if (labels.length == 0) { return getEdgesByType(edgeType).iterator(); } else { List<SteffiEdge> list = new LinkedList<SteffiEdge>(); for (String label : labels) list.addAll(getEdgesByTypeName(edgeType, label)); return list.iterator(); } } }; } public String toString() { String string = ""; string = super.toString(); SteffiGraph graph = SteffiGraph.getInstance(); if (!edges.isEmpty()) { string += "\n\tEDGES: "; for (SteffiEdge edge : edges) { string += "\n\t " + edge.toString(); } for (Entry<String, Integer> memberEntry : graph.getMemberIndexes().entrySet()) { string += "\n\t" + memberEntry.getKey() + ":"; if (edgesAddresses[memberEntry.getValue()] != null) { for (SteffiEdge edge : edgesAddresses[memberEntry.getValue()].getAllEdges()) string += "\n\t\t" + edge.toString(); } } } return string; } public List<SteffiEdge> getEdgesByAddress(String address) { return getEdgeMap(address).getAllEdges(); } public SteffiIndexedEdges getEdgeMapByAddress(String address) { return getEdgeMap(address); } public Cell clone() { SteffiVertex clon = (SteffiVertex) super.clone(); for (SteffiEdge edge : this.edges) { SteffiEdge clonedEdge = (SteffiEdge) edge.clone(); clon.edges.add(clonedEdge); EdgeAddressesUpdater.updateEdgeAddress(clon, clonedEdge); } return clon; } }