/* 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.surrogate;
import java.util.Hashtable;
import org.mitre.provenance.EdgeMarking;
import org.mitre.provenance.plusobject.PLUSEdge;
import org.mitre.provenance.plusobject.PLUSObject;
/**
* Wrapper class for a surrogate, with a little extra magic.
* Surrogates in PLUS consist of the following: (1) An optional SignPost, indicating where the user can get
* more information. (2) An (optionally populated) surrogate quality data structure, containing extra
* hints (such as that the surrogate incomplete). (3) a set of "edge markings".
* <p>Edge markings have to do with how an individual surrogate interacts with the broader lineage DAG. By using
* edge markings, surrogates can indicate that edges to and from them should not be shown, or should be inferred.
* Surrogates can either specify each edge individually on a case-by-case basis, or they can specify an "edge policy",
* which has the effect of always hiding/showing/inferring edges.
* @see SurrogateGeneratingFunction#generateSurrogate(PLUSObject, org.mitre.provenance.user.User)
* @author moxious
*/
public class SurrogateDetail {
protected SurrogateQuality quality;
protected SignPost signpost;
protected int edgePolicy;
protected EdgeVoter voter = null;
/** Use this policy to vote on edges on a case-by-case basis.
* @see SurrogateDetail#addEdgeMarking(String, EdgeMarking)
* @see SurrogateDetail#setEdgePolicy(int)
*/
public static final int EDGE_POLICY_INDIVIDUAL = 0;
/** Use this policy to mark all edges as hide.
* @see SurrogateDetail#setEdgePolicy(int)
*/
public static final int EDGE_POLICY_HIDE_ALL = 1;
/** Use this policy to mark all edges as show.
* @see SurrogateDetail#setEdgePolicy(int)
*/
public static final int EDGE_POLICY_SHOW_ALL = 2;
/** Use this policy to mark all edges as infer.
* @see SurrogateDetail#setEdgePolicy(int)
*/
public static final int EDGE_POLICY_INFER_ALL = 3;
/**
* Use this policy to mark incoming edges infer, and outgoing edges visible.
* @see SurrogateDetail#setEdgePolicy(int)
*/
public static final int EDGE_POLICY_IN_INFER_OUT_VISIBLE = 4;
/**
* Use this policy to mark incoming edges visible, and outgoing edges infer.
* @see SurrogateDetail#setEdgePolicy(int)
*/
public static final int EDGE_POLICY_IN_VISIBLE_OUT_INFER = 5;
/**
* Use this policy to mark edges through the use of a voter.
* @see SurrogateDetail#setEdgePolicy(int)
*/
public static final int EDGE_POLICY_USE_VOTER = 6;
/** Stores a mapping of OIDs to edge markings. Let's say A wants to hide its edge to B. Then
* A should add an edge marking with B's OID.
*/
protected Hashtable <String,EdgeMarking> edgeMarkings;
/**
* Create a SurrogateDetail with a default policy of individual edge voting.
* @param quality extra quality hints
* @param signpost pointers to more information.
*/
public SurrogateDetail(SurrogateQuality quality, SignPost signpost) {
this.quality = quality;
this.signpost = signpost;
setEdgePolicy(SurrogateDetail.EDGE_POLICY_INDIVIDUAL);
} // End DataSurrogateDetail
/**
* Set the edge voting policy for this surrogate.
* @param newPolicy the new policy to use.
* @see SurrogateDetail#EDGE_POLICY_HIDE_ALL
* @see SurrogateDetail#EDGE_POLICY_INDIVIDUAL
* @see SurrogateDetail#EDGE_POLICY_SHOW_ALL
*/
public void setEdgePolicy(int newPolicy) {
edgePolicy = newPolicy;
}
/**
* @return the edge voter for this object, or null if there is none.
*/
public EdgeVoter getEdgeVoter() { return voter; }
public void setEdgeVoter(EdgeVoter voter) {
this.edgePolicy = SurrogateDetail.EDGE_POLICY_USE_VOTER;
this.voter = voter;
}
public SurrogateQuality getQuality() { return quality; }
public SignPost getSignPost() { return signpost; }
public String toString() {
return new String("[SURROGATE: SignPost " + signpost + " quality " + quality + "]");
}
/**
* Indicate that this item is a surrogate. If you're using this object,
* then this is always a surrogate. This method always returns true.
*/
public boolean isSurrogate() { return true; }
/**
* Get the marking for a particular edge. The input parameter specifies the object on the other end of
* the edge. There is no guarantee whether the edge is outgoing or incoming.
* <p>This function may return null if the surrogate isn't sophisticated enough to vote on the edge, or
* has no opinion.
* @param other the object at the other end of the edge that's being marked.
*/
public EdgeMarking getMarking(PLUSEdge edge, PLUSObject other) {
if(edgePolicy == SurrogateDetail.EDGE_POLICY_HIDE_ALL) return EdgeMarking.HIDE;
if(edgePolicy == SurrogateDetail.EDGE_POLICY_SHOW_ALL) return EdgeMarking.SHOW;
if(edgePolicy == SurrogateDetail.EDGE_POLICY_INFER_ALL) return EdgeMarking.INFER;
if(edgePolicy == SurrogateDetail.EDGE_POLICY_USE_VOTER) return voter.getMarking(other);
if(edgePolicy == SurrogateDetail.EDGE_POLICY_IN_INFER_OUT_VISIBLE) {
// If other is the 'to' end, then I'm the 'from' end.
if(edge.getTo().equals(other.getId())) return EdgeMarking.SHOW;
else return EdgeMarking.INFER;
}
if(edgePolicy == SurrogateDetail.EDGE_POLICY_IN_VISIBLE_OUT_INFER) {
// If other is the 'to' end, then I'm the 'from' end.
if(edge.getTo().equals(other.getId())) return EdgeMarking.INFER;
else return EdgeMarking.SHOW;
}
if(edgeMarkings == null) edgeMarkings = new Hashtable<String,EdgeMarking> ();
// Last resort -- case by case edge marking.
return edgeMarkings.get(other.getId());
} // End getMarking
/**
* Add a case-by-case basis edge marking for a particular object. Whenever an object at the other end of
* an edge has an ID matching the input, the provided EdgeMarking will be used.
* <p>Note: this method has a side effect of always setting the edge policy to EDGE_POLICY_INDIVIDUAL
* @param oid the ID of the object on the other end of the edge you want to mark.
* @param marking the marking to use
* @see SurrogateDetail#EDGE_POLICY_INDIVIDUAL
*/
public void addEdgeMarking(String oid, EdgeMarking marking) {
edgePolicy = SurrogateDetail.EDGE_POLICY_INDIVIDUAL;
if(edgeMarkings == null) edgeMarkings = new Hashtable <String,EdgeMarking>();
edgeMarkings.put(oid, marking);
} // End addEdgeMarking
} // End SurrogateDetail