/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.layer0.utils.binaryPredicates; import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; import java.util.HashSet; import java.util.Set; import org.simantics.db.Resource; import org.simantics.db.ReadGraph; import org.simantics.db.WriteGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.utils.datastructures.Pair; public class TransitiveClosure extends BinaryPredicate { IBinaryPredicate predicate; public TransitiveClosure(IBinaryPredicate predicate) { this.predicate = predicate; } @Override public void add(WriteGraph g, Resource subject, Resource object) throws DatabaseException { if(!has(g, subject, object)) predicate.add(g, subject, object); } @Override public Collection getObjects(ReadGraph g, Resource subject) throws DatabaseException { Deque unprocessed = new ArrayDeque(); unprocessed.add(subject); Set result = new HashSet(); while(!unprocessed.isEmpty()) for(Resource r : predicate.getObjects(g, unprocessed.pop())) if(result.add(r)) unprocessed.push(r); return result; } @Override public Collection> getStatements(ReadGraph g) { // TODO Auto-generated method stub return null; } @Override public Collection getSubjects(ReadGraph g, Resource object) throws DatabaseException { Deque unprocessed = new ArrayDeque(); unprocessed.add(object); Set result = new HashSet(); while(!unprocessed.isEmpty()) for(Resource r : predicate.getSubjects(g, unprocessed.pop())) if(result.add(r)) unprocessed.push(r); return result; } @Override public boolean has(ReadGraph g, Resource subject, Resource object) throws DatabaseException { Deque unprocessed = new ArrayDeque(); unprocessed.add(subject); Set objects = new HashSet(); while(!unprocessed.isEmpty()) for(Resource r : predicate.getObjects(g, unprocessed.pop())) if(r.equals(object)) return true; else if(objects.add(r)) unprocessed.push(r); return false; } @Override public void remove(WriteGraph g, Resource subject, Resource object) { throw new UnsupportedOperationException(); } @Override public boolean supportsAdditions() { return predicate.supportsAdditions(); } @Override public boolean supportsGetObjects() { return predicate.supportsGetObjects(); } @Override public boolean supportsGetStatements() { return false; // FIXME: just unimplemented } @Override public boolean supportsGetSubjects() { return predicate.supportsGetSubjects(); } @Override public boolean supportsRemovals() { return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((predicate == null) ? 0 : predicate.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TransitiveClosure other = (TransitiveClosure) obj; if (predicate == null) { if (other.predicate != null) return false; } else if (!predicate.equals(other.predicate)) return false; return true; } }