de.uni.freiburg.iig.telematik.sepia.petrinet.abstr.AbstractPNNode Maven / Gradle / Ivy
/*
* Copyright (c) 2015, IIG Telematics, Uni Freiburg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the disclaimer
* below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of IIG Telematics, Uni Freiburg nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BELIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.uni.freiburg.iig.telematik.sepia.petrinet.abstr;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.invation.code.toval.validate.ParameterException;
import de.invation.code.toval.validate.Validate;
import de.uni.freiburg.iig.telematik.sepia.util.PNUtils;
import java.util.HashMap;
import java.util.Map;
/**
* This abstract class subsumes common properties of Petri net places and transitions.
* Petri net places and transitions are defined in the classes {@link AbstractPlace} and {@link AbstractTransition}
* whoch both inherit from {@link AbstractPNNode}.
* In detail, these properties are:
*
*
* - Name: The name of the node (unique).
* - Label: The label of the node (not unique).
* - Relations: Incoming and outgoing relations to other nodes.
* This allows nodes to notify other nodes about state changes.
*
*
* Besides basic properties, this class provides further functionality,
* such as extraction of child- and parent-nodes and source/drain properties.
*
* @author Thomas Stocker
*
* @param Relation Type (inherits from AbstractFlowRelation)
* @see AbstractFlowRelation
* @see AbstractPlace
* @see AbstractTransition
*/
public abstract class AbstractPNNode, ? extends AbstractTransition, ?>> implements Serializable{
private static final long serialVersionUID = -809201554674739116L;
protected final String toStringFormat = "%s[%s]";
/**
* Incoming relations of the Petri net node.
*/
protected Map incomingRelations = new HashMap<>();
/**
* Outgoing relations of the Petri net node.
*/
protected Map outgoingRelations = new HashMap<>();
/**
* The name of the Petri net node.
* Node names must be unique within a Petri net and are used for distinction.
* Once added to a Petri net, the name property should not be changed to avoid conflicts.
*/
protected final String name;
/**
* The label of the Petri net node.
* The label is not unique and can be altered, whenever convenient.
*/
protected String label;
private PNNodeType type = null;
//------- Constructors ---------------------------------------------------------------------------
// protected AbstractPNNode(PNNodeType type){
// super();
// this.type = type;
// }
/**
* Creates a new Petri net node, using the given name.
* Ba default, the label of the node equals the name.
* @param type The type of the Petri net node.
* @param name The name for the Petri net node.
* @throws ParameterException If the given name is null.
*/
public AbstractPNNode(PNNodeType type, String name){
this(type, name, name);
this.type = type;
}
/**
* Creates a new Petri net node, using the given name and label.
* @param type The type of the Petri net node.
* @param name The name for the Petri net node. It must start with a
* character of the range [a-zA-Z] and must only contain alphanumerical
* characters and the symbols -_.:.
* @param label The label for the Petri net node.
* @throws ParameterException If some parameters are null.
*/
public AbstractPNNode(PNNodeType type, String name, String label){
Validate.notNull(name);
Validate.notNull(label);
PNUtils.validateElementName(name);
this.name = name;
setLabel(label);
this.type = type;
}
//------- Basic properties -----------------------------------------------------------------------
/**
* Returns the name of the Petri net node.
* @return The name of the Petri net.
*/
public String getName(){
return name;
}
// /**
// * Sets the name of the Petri net node.
// * Implementing classes must make sure, that the net does not contain other nodes with the same name.
// * @param name New name for the Petri net node.
// * @throws ParameterException If the given name is null.
// */
// protected abstract void setName(String name);
/**
* Returns the label of the Petri net node.
* @return The label of the Petri net node.
*/
public String getLabel() {
return label;
}
/**
* Sets the label of the Petri net node.
* @param label New label for the Petri net node.
* @throws ParameterException If the given label is null.
*/
public final void setLabel(String label){
Validate.notNull(label);
this.label = label;
}
/**
* Indicates if the Petri net node is a source, i.e.
* it has outgoing relations, but no incoming relations.
* @return true if the node is a source;
* false otherwise.
*/
public boolean isSource(){
return incomingRelations.isEmpty() && !outgoingRelations.isEmpty();
}
/**
* Indicates if the Petri net node is a drain, i.e.
* it has incoming relations, but no outgoing relations.
* @return true if the node is a drain;
* false otherwise.
*/
public boolean isDrain(){
return !incomingRelations.isEmpty() && outgoingRelations.isEmpty();
}
/**
* Returns all parent nodes of this Petri net node.
* @return A set of all parent nodes.
*/
@SuppressWarnings("unchecked")
public Set> getParents(){
Set> result = new HashSet<>();
for(E relation: incomingRelations.values()){
result.add((AbstractPNNode) relation.getSource());
}
return result;
}
/**
* Returns all child nodes of this Petri net node.
* @return A set of all child nodes.
*/
@SuppressWarnings("unchecked")
public Set> getChildren(){
Set> result = new HashSet<>();
for(E relation: outgoingRelations.values()){
result.add((AbstractPNNode) relation.getTarget());
}
return result;
}
//------- Relations ------------------------------------------------------------------------------
/**
* Returns the incoming relations of the Petri net node.
* @return A list of all incoming relations.
*/
public List getIncomingRelations(){
return new ArrayList<>(incomingRelations.values());
}
/**
* Returns the outgoing relations of the Petri net node.
* @return A list of all outgoing relations.
*/
public List getOutgoingRelations(){
return new ArrayList<>(outgoingRelations.values());
}
/**
* Adds an incoming relation to the Petri net node.
* This method is protected, since adding relations to nodes should be done by the
* corresponding Petri net only.
* @param relation The incoming relation to add.
* @return true if the relation was added;
* false otherwise.
* @throws ParameterException If the given relation is null.
*/
protected boolean addIncomingRelation(E relation){
Validate.notNull(relation);
return (incomingRelations.put(relation.getName(), relation)) == null;
}
/**
* Adds an outgoing relation to the Petri net node.
* This method is protected, since adding relations to nodes should be done by the
* corresponding Petri net only.
* @param relation The outgoing relation to add.
* @return true if the relation was added;
* false otherwise.
* @throws ParameterException If the given relation is null.
*/
protected boolean addOutgoingRelation(E relation){
Validate.notNull(relation);
return (outgoingRelations.put(relation.getName(), relation)) == null;
}
/**
* Removes the given relation from the Petri net node.
* The method checks itself if the relation is incoming or outgoing.
* @param relation The relation to remove.
* @return true if the relation was removed;
* false otherwise.
* @throws ParameterException If the given relation is null.
*/
protected boolean removeRelation(E relation){
Validate.notNull(relation);
if(removeIncomingRelation(relation))
return true;
return removeOutgoingRelation(relation);
}
/**
* Removes the given relation from the set of incoming relations.
* @param relation The incoming relation to remove.
* @return true if the relation was removed;
* false otherwise.
* @throws ParameterException If the given relation is null.
*/
protected boolean removeIncomingRelation(E relation){
Validate.notNull(relation);
return (incomingRelations.remove(relation.getName())) != null;
}
/**
* Removes the given relation from the set of outgoing relations.
* @param relation The outgoing relation to remove.
* @return true if the relation was removed;
* false otherwise.
* @throws ParameterException If the given relation is null.
*/
protected boolean removeOutgoingRelation(E relation){
Validate.notNull(relation);
return (outgoingRelations.remove(relation.getName())) != null;
}
/**
* Returns the relation from the given Petri net node leading to this node.
* The method checks if there is an incoming relation with this property.
* @param Type of the node, subclass of \@link AbstractPNNode}.
* @param node The source node of the relation of interest.
* @return The incoming relation leading from the given node to this node;
* null if there is no such incoming relation.
* @throws ParameterException If the given node is null.
*/
public > E getRelationFrom(N node){
Validate.notNull(node);
for(E incomingRelation: incomingRelations.values()){
if(incomingRelation.getSource().equals(node)){
return incomingRelation;
}
}
return null;
}
/**
* Returns the relation from this node leading to the given Petri net node.
* The method checks if there is an outgoing relation with this property.
* @param Type of the node, subclass of \@link AbstractPNNode}.
* @param node The target node of the relation of interest.
* @return The outgoing relation leading from this node to the given node;
* null if there is no such outgoing relation.
* @throws ParameterException If the given node is null.
*/
public > E getRelationTo(N node){
Validate.notNull(node);
for(E outgoingRelation: outgoingRelations.values()){
if(outgoingRelation.getTarget().equals(node)){
return outgoingRelation;
}
}
return null;
}
/**
* Checks if there is an outgoing relation leading to the given Petri net node.
* @param Type of the node, subclass of \@link AbstractPNNode}.
* @param node The node of interest.
* @return true if there is an outgoing relation to the given node;
* false otherwise.
* @throws ParameterException If the given node is null.
*/
public > boolean containsRelationTo(N node){
return getRelationTo(node) != null;
}
/**
* Checks if there is an incoming relation from the given Petri net node.
* @param Type of the node, subclass of \@link AbstractPNNode}.
* @param node The node of interest.
* @return true if there is an incoming relation from the given node;
* false otherwise.
* @throws ParameterException If the given node is null.
*/
public > boolean containsRelationFrom(N node){
return getRelationFrom(node) != null;
}
protected PNNodeType getPNNodeType() {
return type;
}
protected void setType(PNNodeType type) {
this.type = type;
}
public int degree(){
return outgoingRelations.size() + incomingRelations.size();
}
public boolean isTransition(){
return type.equals(PNNodeType.TRANSITION);
}
public boolean isPlace(){
return type.equals(PNNodeType.PLACE);
}
//------- HashCode and Equals -------------------------------------------------------------------
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((label == null) ? 0 : label.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((toStringFormat == null) ? 0 : toStringFormat.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
@SuppressWarnings("rawtypes")
AbstractPNNode other = (AbstractPNNode) obj;
// if (incomingRelations == null) {
// if (other.incomingRelations != null) {
// return false;
// }
// } else if (!incomingRelations.equals(other.incomingRelations)) {
// if (incomingRelations.size() == other.incomingRelations.size()) {
// for (E incomingRelation : incomingRelations) {
// if (!other.incomingRelations.contains(incomingRelation)) {
// return false;
// }
// }
// return true;
// }
// return false;
// }
if (label == null) {
if (other.label != null) {
return false;
}
} else if (!label.equals(other.label)) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
// if (outgoingRelations == null) {
// if (other.outgoingRelations != null) {
// return false;
// }
// } else if (!outgoingRelations.equals(other.outgoingRelations)) {
// if (outgoingRelations.size() == other.outgoingRelations.size()) {
// for (E outgoingRelation : outgoingRelations) {
// if (!other.outgoingRelations.contains(outgoingRelation)) {
// return false;
// }
// }
// return true;
// }
// return false;
// }
if (toStringFormat == null) {
if (other.toStringFormat != null) {
return false;
}
} else if (!toStringFormat.equals(other.toStringFormat)) {
return false;
}
if (type != other.type) {
return false;
}
return true;
}
@Override
public AbstractPNNode clone() {
AbstractPNNode result = newInstance(getName());
result.setLabel(getLabel());
result.setType(getPNNodeType());
// for (E incomingRelation: getIncomingRelations())
// result.addIncomingRelation(incomingRelation);
// for (E outgoingRelation: getOutgoingRelations())
// result.addOutgoingRelation(outgoingRelation);
// -> Is done in AbstractPetriNet.clone()
return result;
}
//------- toString -------------------------------------------------------------------------------
@Override
public String toString() {
return String.format(toStringFormat, name, label);
}
protected abstract AbstractPNNode newInstance(String name);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy