/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated.
* 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
*
* File: $Source: /cvsroot/slrp/boca/com.ibm.adtech.boca.model/src/com/ibm/adtech/boca/model/repository/update/ServerUpdatesProcessor.java,v $
* Created by: Matthew Roy ( <a href="mailto:mroy@us.ibm.com">mroy@us.ibm.com </a>)
* Created on: 5/5/2006
* Revision: $Id: ServerUpdatesProcessor.java 180 2007-07-31 14:24:13Z mroy $
*
* Contributors:
* IBM Corporation - initial API and implementation
* Cambridge Semantics Incorporated - Fork to Anzo
*******************************************************************************/
package org.openanzo.datasource.update;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.apache.commons.collections15.MultiMap;
import org.apache.commons.collections15.multimap.MultiHashMap;
import org.openanzo.datasource.IAuthorizationService;
import org.openanzo.datasource.IQueryService;
import org.openanzo.datasource.IServerQuadStore;
import org.openanzo.datasource.IStoredNamedGraph;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.AnzoRuntimeException;
import org.openanzo.exceptions.CompoundAnzoException;
import org.openanzo.exceptions.ExceptionConstants;
import org.openanzo.exceptions.LogUtils;
import org.openanzo.glitter.exception.GlitterRuntimeException;
import org.openanzo.ontologies.openanzo.AnzoFactory;
import org.openanzo.ontologies.openanzo.NamedGraph;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.TypedLiteral;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Value;
import org.openanzo.rdf.Constants.GRAPHS;
import org.openanzo.rdf.Constants.NAMESPACES;
import org.openanzo.rdf.utils.UriGenerator;
import org.openanzo.rdf.vocabulary.RDF;
import org.openanzo.services.IAuthorizationEventListener;
import org.openanzo.services.INamedGraphUpdate;
import org.openanzo.services.IOperationContext;
import org.openanzo.services.IPrecondition;
import org.openanzo.services.IUpdateTransaction;
import org.openanzo.services.IUpdates;
import org.openanzo.services.impl.AskResult;
import org.openanzo.services.impl.UpdateTransaction;
import org.openanzo.services.impl.Updates;
import org.openanzo.services.serialization.IUpdatesHandler;
import org.openanzo.services.serialization.IUpdatesReader;
import org.openanzo.services.serialization.NamedGraphUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ServerUpdatesProcessor handles updates sent from the client, and applies them to the server
*
* @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
*
*/
public class MultiStageUpdatesProcessor {
/**
* The interface that ServerQuadStores implement in order to handle the contents of update transactions
*/
public interface NamedGraphUpdateHandler {
/**
* Handle a statement
*
* @param addition
* is this an addition or a deletion
* @param metadata
* is this a metadata statement
* @param statement
* statement to process
* @return true if the statement is handled
* @throws AnzoException
*/
public boolean handleStatement(boolean addition, boolean metadata, Statement statement) throws AnzoException;
/**
* Handle named graph info
*
* @param namedGraphUri
* URI of namedGraph
* @param metadataGraphUri
* URI of metadataGraph
* @param aclAdditionSet
* Set of acl additions
* @param aclRemovalSet
* Set of acl removals
* @param revisioned
* Is this graph revisioned
* @param persisted
* Is this graph persisted
* @param metaStatements
* Metadata statements about namedGraph
* @return true if the namedgraph is handled
* @throws AnzoException
*/
public boolean handleAddNamedGraph(URI namedGraphUri, URI metadataGraphUri, AclSet aclAdditionSet, AclSet aclRemovalSet, boolean revisioned, boolean persisted, Collection<Statement> metaStatements) throws AnzoException;
/**
* Handle removing a namedGraph
*
* @param namedGraphUri
* URI of namedGraph
* @return true if namedgraph removal is handled
* @throws AnzoException
*/
public boolean handleRemoveNamedGraph(URI namedGraphUri) throws AnzoException;
/**
* Handle adding an acl privilege
*
* @param statement
* acl statement
* @return true if privilege is added
* @throws AnzoException
*/
public boolean handleAddPrivilege(Statement statement) throws AnzoException;
/**
* Handle removing an acl privilege
*
* @param statement
* acl statement
* @return true if privilege is removed
* @throws AnzoException
*/
public boolean handleRemovePrivilege(Statement statement) throws AnzoException;
}
static class AclSet {
final MultiMap<URI, Statement> aclMap = new MultiHashMap<URI, Statement>();
void add(Statement statement) {
aclMap.put(statement.getPredicate(), statement);
}
int size() {
return aclMap.size();
}
}
private static final Logger log = LoggerFactory.getLogger(MultiStageUpdatesProcessor.class);
private static final String ERROR_PROCESSING_UPDATE = "Error Processing Update:";
private final IQueryService queryService;
private final IAuthorizationService authorizationService;
private final Collection<IAuthorizationEventListener> eventListeners;
private final IOperationContext context;
/** UpdateResults to which updates are written */
private final Updates updateResults;
/** TransactionUpdateResults for the current Transaction */
private ServerUpdateTransaction currentTransactionUpdateResults = null;
/** Flag to keep track if anything has changed during the current transaction */
private boolean transactionChangeHappend = false;
private final IServerQuadStore backend;
private Set<URI> affectedNamedGraphs = null;
private final Set<URI> failedTransactionGraphs = new HashSet<URI>();
private static final Random random = new Random();
private final boolean reseting;
private boolean aborted = false;
/**
* Process a set of IUpdateTransactions and return results
*
* @param context
* NodeCentric specific context, which contains connection to run queries against
* @param backend
* The backend store to which this update processor will apply changes
* @param queryService
* reference to the IQueryService, used for precondition checks
* @param authorizationService
* reference to the authorization service used to check permission on graphs
* @param eventListeners
* Listeners that are notified about updates
* @param transactions
* Array of IUpdateTransactions to commit
* @param resetting
* Is the server resetting
* @return UpdateResults from update
* @throws AnzoException
*/
public static Updates update(IOperationContext context, IServerQuadStore backend, IQueryService queryService, IAuthorizationService authorizationService, Collection<IAuthorizationEventListener> eventListeners, IUpdates transactions, boolean resetting) throws AnzoException {
try {
Updates updateResults = new Updates(context.getOperationId());
MultiStageUpdatesProcessor sup = new MultiStageUpdatesProcessor(context, backend, queryService, authorizationService, eventListeners, updateResults, resetting);
for (IUpdateTransaction transaction : transactions.getTransactions()) {
sup.handleTransaction(transaction);
}
return updateResults;
} finally {
backend.close();
}
}
/**
* Process a set of IUpdateTransactions contained in InputStream and return results
*
* @param context
* NodeCentric specific context, which contains connection to run queries against
* @param backend
* backend for data
* @param queryService
* reference to the IQueryService, used for precondition checks
* @param authorizationService
* reference to the authorization service used to check permission on graphs
* @param eventListeners
* set of listeners that listen for ACL events
*
* @param reader
* InputStream containing transactions
* @param resetting
* Is the server resetting
* @return UpdateResults from transactions
* @throws AnzoException
*/
public static Updates update(IOperationContext context, IServerQuadStore backend, IQueryService queryService, IAuthorizationService authorizationService, Collection<IAuthorizationEventListener> eventListeners, IUpdatesReader reader, boolean resetting) throws AnzoException {
try {
Updates updateResults = new Updates(context.getOperationId());
MultiStageUpdatesProcessor serverUpdateProcessor = new MultiStageUpdatesProcessor(context, backend, queryService, authorizationService, eventListeners, updateResults, resetting);
serverUpdateProcessor.read(reader);
return updateResults;
} finally {
backend.close();
}
}
/**
* Process a set of IUpdateTransactions and return results
*
* @param context
* NodeCentric specific context, which contains connection to run queries against
* @param backend
* backend for data
* @param queryService
* reference to the IQueryService, used for precondition checks
* @param authorizationService
* reference to the authorization service used to check permission on graphs
* @param eventListeners
* set of listeners that listen for ACL events
* @param statements
* Data to add to server
* @param graphTemplate
* Template of statements for creating a new graph
* @param reseting
* Is the server resetting
* @param bulkUpdate
* Is this a bulk update
* @return UpdateResults from update
* @throws AnzoException
*/
public static Updates update(IOperationContext context, IServerQuadStore backend, IQueryService queryService, IAuthorizationService authorizationService, Collection<IAuthorizationEventListener> eventListeners, MultiMap<URI, Statement> statements, Collection<Statement> graphTemplate, boolean reseting, boolean bulkUpdate) throws AnzoException {
long start = System.currentTimeMillis();
IUpdates updates = convertStatementsToUpdates(context, bulkUpdate, statements, graphTemplate, backend);
if (log.isDebugEnabled()) {
log.debug(LogUtils.TIMING_MARKER, "MULTISTAGE_UPDATEPROC CONVERT,{},{}", Long.toString(System.currentTimeMillis() - start), statements.size());
}
Updates results = update(context, backend, queryService, authorizationService, eventListeners, updates, reseting);
return results;
}
/**
* Create a new ServerUpdatesProcessor
*
* @param context
* NodeCentric specific context, which contains connection to run queries against
* @param queryService
* reference to the query service used for precondition checks
* @param authorizationService
* reference to the authorization service used to check permission on graphs
* @param eventListeners
* set of listeners that listen for ACL events
* @param updateResults
* UpdateResults to which updates are written
* @param isReseting
* true if server is in the process of resetting
* @throws AnzoException
*/
private MultiStageUpdatesProcessor(IOperationContext context, IServerQuadStore backend, IQueryService queryService, IAuthorizationService authorizationService, Collection<IAuthorizationEventListener> eventListeners, Updates updateResults, boolean isReseting) throws AnzoException {
this.context = context;
this.updateResults = updateResults;
this.queryService = queryService;
this.authorizationService = authorizationService;
this.eventListeners = eventListeners;
this.backend = backend;
this.reseting = isReseting;
}
/**
* Read updates from an InputStream
*
* @param reader
* InputStream containing updates
* @throws AnzoException
*/
private void read(IUpdatesReader reader) throws AnzoException {
try {
reader.read(new IUpdatesHandler() {
public void start() throws AnzoException {
}
public void handleTransaction(IUpdateTransaction transaction) throws AnzoException {
MultiStageUpdatesProcessor.this.handleTransaction(transaction);
}
public void end() throws AnzoException {
}
});
} catch (AnzoException ae) {
log.error(LogUtils.DATASOURCE_MARKER, ERROR_PROCESSING_UPDATE, ae);
AnzoException throwing = null;
if (currentTransactionUpdateResults != null) {
currentTransactionUpdateResults.handleError(ae.getErrorCode(), ae.getArgs());
try {
backend.abort();
} catch (AnzoException ae2) {
throwing = new CompoundAnzoException(ae, ae2);
}
}
throw (throwing != null) ? throwing : ae;
} catch (AnzoRuntimeException ae) {
log.error(LogUtils.DATASOURCE_MARKER, ERROR_PROCESSING_UPDATE, ae);
AnzoException throwing = null;
if (currentTransactionUpdateResults != null) {
currentTransactionUpdateResults.handleError(ae.getErrorCode(), ae.getArgs());
try {
backend.abort();
} catch (AnzoException ae2) {
throwing = new CompoundAnzoException(ae.getAnzoException(), ae2);
}
}
throw (throwing != null) ? throwing : ae.getAnzoException();
}
}
/**
* Abort the current transaction
*
* @throws AnzoException
* if there was a problem aborting this update
*/
private void abort() throws AnzoException {
if (!aborted) {
aborted = true;
backend.abort();
}
}
/**
* Create a new transaction with given ID and add it list of transactions
*
* @param transactionId
* ID of transaction
* @param timestamp
* timestamp of transaction
* @return a TransactionUpdateResults with given ID
*/
private ServerUpdateTransaction nextTransaction(URI transactionURI, Collection<Statement> transactionContext) throws AnzoException {
long nextId = random.nextLong();
ServerUpdateTransaction tur = new ServerUpdateTransaction(context, System.currentTimeMillis(), nextId, transactionURI, transactionContext);
updateResults.getTransactions().add(tur);
return tur;
}
private void handleTransaction(IUpdateTransaction transaction) throws AnzoException {
if (transaction.getNamedGraphUpdates() != null && transaction.getNamedGraphUpdates().size() > 0) {
long start = System.currentTimeMillis();
try {
handleTransactionStart(transaction.getURI(), transaction.getNamedGraphs(), transaction.getTransactionContext(), transaction.getPreconditions());
long start1 = System.currentTimeMillis();
for (INamedGraphUpdate update : transaction.getNamedGraphUpdates()) {
ServerQuadStoreUpdateHandler sqsuh = new ServerQuadStoreUpdateHandler(backend, currentTransactionUpdateResults, authorizationService, reseting);
MultiStageUpdatesProcessor.handleNamedGraphUpdate(reseting, update, sqsuh);
}
if (log.isDebugEnabled()) {
log.debug(LogUtils.TIMING_MARKER, "[UPDATE-PRE_TRANSACTION_COMMIT],{}", (System.currentTimeMillis() - start1));
}
handleTransactionEnd();
} catch (AnzoException t) {
log.warn(LogUtils.DATASOURCE_MARKER, ERROR_PROCESSING_UPDATE, t);
for (INamedGraphUpdate ngUpdate : transaction.getNamedGraphUpdates()) {
failedTransactionGraphs.add(ngUpdate.getNamedGraphURI());
}
abort();
getCurrentTransactionUpdateResults().handleError(t.getErrorCode(), t.getArgs());
} catch (AnzoRuntimeException ae) {
log.warn(LogUtils.DATASOURCE_MARKER, ERROR_PROCESSING_UPDATE, ae.getAnzoException());
for (INamedGraphUpdate ngUpdate : transaction.getNamedGraphUpdates()) {
failedTransactionGraphs.add(ngUpdate.getNamedGraphURI());
}
abort();
getCurrentTransactionUpdateResults().handleError(ae.getAnzoException().getErrorCode(), ae.getAnzoException().getArgs());
} finally {
if (log.isDebugEnabled()) {
log.debug(LogUtils.TIMING_MARKER, "[TRANSACTION_TOTAL],{}", (System.currentTimeMillis() - start));
}
}
}
}
static long started = 0;
private boolean handleTransactionStart(URI transactionURI, Set<URI> affectedNamedGraphs, Collection<Statement> transactionContext, Collection<IPrecondition> preconditions) throws AnzoException {
transactionChangeHappend = false;
this.affectedNamedGraphs = affectedNamedGraphs;
this.aborted = false;
currentTransactionUpdateResults = nextTransaction(transactionURI, transactionContext);
backend.beginTransaction(currentTransactionUpdateResults.getTransactionId(), currentTransactionUpdateResults.getURI(), affectedNamedGraphs, currentTransactionUpdateResults.getTransactionContext());
for (URI uri : affectedNamedGraphs) {
if (failedTransactionGraphs.contains(uri)) {
throw new AnzoException(ExceptionConstants.DATASOURCE.PREVIOUS_TRANSACTION_FAILED, uri.toString());
}
}
if (preconditions != null) {
for (IPrecondition precondition : preconditions) {
try {
if (!(queryService.askQuery(context, precondition.getDefaultGraphUris(), precondition.getNamedGraphUris(), null, precondition.getQuery(), null, null, true) == ((AskResult) precondition.getResult()).getResultValue())) {
throw new AnzoException(ExceptionConstants.DATASOURCE.COMMAND_PREREQ_FAILED, transactionURI.toString(), precondition.getQuery());
}
} catch (GlitterRuntimeException uge) {
if (((AskResult) precondition.getResult()).getResultValue()) {
throw new AnzoException(ExceptionConstants.DATASOURCE.COMMAND_PREREQ_FAILED, uge, transactionURI.toString(), precondition.getQuery());
}
}
}
}
return true;
}
private boolean handleTransactionEnd() throws AnzoException {
if (log.isDebugEnabled()) {
log.debug(LogUtils.TIMING_MARKER, "Total PROCESS TRANSACTION,{}", Long.valueOf((System.currentTimeMillis() - currentTransactionUpdateResults.getTransactionTimestamp())));
}
long tStart = System.currentTimeMillis();
if (!currentTransactionUpdateResults.hasError()) {
try {
URI userURI = (currentTransactionUpdateResults.getServerPrincipal() != null) ? currentTransactionUpdateResults.getServerPrincipal().getUserURI() : Constants.DEFAULT_INTERNAL_USER;
org.openanzo.datasource.update.UpdateChanges quadResults = new org.openanzo.datasource.update.UpdateChanges();
backend.insertUpdates(quadResults, currentTransactionUpdateResults.getTransactionTimestamp(), userURI);
if (quadResults.removedStatements.size() > 0) {
Integer countA = context.getAttribute("countRemove", Integer.class);
if (countA == null) {
countA = Integer.valueOf(quadResults.removedStatements.size());
} else {
countA = Integer.valueOf(countA.intValue() + quadResults.removedStatements.size());
}
context.setAttribute("countRemove", countA);
currentTransactionUpdateResults.removeStatement(quadResults.removedStatements);
transactionChangeHappend = true;
}
if (quadResults.addedStatements.size() > 0) {
Integer countA = context.getAttribute("countAdd", Integer.class);
if (countA == null) {
countA = Integer.valueOf(quadResults.addedStatements.size());
} else {
countA = Integer.valueOf(countA.intValue() + quadResults.addedStatements.size());
}
context.setAttribute("countAdd", countA);
currentTransactionUpdateResults.addStatement(quadResults.addedStatements);
transactionChangeHappend = true;
}
for (IStoredNamedGraph storedGraph : quadResults.namedGraphs) {
currentTransactionUpdateResults.getUpdatedNamedGraphRevisions().put(storedGraph.getUUID(), storedGraph.getRevision());
currentTransactionUpdateResults.getUpdatedNamedGraphs().put(storedGraph.getURI(), storedGraph.getUUID());
INamedGraphUpdate update = currentTransactionUpdateResults.getNamedGraphUpdate(storedGraph.getURI());
update.setRevision(storedGraph.getRevision());
update.setUUID(storedGraph.getUUID());
transactionChangeHappend = true;
}
if (quadResults.removedNamedGraphs.size() > 0) {
currentTransactionUpdateResults.getRemovedNamedGraphs().putAll(quadResults.removedNamedGraphs);
transactionChangeHappend = true;
}
if (transactionChangeHappend) {
long start = System.currentTimeMillis();
backend.commitTransaction(currentTransactionUpdateResults, affectedNamedGraphs);
if (log.isDebugEnabled()) {
log.debug(LogUtils.TIMING_MARKER, "COMMIT TRANSACTION,{}", Long.valueOf((System.currentTimeMillis() - start)));
}
if (eventListeners != null) {
for (IAuthorizationEventListener listener : eventListeners) {
listener.handleAuthorizationUpdates(currentTransactionUpdateResults.getAclAdditions(), currentTransactionUpdateResults.getAclRemovals());
}
}
} else {
abort();
}
this.affectedNamedGraphs = null;
} catch (AnzoException ae) {
AnzoException throwing = null;
try {
abort();
} catch (AnzoException ae2) {
throwing = new CompoundAnzoException(ae, ae2);
}
throw (throwing != null) ? throwing : ae;
}
} else {
abort();
}
if (log.isDebugEnabled()) {
log.debug(LogUtils.TIMING_MARKER, "PROCESS TRANSACTION END,{}", Long.valueOf((System.currentTimeMillis() - tStart)));
}
return true;
}
/**
* @return the currentTransactionUpdateResults
*/
private ServerUpdateTransaction getCurrentTransactionUpdateResults() {
return currentTransactionUpdateResults;
}
static private void handleNamedGraphUpdate(boolean resetting, INamedGraphUpdate update, MultiStageUpdatesProcessor.NamedGraphUpdateHandler handler) throws AnzoException {
if (!resetting && update.getNamedGraphURI().equals(Constants.GRAPHS.GRAPHS_DATASET) && (update.getAdditions().size() > 0 || update.getRemovals().size() > 0)) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.CANNOT_WRITE_TO_A_SYSTEM_GRAPH, Constants.GRAPHS.GRAPHS_DATASET.toString());
} else if (!resetting && update.getNamedGraphURI().equals(Constants.GRAPHS.METADATA_GRAPHS_DATASET) && (update.getAdditions().size() > 0 || update.getRemovals().size() > 0)) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.CANNOT_WRITE_TO_A_SYSTEM_GRAPH, Constants.GRAPHS.METADATA_GRAPHS_DATASET.toString());
}
if (update.getMetaRemovals().size() > 0) {
handleNamedGraphGraph(update.getNamedGraphURI(), update.getMetaRemovals(), false, handler);
}
if (update.getMetaAdditions().size() > 0) {
handleNamedGraphGraph(update.getNamedGraphURI(), update.getMetaAdditions(), true, handler);
}
for (Statement stmt : update.getRemovals()) {
handler.handleStatement(false, false, stmt);
}
for (Statement stmt : update.getAdditions()) {
handler.handleStatement(true, false, stmt);
}
}
private static boolean isAclResource(Statement statement) {
boolean retval = false;
retval = statement.getPredicate().equals(NamedGraph.canBeReadByProperty) || statement.getPredicate().equals(NamedGraph.canBeAddedToByProperty) || statement.getPredicate().equals(NamedGraph.canBeRemovedFromByProperty);
return retval;
}
private static final boolean statementMatch(Statement stmt, URI predicate, Value obj) {
return stmt.getPredicate().equals(predicate) && stmt.getObject().equals(obj);
}
//The statements that can be added to the metadata graph must meet the following rules:
//The subject of the statement must be either the namedGraph's URI or the metadata graph's URI.
//If it is the metadata graph's URI, the only additions or removals can be acl predicates.
//Any other statement will throw an exception
static void handleNamedGraphGraph(URI namedGraphURI, Collection<Statement> metaStatements, boolean additions, MultiStageUpdatesProcessor.NamedGraphUpdateHandler handler) throws AnzoException {
boolean hasType = false;
URI metadataGraphUri = UriGenerator.generateEncapsulatedURI(NAMESPACES.METADATAGRAPH_PREFIX, namedGraphURI);
MultiStageUpdatesProcessor.AclSet aclSet = new MultiStageUpdatesProcessor.AclSet();
MultiStageUpdatesProcessor.AclSet metaAclSet = new MultiStageUpdatesProcessor.AclSet();
boolean revisioned = true;
boolean persisted = true;
for (Iterator<Statement> iterator = metaStatements.iterator(); iterator.hasNext();) {
Statement statement = iterator.next();
if (MultiStageUpdatesProcessor.statementMatch(statement, RDF.TYPE, NamedGraph.TYPE)) {
iterator.remove();
if (statement.getSubject().equals(namedGraphURI)) {
hasType = true;
} else {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.INVALID_METADATA_TRIPLE, statement.toString(), metadataGraphUri.toString());
}
} else {
if (statement.getSubject().equals(metadataGraphUri)) {
if (isAclResource(statement)) {
metaAclSet.add(statement);
} else {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.INVALID_METADATA_TRIPLE, statement.toString(), metadataGraphUri.toString());
}
} else if (AnzoFactory.isNamedGraphPredicate(statement.getPredicate())) {
if (!statement.getSubject().equals(namedGraphURI)) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.INVALID_METADATA_TRIPLE, statement.toString(), metadataGraphUri.toString());
}
if (isAclResource(statement)) {
aclSet.add(statement);
} else if (statement.getPredicate().equals(NamedGraph.persistedProperty)) {
persisted = ((Boolean) ((TypedLiteral) statement.getObject()).getNativeValue()).booleanValue();
iterator.remove();
} else if (statement.getPredicate().equals(NamedGraph.revisionedProperty)) {
revisioned = ((Boolean) ((TypedLiteral) statement.getObject()).getNativeValue()).booleanValue();
iterator.remove();
} else if (statement.getPredicate().equals(NamedGraph.lastModifiedByUserProperty) || statement.getPredicate().equals(NamedGraph.modifiedProperty) || statement.getPredicate().equals(NamedGraph.createdByProperty) || statement.getPredicate().equals(NamedGraph.createdProperty) || statement.getPredicate().equals(NamedGraph.uuidProperty) || statement.getPredicate().equals(NamedGraph.revisionProperty) || statement.getPredicate().equals(NamedGraph.datasourceProperty)) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.INVALID_METADATA_TRIPLE, statement.toString(), metadataGraphUri.toString());
} else if (statement.getPredicate().equals(NamedGraph.hasMetadataGraphProperty)) {
if (!statement.getObject().equals(metadataGraphUri)) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.INVALID_METADATA_TRIPLE, statement.toString(), metadataGraphUri.toString());
} else {
iterator.remove();
}
}
}
}
}
if (metadataGraphUri != null && hasType) {
if (additions) {
handler.handleAddNamedGraph(namedGraphURI, metadataGraphUri, aclSet, metaAclSet, revisioned, persisted, metaStatements);
} else {
handler.handleRemoveNamedGraph(namedGraphURI);
}
} else {
for (Statement stmt : aclSet.aclMap.values()) {
if (additions) {
handler.handleAddPrivilege(stmt);
} else {
handler.handleRemovePrivilege(stmt);
}
}
for (Statement stmt : metaAclSet.aclMap.values()) {
if (additions) {
handler.handleAddPrivilege(stmt);
} else {
handler.handleRemovePrivilege(stmt);
}
}
for (Statement stmt : metaStatements) {
handler.handleStatement(additions, false, stmt);
}
}
}
private static IUpdates convertStatementsToUpdates(IOperationContext context, boolean bulkUpdate, MultiMap<URI, Statement> statements, Collection<Statement> graphTemplate, IServerQuadStore serverQuadStore) throws AnzoException {
IUpdates updates = new Updates(context.getOperationId());
IUpdateTransaction transaction = new UpdateTransaction(UriGenerator.generateTransactionURI(), 0, null, null);
updates.getTransactions().add(transaction);
// the orderedResourceMaps, once filled will have everything in order
Map<URI, Collection<Statement>> statementMap = new HashMap<URI, Collection<Statement>>();
Map<URI, Collection<Statement>> metaStatementMap = new HashMap<URI, Collection<Statement>>();
Collection<Statement> datasetNG = null;
Collection<Statement> metaDatasetNG = null;
for (Map.Entry<URI, Collection<Statement>> entry : statements.entrySet()) {
if (entry.getKey().equals(GRAPHS.METADATA_GRAPHS_DATASET_META)) {
metaDatasetNG = entry.getValue();
} else if (entry.getKey().equals(GRAPHS.GRAPHS_DATASET_META)) {
datasetNG = entry.getValue();
} else if (UriGenerator.isMetadataGraphUri(entry.getKey())) {
metaStatementMap.put(entry.getKey(), entry.getValue());
} else {
statementMap.put(entry.getKey(), entry.getValue());
}
}
for (Map.Entry<URI, Collection<Statement>> entry : metaStatementMap.entrySet()) {
URI ngURI = UriGenerator.stripEncapsulatedURI(NAMESPACES.METADATAGRAPH_PREFIX, entry.getKey());
Collection<Statement> ngStatements = statementMap.remove(ngURI);
Collection<Statement> ngmdStatements = entry.getValue();
if (ngStatements == null) {
ngStatements = new ArrayList<Statement>();
}
INamedGraphUpdate ngu = new NamedGraphUpdate(ngURI, null, ngStatements, null, ngmdStatements, null);
transaction.addNamedGraphUpdate(ngu);
}
if (datasetNG != null) {
Collection<Statement> ngStatements = statementMap.remove(GRAPHS.GRAPHS_DATASET);
Collection<Statement> ngmdStatements = datasetNG;
if (ngStatements == null) {
ngStatements = new ArrayList<Statement>();
}
INamedGraphUpdate ngu = new NamedGraphUpdate(GRAPHS.GRAPHS_DATASET, null, ngStatements, null, ngmdStatements, null);
transaction.addNamedGraphUpdate(ngu);
}
if (metaDatasetNG != null) {
Collection<Statement> ngStatements = statementMap.remove(GRAPHS.METADATA_GRAPHS_DATASET);
Collection<Statement> ngmdStatements = metaDatasetNG;
if (ngStatements == null) {
ngStatements = new ArrayList<Statement>();
}
INamedGraphUpdate ngu = new NamedGraphUpdate(GRAPHS.METADATA_GRAPHS_DATASET, null, ngStatements, null, ngmdStatements, null);
transaction.addNamedGraphUpdate(ngu);
}
for (Map.Entry<URI, Collection<Statement>> entry : statementMap.entrySet()) {
INamedGraphUpdate ngu = new NamedGraphUpdate(entry.getKey(), null, entry.getValue(), new ArrayList<Statement>(), new ArrayList<Statement>(), new ArrayList<Statement>());
if (!serverQuadStore.containsNamedGraph(entry.getKey()) && graphTemplate != null) {
URI metaURI = UriGenerator.generateMetadataGraphUri(entry.getKey());
for (Statement initStatement : graphTemplate) {
if (initStatement.getSubject().equals(GRAPHS.DEFAULT_GRAPH_TEMPLATE)) {
ngu.getMetaAdditions().add(Constants.valueFactory.createStatement(entry.getKey(), initStatement.getPredicate(), initStatement.getObject(), metaURI));
} else if (initStatement.getSubject().equals(GRAPHS.DEFAULT_METADATA_GRAPH_TEMPLATE)) {
ngu.getMetaAdditions().add(Constants.valueFactory.createStatement(metaURI, initStatement.getPredicate(), initStatement.getObject(), metaURI));
} else if (initStatement.getSubject().equals(GRAPHS.DEFAULT_METADATA_GRAPH_TEMPLATE)) {
ngu.getMetaAdditions().add(Constants.valueFactory.createStatement(metaURI, initStatement.getPredicate(), initStatement.getObject(), metaURI));
}
}
ngu.getMetaAdditions().add(Constants.valueFactory.createStatement(entry.getKey(), RDF.TYPE, NamedGraph.TYPE, metaURI));
ngu.getMetaAdditions().add(Constants.valueFactory.createStatement(entry.getKey(), NamedGraph.hasMetadataGraphProperty, metaURI, metaURI));
}
transaction.addNamedGraphUpdate(ngu);
}
return updates;
}
}