/* 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.client;
import java.io.IOException;
import java.util.List;
import java.util.ListIterator;
import org.mitre.provenance.Metadata;
import org.mitre.provenance.PLUSException;
import org.mitre.provenance.dag.TraversalSettings;
import org.mitre.provenance.plusobject.PLUSActor;
import org.mitre.provenance.plusobject.PLUSObject;
import org.mitre.provenance.plusobject.PLUSWorkflow;
import org.mitre.provenance.plusobject.ProvenanceCollection;
import org.mitre.provenance.user.PrivilegeClass;
import org.mitre.provenance.user.PrivilegeSet;
import org.mitre.provenance.user.User;
/**
* This class defines the methods that all provenance clients must implement.
* @author moxious
* TODO this class should have functionality that unifies the RESTful API with Neo4JStorage. Many more methods to add.
*/
public abstract class AbstractProvenanceClient {
protected User viewer = User.PUBLIC;
/**
* Get the user object that will be used for all requests.
* @return the user
*/
public User getViewer() { return viewer; }
/**
* Modify the user object that will be used for all requests.
* @param user the new user to use for all subsequent requests.
*/
public void setUser(User user) {
this.viewer = user;
}
/**
* Report new provenance to the provenance store. This has the effect of creating new objects.
* @param col the collection to report
* @return true if successful, false if unsuccessful.
* @throws ProvenanceClientException
*/
public abstract boolean report(ProvenanceCollection col) throws ProvenanceClientException;
/**
* Fetch provenance from a store.
* @param oid the ID of the object to start from
* @param desc a set of traversal settings describing how provenance should be discovered.
* @return a provenance collection
* @throws ProvenanceClientException
* @see org.mitre.provenance.dag.TraversalSettings
*/
public abstract ProvenanceCollection getGraph(String oid, TraversalSettings desc) throws ProvenanceClientException;
public ProvenanceCollection getGraph(PLUSObject obj, TraversalSettings desc) throws ProvenanceClientException {
return getGraph(obj.getId(), desc);
}
/**
* Send a Cypher query and return the graph
* @param the query string written in Cypher
* @return the requested query stored as a ProvenanceCollection
* @throws IOException
*/
public abstract ProvenanceCollection query(String query) throws IOException;
/**
* Determine whether or not an object exists.
* @param obj the object to check
* @return the object that's stored by the same ID, or null if it does not exist.
* @throws ProvenanceClientException
*/
public PLUSObject exists(PLUSObject obj) throws ProvenanceClientException {
return exists(obj.getId());
}
/**
* Checks to see if an actor exists by an AID.
* @param aid
* @return the PLUSActor, or null if it doesn't exist.
* @throws ProvenanceClientException
*/
public abstract PLUSActor actorExists(String aid) throws ProvenanceClientException;
/**
* Checks to see if an actor exists by a name.
* @param name the name
* @return the PLUSActor, or null if it doesn't exist.
* @throws ProvenanceClientException
*/
public abstract PLUSActor actorExistsByName(String name) throws ProvenanceClientException;
/**
* Determine whether or not an object exists.
* @param oid the object ID of the object to check for existance
* @return true if the object exists, false otherwise.
* @throws ProvenanceClientException
*/
public PLUSObject exists(String oid) throws ProvenanceClientException {
TraversalSettings s = new TraversalSettings()
.excludeEdges()
.excludeNPEs()
.includeNodes()
.setMaxDepth(1)
.dontExpandWorkflows()
.ignoreNPIDs()
.setN(1);
ProvenanceCollection col = getGraph(oid, s);
if(col.isEmpty()) return null;
return col.getNode(oid);
} // End exists
/**
* Fetch provenance from a store, using the default traversal settings.
* @param oid the ID of the object to start from
* @return a provenance collection
*/
public ProvenanceCollection getGraph(String oid) throws ProvenanceClientException { return getGraph(oid, new TraversalSettings()); }
/**
* List workflows in the catalog (most recent) up to a certain max number.
* @param max
* @return
* @throws ProvenanceClientException
*/
public abstract List<PLUSWorkflow> listWorkflows(int max) throws ProvenanceClientException;
public abstract PLUSObject getSingleNode(String oid) throws ProvenanceClientException;
public abstract ProvenanceCollection getWorkflowMembers(String oid, int max) throws ProvenanceClientException;
/**
* @return a collection containing the latest reported objects.
* @throws ProvenanceClientException
*/
public abstract ProvenanceCollection latest() throws ProvenanceClientException;
/**
* Return a collection containing the latest reported actors.
* @param max the maximum number of items to return.
* @return a ProvenanceCollection containing only actors.
* @throws ProvenanceClientException
*/
public abstract ProvenanceCollection getActors(int max) throws ProvenanceClientException;
public ProvenanceCollection getActors() throws ProvenanceClientException {
return getActors(100);
}
/**
* Search for provenance matching a certain term
* @param searchTerm the search term
* @param max the maximum number of items to return.
* @return a provenance collection.
* @throws ProvenanceClientException
*/
public abstract ProvenanceCollection search(String searchTerm, int max) throws ProvenanceClientException;
/**
* Search for provenance matching a certain set of metadata properties.
* @param parameters the properties being sought.
* @param max the maximum number of items to return.
* @return a provenance collection.
* @throws ProvenanceClientException
*/
public abstract ProvenanceCollection search(Metadata parameters, int max) throws ProvenanceClientException;
/**
* Indicate whether this set of privileges dominates a particular class. If a member of this set dominates a particular
* class, then the user possessing that set is authorized to see data at that privilege class.
* @param ps the set to check
* @param other the class to check
* @return true if any privilege class in the set dominates c
* @throws PLUSException
*/
public boolean dominates(PrivilegeSet ps, PrivilegeClass other) throws ProvenanceClientException {
for(int x=0; x<ps.set.size(); x++) {
PrivilegeClass p = ps.set.get(x);
if(dominates(p, other)) return true;
}
return false;
}
/**
* Determine whether this privilege set dominates another.
* @param one the first set to check.
* @param other the other you want to check.
* @return true if one privilege set contains a set of privilege classes that dominates all privilege classes in the
* other privilege set, false otherwise. In the case of incomparable PrivilegeSets, this method will return
* false.
* @throws PLUSException
*/
public boolean dominates(PrivilegeSet one, PrivilegeSet other) throws ProvenanceClientException {
try {
ListIterator <PrivilegeClass> otherprivileges = (other.getPrivilegeSet()).listIterator();
while (otherprivileges.hasNext()) {
PrivilegeClass otherprivilege = otherprivileges.next();
if (!dominates(one, otherprivilege))
return false;
} // End while
return true;
} catch(PLUSException e) {
throw new ProvenanceClientException(e);
} // End catch
} // End dominates(PrivilegeSet)
public abstract boolean dominates(PrivilegeClass a, PrivilegeClass b) throws ProvenanceClientException;
/**
* Determine whether this user can see information at privilege class p.
* @param user the user
* @param p the class you want to check
* @return true if the user has this privilege, or has a privilege which dominates it.
*/
public boolean authorizedFor(User user, PrivilegeClass p) throws ProvenanceClientException {
if(user == User.DEFAULT_USER_GOD) return true;
return dominates(user.getPrivileges(), p);
}
/**
* Determine whether or not a given user is permitted to see a given object.
* @param user the user whose permissions should be checked.
* @param obj the object, which may or may not be visible to the user.
* @param conjunctive if true, use a conjunctive check. If false, use a disjunctive check.
* @return true if the user is permitted to see the object, false otherwise.
* @throws PLUSException
*/
public boolean canSee(User user, PLUSObject obj, boolean conjunctive) throws PLUSException {
try {
if (conjunctive) return canSee(user, obj);
return canSeeDisjunctive(user, obj);
} catch(PLUSException e) {
throw new PLUSException("PrivilegeSet#dominatesDisjunctive: " + e, e);
}
}
/**
* Check and see if a given PLUSObject should be visible to this user.
* @param user the user in question
* @param obj the object you want to check.
* @return true if the user's privileges dominate ALL of the privileges required by the object, false otherwise.
* @throws PLUSException
*/
public boolean canSee(User user, PLUSObject obj) throws ProvenanceClientException {
if(user == User.DEFAULT_USER_GOD) return true;
if(user.getPrivileges().contains(PrivilegeClass.ADMIN)) return true;
PrivilegeSet ps = obj.getPrivileges();
// Check each privilege class in the object.
// If the user isn't authorized for one of them, they can't see this object.
for(int x=0; x<ps.set.size(); x++) {
PrivilegeClass c = ps.set.get(x);
if(!authorizedFor(user, c)) {
// PLUSUtils.log.debug("Not authorized for " + c);
return false;
} // else System.out.print(c + " (check), ");
} // End for
return true;
}
/**
* Performs a disjunctive check to see whether a user can see the object in question.
* @param user
* @param obj
* @return true if the user is authorized for ANY ONE of the privileges required by the object (not necessarily all)
*/
private boolean canSeeDisjunctive(User user, PLUSObject obj) throws PLUSException {
if(user == User.DEFAULT_USER_GOD) return true;
if(user.getPrivileges().contains(PrivilegeClass.ADMIN)) return true;
PrivilegeSet ps = obj.getPrivileges();
// Check each privilege class in the object.
// If the user is authorized for one of them, they can see this object.
for(int x=0; x<ps.set.size(); x++) {
PrivilegeClass c = ps.set.get(x);
if(authorizedFor(user, c)) {
return true;
} // else System.out.print(c + " (check), ");
} // End for
return false;
}
} // End AbstractProvenanceClient