package de.tum.pip.structures; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class PIPStruct { // counter for the unique data and container ids private int dataIDCounter = 0; private int containerIDCounter = 0; // the container set of the GUSM model private List<PIPContainer> containerSet; // the data set of the GUSM model private List<String> dataSet; // the storage set of the GUSM model [Container.identifier -> // List[Data.identifier]] private Map<Integer, Set> dataContainerSet; // the alias set of the GUSM model [Container.identifier -> // List[Container.identifier]] private Map<Integer, Set> aliasSet; // the naming set of the GUSM model [name -> List[Container.identifier]] private Map<PIPName, Integer> namingSet; // ToDo: Track past events (all persistent eventTraces) // private Map<String, Stack<PDPEvent>> eventTraces; /** * */ public PIPStruct() { // TODO: Linked List May Be Better... ?? containerSet = new ArrayList<PIPContainer>(); dataSet = new ArrayList<String>(); // TODO: Is HashMap, SortedMap or TreeMap? dataContainerSet = new HashMap<Integer, Set>(); aliasSet = new HashMap<Integer, Set>(); namingSet = new HashMap<PIPName, Integer>(); // ToDo: Track past events // eventTraces = new Map<String, Stack<PDPEvent>>(); } // Data set management functions: /** * Adds a new data item to the data set, or create a new one if a null data * item was passed to this function. */ public String addData(String data) { if (dataSet.contains(data)) return "error"; // if (data == null) data = new PIPData(); if (data == null) { data = "D" + dataIDCounter; dataIDCounter++; } dataSet.add(data); return data; } /** * Removes a data item form the data set. */ public boolean removeData(String data) { // if ((data == null) | !(dataSet.contains(data))) return false; if (!dataSet.contains(data)) return false; dataSet.remove(data); return true; } /** * Returns the data item identified by the passed data ID. */ public String getDataByID(String identifier) { return dataSet.get(dataSet.indexOf(identifier)); } /** * Returns true if the data set includes a data item with the passed data * ID, false otherwise. */ public boolean hasDataByID(String identifier) { if (getDataByID(identifier) != null) { return true; } else { return false; } } // Container set management functions: /** * Adds a new data container to the container set, or create a new one if a * null container was passed to this function. */ public int addContainer(PIPContainer container) { if (containerSet.contains(container)) return -1; if (container == null) container = new PIPContainer(); container.identifier = containerIDCounter; containerSet.add(container); containerIDCounter++; return containerIDCounter - 1; } /** * Removes the specified container from the container set. */ public boolean removeContainer(PIPContainer container) { if (!(containerSet.contains(container))) return false; containerSet.remove(container); // ToDo: remove also entries in dataContainer list return true; } /** * Removes the container, identified by the provided container id. */ public boolean removeContainer(int contID) { PIPContainer container = containerSet.get(contID); for (int i = containerSet.size(); i >= 0; i--) { if (container.identifier == containerSet.get(i).identifier) { containerSet.remove(i); } } return true; } /** * Empties the container (= its containing data items), specified via the * passed container ID. */ public boolean emptyContainer(int contID) { if (!dataContainerSet.containsKey(contID)) return false; dataContainerSet.get(contID).clear(); return true; } /** * Returns the data container, referrenced by the provided container ID. */ public PIPContainer getContainerByID(int contID) { return containerSet.get(contID); } /** * Returns true if the container set includes a data container with the * passed container ID, false otherwise. */ public boolean hasContainerByID(int contID) { if (getContainerByID(contID) == null) { return false; } else { return true; } } // Alias set manipulation functions: /** * Adds an alias relation from a container to a container. */ public boolean addAlias(int from, int to) { if (aliasSet.containsKey(from)) { aliasSet.get(from).add(to); } else { Set newList = new HashSet(); newList.add(to); aliasSet.put(from, newList); } return true; } /** * Remove the alias relation identified by the tuple (from, to). */ public boolean removeAlias(int from, int to) { if (aliasSet.containsKey(from)) { aliasSet.get(from).remove(to); return true; } else { return false; } } /** * Returns all aliases of the container with the passed container ID. */ public Set getAliasByID(Object contID) { if (aliasSet.containsKey(contID)) { return aliasSet.get(contID); } else { return new HashSet(); } } /** * Returns the reflexive, transitive closure of the alias function for * container with ID contID. */ public Set<Integer> getAliasClosureByID(int contID) { Set closure = getAliasClosure(contID, new HashSet()); // add self to set ==> reflexive closure.add(contID); return closure; } /** * Removes all aliases that start from the container with container ID = * from. */ public boolean removeAllAliasesFrom(int from) { if (aliasSet.containsKey(from)) { aliasSet.get(from).clear(); return true; } else { return false; } } /** * Removes all aliases that end in the container with container ID = to. */ public boolean removeAllAliasesTo(int to) { if (getAliasesTo(to).size() > 0) { for (Set entry : aliasSet.values()) { if (entry.contains(to)) { aliasSet.remove(to); } } return true; } else { return false; } } /** * Returns all aliases that go to the container with the passed container ID * to. */ public Set getAliasesTo(int to) { Set result = new HashSet(); for (Entry<Integer, Set> entry : aliasSet.entrySet()) { if (entry.getValue().contains(to)) result.add(entry.getKey()); } return result; } /** * Calculates the transitive reflexive closure of the alisa function. */ private Set getAliasClosure(int contID, Set oldSet) { Set<Integer> closure = getAliasByID(contID); if (closure.size() == oldSet.size()) { return closure; } Set tempClosure = new HashSet(); for (int cont : closure) { tempClosure.addAll(getAliasClosure(cont, closure)); } closure.addAll(tempClosure); return closure; } // Naming set manipulation functions: /** * Adds an entry to the naming mapping for container contID, with the * naming/representation name. */ public boolean addName(PIPName name, int contID) { if (name == null || name.name == "") return false; namingSet.put(name, contID); return true; } /** * Removes the naming/representation name from the naming set. */ public boolean removeName(PIPName name) { if (name == null) return false; if (namingSet.containsKey(name)) { namingSet.remove(name); return true; } else { return false; } } /** * Returns the container that is referenced by the naming name. */ public int getContainerByName(PIPName name) { if (name == null) return -1; for (PIPName nm : namingSet.keySet()) { if ((nm.name.equals(name.name)) && (nm.PID == name.PID)) return namingSet.get(nm); } return -1; } /** * Returns the container that is referenced by the naming name. The search * is done in a less strict way, already matching if a name only partially * fits an entry of the naming mapping. */ public int getContainerByNameRelaxed(PIPName name) { if (name == null) return -1; for (PIPName nm : namingSet.keySet()) { if ((nm.name.contains(name.name)) && (nm.PID == name.PID)) { return namingSet.get(nm); } } return -1; } /** * Return all namings that refer to a container wit ID contID. */ public List<PIPName> getAllNames(int contID) { // TODO: Linked List May Be Better... ?? List<PIPName> result = new ArrayList<PIPName>(); if (namingSet.containsValue(contID)) { for (Entry<PIPName, Integer> entry : namingSet.entrySet()) { if (entry.getValue() == contID) result.add(entry.getKey()); } } return result; } /** * Returns all representations that correspond to a process with ID PID. */ public List<PIPName> getAllNamingsFrom(int PID) { // TODO: Linked List May Be Better... ?? List<PIPName> result = new ArrayList<PIPName>(); for (Entry<PIPName, Integer> entry : namingSet.entrySet()) { if (entry.getKey().PID == PID) result.add(entry.getKey()); } return result; } // DataContainer mapping functions: /** * Adds an new mapping between the data container containerID and the data * item dataID. */ public boolean addDataContainer(int containerID, String dataID) { if (dataContainerSet.containsKey(containerID)) { dataContainerSet.get(containerID).add(dataID); } else { Set newDataSet = new HashSet(); newDataSet.add(dataID); dataContainerSet.put(containerID, newDataSet); } return true; } /** * Removes an entry from the data-container mapping. */ public boolean removeDataContainer(int dataID, int containerID) { if (dataContainerSet.containsKey(containerID)) { dataContainerSet.get(containerID).remove(dataID); return true; } return false; } /** * Returns all data items that are stored in the specified container. */ public Set getDataInContainer(int containerID) { Set result = new HashSet(); if (dataContainerSet.containsKey(containerID)) { result = dataContainerSet.get(containerID); } return result; } /** * Returns all containers that contain a data item with ID dataID. */ public Set getContainerOfData(String dataID) { Set result = new HashSet(); for (Entry<Integer, Set> entry : dataContainerSet.entrySet()) { if (entry.getValue().contains(dataID)) result.add(entry.getKey()); } return result; } /** * Adds a list of data items to a container. */ public boolean addDataContainerList(int contID, Set dataList) { if (dataList == null) return false; if (dataContainerSet.containsKey(contID)) { dataContainerSet.get(contID).addAll(dataList); } else { dataContainerSet.put(contID, dataList); } return true; } /** * Returns the formated status of all mappings within one string for * debugging purposes. */ public String printModel() { String dataSetString = ""; String containerSetString = ""; String aliasSetString = ""; String namingSetString = ""; String dataContainerSetString = ""; String combinedModel = ""; for (String data : dataSet) { dataSetString += data + "|"; } // delete the last | if (dataSetString != "") dataSetString = dataSetString.substring(0, dataSetString.length() - 1); for (PIPContainer container : containerSet) { containerSetString += container.identifier + "|"; } // delete the last | if (containerSetString != "") containerSetString = containerSetString.substring(0, containerSetString.length() - 1); for (Entry<Integer, Set> alias : aliasSet.entrySet()) { aliasSetString += "ContainerID=" + alias.getKey() + " -> ContainerIDs=(" + Arrays.deepToString(alias.getValue().toArray()) + ")\n"; } for (Entry<PIPName, Integer> name : namingSet.entrySet()) { namingSetString += "Name=" + name.getKey().PID + "x" + name.getKey().name + " -> ContainerID=" + name.getValue() + "\n"; } for (Entry<Integer, Set> dataContainer : dataContainerSet.entrySet()) { dataContainerSetString += "ContainerID=" + dataContainer.getKey() + " ===> DataIDs=(" + Arrays.deepToString(dataContainer.getValue().toArray()) + ")\n"; } for (Entry<PIPName, Integer> name : namingSet.entrySet()) { combinedModel += "Name=" + name.getKey().PID + "x" + name.getKey().name + " -> ContainerID=" + name.getValue() + " -> DataIDs=" + getDataInContainer(name.getValue()).toString() + "\n"; } String model = "DataSet: [" + dataSetString + "]\n++++\n" + "ContainerSet: [" + containerSetString + "]\n++++\n" + "AliasSet: \n[\n" + aliasSetString + "]\n++++\n" + "NamingSet: \n[\n" + namingSetString + "]\n++++\n" + "DataContainerSet: \n[\n" + dataContainerSetString + "]\n++++\n" + "Combined: \n[\n" + combinedModel + "]\n"; return model; } }