package edu.mit.simile.fresnel.results;
import info.aduna.iteration.Iterations;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.vocabulary.OWL;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import edu.mit.simile.fresnel.util.WrappedVector;
/**
* Set of ValueResults.
*
* @author ryanlee
*/
public class ValueResultSet extends WrappedVector<ValueResult> implements ResultConstants {
/**
* Contents which may apply to the overall set of values.
*/
private ContentSet _contents;
/**
* Base constructor
*/
public ValueResultSet() {
super();
this._contents = new ContentSet();
}
/**
* Returns the set of possible configured contents
*
* @return A <code>ContentSet</code>
*/
public ContentSet getContents() {
return this._contents;
}
/**
* Sets the contents for the value result set
*
* @param contents A <code>ContentSet</code>
*/
public void setContents(ContentSet contents) {
this._contents = contents;
}
/**
* Returns a ValueResultIterator instead of a normal iterator.
*
* @return A <code>ValueResultIterator</code>
*/
public Iterator<ValueResult> valueResultIterator() {
return this._base.iterator();
}
/**
* Adds a value result to the existing set.
*
* @param value A <code>ValueResult</code>
* @param in Data repository
* @return Success or failure
*/
public boolean addValueResult(ValueResult value, Repository in) {
if (value.getResult() != null) {
/* Value is a resource */
RepositoryConnection conn = null;
try {
conn = in.getConnection();
for (ValueResult existingValue : this._base) {
if (existingValue.getResult() == null)
continue;
/* If the same value already exists, don't add it but just provide the origin */
if (existingValue.getResult().getOrigin().equals(value.getResult().getOrigin())) {
existingValue.addSources(value.getSources());
return true;
}
/* If the value is owl:sameAs, don't add it but provide an alias */
if (existingValue.getPossibleAliases().contains(value.getResult().getOrigin())) {
existingValue.addAlias(value.getResult().getOrigin());
return true;
}
}
/* Didn't return, so value will be added. Enhance it with possible aliases. */
RepositoryResult<Statement> result = conn.getStatements(value.getResult().getOrigin(), OWL.SAMEAS, null, true);
RepositoryResult<Statement> inverseResult = conn.getStatements(null, OWL.SAMEAS, value.getResult().getOrigin(), true);
while (result.hasNext() || inverseResult.hasNext()) {
boolean regular = result.hasNext();
Statement st = (regular ? result.next() : inverseResult.next());
value.addPossibleAlias(regular ? (Resource)st.getObject() : st.getSubject());
}
}
catch (RepositoryException e) {
e.printStackTrace();
}
finally {
try {
if (conn != null)
conn.close();
}
catch (RepositoryException e) {
e.printStackTrace();
}
}
}
else {
/* It's a literal. If the same value already exists, don't add it but just provide the origin */
for (ValueResult existingValue : this._base) {
if ((existingValue.getValue() != null && value.getValue() != null && existingValue.getValue().equals(value.getValue()))
|| (existingValue.getTitle() != null && value.getTitle() != null && existingValue.getTitle().getString().equals(value.getTitle().getString()))) {
existingValue.addSources(value.getSources());
return true;
}
}
}
return this._base.add(value);
}
/**
* Adds a value result to the existing set.
*
* @param value A <code>ValueResult</code>
* @return Success or failure
*/
public boolean addValueResult(ValueResult value) {
return addValueResult(value, null);
}
/**
* Removes a value result from the existing set.
*
* @param value A <code>ValueResult</code>
* @return Success or failure
*/
public boolean removeValueResult(ValueResult value) {
return this._base.remove(value);
}
/**
* Add all elements from a value result set into this one.
*
* @param arg0 A <code>ValueResultSet</code>
* @return Success or failure
*/
public boolean addValueResultSet(ValueResultSet arg0) {
return this._base.addAll(arg0._base);
}
/**
* Replace WrappedVector contains method to do specific <code>ValueResult</code>
* equality checking.
*
* @param value The <code>ValueResult</code> component to check
* @return True if contained in set, false if not.
*/
public boolean contains(ValueResult value) {
for (Iterator<ValueResult> it = this.valueResultIterator(); it.hasNext(); ) {
if (value.equals(it.next())) return true;
}
return false;
}
/**
* Render the set as part of a DOM.
*
* @param doc A <code>Document</code> for creating elements.
* @return An <code>Element</code>, e.g.: <values> ... </values>
*/
public Element render(Document doc) {
Element out = doc.createElementNS(INTERMEDIATE_NS, "values");
Element content = getContents().render(doc);
if (content.hasChildNodes()) out.appendChild(content);
for(Iterator<ValueResult> it = valueResultIterator(); it.hasNext(); ) {
out.appendChild(it.next().render(doc));
}
return out;
}
}