package xdi2.messaging.container.interceptor.impl; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import xdi2.core.Graph; import xdi2.core.Relation; import xdi2.core.features.aggregation.Aggregation; import xdi2.core.syntax.XDIAddress; import xdi2.core.util.CopyUtil; import xdi2.core.util.iterators.IteratorListMaker; import xdi2.messaging.Message; import xdi2.messaging.MessageEnvelope; import xdi2.messaging.constants.XDIMessagingConstants; import xdi2.messaging.container.MessagingContainer; import xdi2.messaging.container.Prototype; import xdi2.messaging.container.exceptions.Xdi2MessagingException; import xdi2.messaging.container.execution.ExecutionContext; import xdi2.messaging.container.execution.ExecutionResult; import xdi2.messaging.container.impl.AbstractMessagingContainer; import xdi2.messaging.container.interceptor.InterceptorResult; import xdi2.messaging.container.interceptor.OperationInterceptor; import xdi2.messaging.container.interceptor.impl.linkcontract.LinkContractInterceptor; import xdi2.messaging.operations.GetOperation; import xdi2.messaging.operations.Operation; /** * This interceptor handles $has relations. * * @author markus */ public class HasInterceptor extends AbstractInterceptor<MessagingContainer> implements OperationInterceptor, Prototype<HasInterceptor> { private static final Logger log = LoggerFactory.getLogger(HasInterceptor.class); /* * Prototype */ @Override public HasInterceptor instanceFor(PrototypingContext prototypingContext) { // done return this; } /* * Init and shutdown */ @Override public void init(MessagingContainer messagingContainer) throws Exception { super.init(messagingContainer); if (! (messagingContainer instanceof AbstractMessagingContainer)) throw new Xdi2MessagingException("Can only add this interceptor to an AbstractMessagingContainer", null, null); } /* * OperationInterceptor */ @Override public InterceptorResult before(Operation operation, Graph operationResultGraph, ExecutionContext executionContext) throws Xdi2MessagingException { return InterceptorResult.DEFAULT; } @Override public InterceptorResult after(Operation operation, Graph operationResultGraph, ExecutionContext executionContext) throws Xdi2MessagingException { // look through the message result to process result $has relations if (operation instanceof GetOperation && operation.getTargetXDIAddress() != null) { List<Relation> hasRelations = new IteratorListMaker<Relation> (Aggregation.getAllAggregationRelations(operationResultGraph.getRootContextNode(true))).list(); for (Relation hasRelation : hasRelations) { if (log.isDebugEnabled()) log.debug("In message result: Found $has relation: " + hasRelation); XDIAddress hasTargetXDIAddress = hasRelation.getTargetXDIAddress(); // $get feedback on the target of the $has relation Graph feedbackResultGraph = feedbackGetTargetOfHasRelation(hasTargetXDIAddress, operation, executionContext); // merge the message result CopyUtil.copyGraph(feedbackResultGraph, operationResultGraph, null); // done with this $has relation if (log.isDebugEnabled()) log.debug("In message result: After $get feedback on $has relation " + hasRelation + " we now have: " + operationResultGraph); } } // done return InterceptorResult.DEFAULT; } /* * Feedback methods */ private static Graph feedbackGetTargetOfHasRelation(XDIAddress hasTargetXDIAddress, Operation operation, ExecutionContext executionContext) throws Xdi2MessagingException { if (log.isDebugEnabled()) log.debug("Initiating $get feedback to get target of $has relation: " + hasTargetXDIAddress); // prepare messaging container AbstractMessagingContainer messagingContainer = (AbstractMessagingContainer) executionContext.getCurrentMessagingContainer(); // prepare feedback message MessageEnvelope feedbackMessageEnvelope = new MessageEnvelope(); Message feedbackMessage = feedbackMessageEnvelope.createMessage(operation.getMessage().getSenderXDIAddress()); feedbackMessage.setToPeerRootXDIArc(operation.getMessage().getToPeerRootXDIArc()); Operation feedbackOperation = feedbackMessage.createGetOperation(hasTargetXDIAddress); if (Boolean.TRUE.equals(operation.getParameterBoolean(XDIMessagingConstants.XDI_ADD_OPERATION_PARAMETER_DEHAS))) feedbackOperation.setParameter(XDIMessagingConstants.XDI_ADD_OPERATION_PARAMETER_DEHAS, Boolean.TRUE); // prepare feedback execution result ExecutionResult feedbackExecutionResult = ExecutionResult.createExecutionResult(feedbackMessageEnvelope); // feedback Map<String, Object> messageAttributes = null; Map<String, Object> operationAttributes = null; try { // before feedback: tweak the execution context and messaging container LinkContractInterceptor linkContractInterceptor = messagingContainer.getInterceptors().getInterceptor(LinkContractInterceptor.class); if (linkContractInterceptor != null) linkContractInterceptor.setDisabledForMessage(feedbackMessage); messageAttributes = executionContext.getMessageAttributes(); operationAttributes = executionContext.getOperationAttributes(); // execute feedback messages messagingContainer.execute(feedbackMessage, executionContext, feedbackExecutionResult); } finally { // after feedback: restore the execution context and messaging container if (messageAttributes != null) executionContext.setMessageAttributes(messageAttributes); if (operationAttributes != null) executionContext.setOperationAttributes(operationAttributes); } // finish feedback execution result feedbackExecutionResult.finish(); // done if (log.isDebugEnabled()) log.debug("Completed $get feedback on target of $has relation: " + hasTargetXDIAddress + ", execution result: " + feedbackExecutionResult); return feedbackExecutionResult.makeLightMessagingResponse().getResultGraph(); } }