/* Copyright 2014 MITRE Corporation
*
* 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.
*/
package org.mitre.provenance.plusobject;
import org.mitre.provenance.EdgeMarking;
import org.mitre.provenance.surrogate.SignPost;
/**
* This class models an edge in a provenance graph. This class is ONLY for provenance edges
* <p>The type of a PLUSEdge <b>must always be</b> one of the enumerated strings in this class. For any other type of edge (bearing non-
* provenance semantics) use NonProvenanceEdge
* @see org.mitre.provenance.npe.NonProvenanceEdge
* @author moxious
*/
public class PLUSEdge extends AbstractDirectedEdge {
/** A marks edge indicates that one provenance object provides additional information about another. As an example, Taint objects mark what they taint */
public static final String EDGE_TYPE_MARKS = "marks";
/** A triggered edge goes between two invocations, indicating that the from end of the edge triggered the "to" end of the edge. */
public static final String EDGE_TYPE_TRIGGERED = "triggered";
/** A generated edge goes between an invocation and a data item, indicating that the invocation generated the data item */
public static final String EDGE_TYPE_GENERATED = "generated";
/** Input to goes between a data item and an invocation, denoting that the data was input to the invocation */
public static final String EDGE_TYPE_INPUT_TO = "input to";
/** Contributed is a mostly unspecified auxilary edge type that indicates one data item contributed to another (i.e. excerpting) */
public static final String EDGE_TYPE_CONTRIBUTED = "contributed";
/** Unspecified edges are meant for later revision; in general they should be avoided, but may be created in cases where it is known that a
* relationship exists between two objects, but when the nature of the relationship isn't known
*/
public static final String EDGE_TYPE_UNSPECIFIED = "unspecified";
/** The source/head/origin of the edge */
protected PLUSObject from;
/** The tail/end/termination point of the edge */
protected PLUSObject to;
/** The type of edge */
protected String type;
/** The workflow that this edge is a part of */
protected PLUSWorkflow workflow;
/**
* Create a new edge from one object to another, under the default workflow. The edge type will be chosen automatically, depending on
* the types of the incident objects.
* @param from
* @param to
*/
public PLUSEdge(PLUSObject from, PLUSObject to) {
this(from, to, PLUSWorkflow.DEFAULT_WORKFLOW);
}
/**
* Create a new PLUSEdge
* @param from the origin of the edge
* @param to the destination of the edge
* @param wf the workflow the edge belongs to. If null, the default workflow will be used.
* @param type the type of the edge; should be one of the edge types defined in this class.
*/
public PLUSEdge(PLUSObject from, PLUSObject to, PLUSWorkflow wf, String type) {
this(from, to, wf);
setType(type);
}
/**
* Create a new edge from one object to another, under the workflow specified. The edge type will be chosen automatically, depending on
* the types of the incident objects.
* @param from
* @param to
*/
public PLUSEdge(PLUSObject from, PLUSObject to, PLUSWorkflow wf) {
this.from = from;
this.to = to;
if(wf == null) {
log.warning("Attempt to use null workflow in creating PLUSEdge");
this.workflow = PLUSWorkflow.DEFAULT_WORKFLOW;
} else this.workflow = wf;
setType(EDGE_TYPE_CONTRIBUTED);
setFromMarking(EdgeMarking.SHOW);
setToMarking(EdgeMarking.SHOW);
setSourceHints(SignPost.SRC_HINTS_LOCAL);
if(from.isInvocation() && to.isInvocation()) setType(EDGE_TYPE_TRIGGERED);
if(from.isDataItem() && to.isInvocation()) setType(EDGE_TYPE_INPUT_TO);
if(from.isInvocation() && to.isDataItem()) setType(EDGE_TYPE_GENERATED);
if(from.isDataItem() && to.isDataItem()) setType(EDGE_TYPE_CONTRIBUTED);
} // End PLUSEdge
public PLUSEdge clone() {
PLUSEdge copy = new PLUSEdge(getFrom(), getTo(), getWorkflow(), getType());
copy.setFromMarking(getFromMarking());
copy.setToMarking(getToMarking());
copy.setSourceHints(getSourceHints());
return copy;
} // End clone
/**
* @param type
* @return true if a given type is one of the enumerated provenance edge types; false otherwise.
*/
public static boolean isProvenanceEdgeType(String type) {
return EDGE_TYPE_TRIGGERED.equals(type) ||
EDGE_TYPE_GENERATED.equals(type) ||
EDGE_TYPE_INPUT_TO.equals(type) ||
EDGE_TYPE_CONTRIBUTED.equals(type) ||
EDGE_TYPE_UNSPECIFIED.equals(type) ||
EDGE_TYPE_MARKS.equals(type);
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((from == null) ? 0 : from.hashCode());
result = prime * result
+ ((to == null) ? 0 : to.hashCode());
result = prime * result
+ ((workflow == null) ? 0 : workflow.hashCode());
result = prime * result
+ ((type == null) ? 0 : type.hashCode());
return result;
}
public boolean equals(Object other) {
if(!(other instanceof PLUSEdge) || other == null) return false;
return ((PLUSEdge)other).getFrom().equals(getFrom()) &&
((PLUSEdge)other).getTo().equals(getTo());
}
public String toString() { return new String("<PLUSEdge (" + getType() + ") " + getFrom() + " -> " + getTo() + ">"); }
public boolean isBLINGOf(PLUSObject obj) {
return getTo().equals(obj.getId());
}
public boolean isFLINGOf(PLUSObject obj) {
return getFrom().equals(obj.getId());
}
public PLUSObject getFrom() { return from; }
public PLUSObject getTo() { return to; }
public String getType() { return type; }
public PLUSWorkflow getWorkflow() { return workflow; }
public void setWorkflow(PLUSWorkflow wf) { this.workflow = wf; }
public void setFrom(PLUSObject from) { this.from = from; }
public void setTo(PLUSObject to) { this.to = to; }
public void setType(String type) {
if(!isProvenanceEdgeType(type)) {
log.severe("Edge " + this + ": attempt to set edge type to non-provenance edge type '" + type + "': using 'unspecified' instead.");
this.type = EDGE_TYPE_UNSPECIFIED;
} else {
this.type = type;
} // End else
} // End setType
public SignPost getSourceHints() { return this.srcHints; }
public void setSourceHints(SignPost sp) { this.srcHints = sp; }
} // End PLUSEdge