package com.temenos.interaction.core.hypermedia.expression; /* * #%L * interaction-core * %% * Copyright (C) 2012 - 2013 Temenos Holdings N.V. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response.Status; import com.temenos.interaction.core.command.CommandHelper; import com.temenos.interaction.core.command.InteractionContext; import com.temenos.interaction.core.hypermedia.HypermediaTemplateHelper; import com.temenos.interaction.core.hypermedia.LazyResourceState; import com.temenos.interaction.core.hypermedia.ResourceState; import com.temenos.interaction.core.hypermedia.ResourceStateMachine; import com.temenos.interaction.core.hypermedia.Transition; import com.temenos.interaction.core.resource.EntityResource; import com.temenos.interaction.core.resource.RESTResource; import com.temenos.interaction.core.rim.HTTPHypermediaRIM; import com.temenos.interaction.core.rim.ResourceRequestConfig; import com.temenos.interaction.core.rim.ResourceRequestResult; import com.temenos.interaction.core.rim.SequentialResourceRequestHandler; public class ResourceGETExpression implements Expression { public enum Function { OK, NOT_FOUND } public final Function function; public final String state; public final Transition transition; public final Set<Transition> transitions = new HashSet<Transition>(); public ResourceGETExpression(ResourceState target, Function function) { this.function = function; this.state = null; this.transition = new Transition.Builder().method("GET").target(target).flags(Transition.EXPRESSION).build(); this.transitions.add(transition); } // keep old way until 0.5.1 @Deprecated public ResourceGETExpression(String state, Function function) { this.function = function; this.state = state; this.transition = null; } public Function getFunction() { return function; } public String getState() { String state = null; if (transition != null) { state = transition.getTarget().getName(); } return state; } @Override public boolean evaluate(HTTPHypermediaRIM rimHandler, InteractionContext ctx, EntityResource<?> resource) { ResourceStateMachine hypermediaEngine = rimHandler.getHypermediaEngine(); ResourceState target = null; Transition ourTransition = transition; if (ourTransition == null) { target = hypermediaEngine.getResourceStateByName(state); ourTransition = ctx.getCurrentState().getTransition(target); } else { target = ourTransition.getTarget(); } target = hypermediaEngine.checkAndResolve(target); assert(ourTransition != null); if (target == null) throw new IllegalArgumentException("Indicates a problem with the RIM, it allowed an invalid state to be supplied"); assert(target.getActions() != null); if(ourTransition.getTarget() instanceof LazyResourceState) { ourTransition.setTarget(target); } //Create a new interaction context for this state MultivaluedMap<String, String> pathParameters = getPathParametersForTargetState(hypermediaEngine, ctx, ourTransition); InteractionContext newCtx = new InteractionContext(ctx, null, pathParameters, null, target); EntityResource<?> entityResourceCopy = CommandHelper.createEntityResource(resolveEntityResource(resource, ctx.getResource())); newCtx.setResource(entityResourceCopy); //Get the target resource ResourceRequestConfig config = new ResourceRequestConfig.Builder() .transition(ourTransition) .injectLinks(false) .embedResources(false) .build(); Map<Transition, ResourceRequestResult> results = new SequentialResourceRequestHandler().getResources(rimHandler, null, newCtx, entityResourceCopy, config); assert(results.values() != null && results.values().size() == 1); ResourceRequestResult result = results.values().iterator().next(); //Ignore the resource and its links, just interested in the result status if (Status.OK.getStatusCode() == result.getStatus() && getFunction().equals(Function.OK)) { return true; } if (Status.OK.getStatusCode() != result.getStatus() && getFunction().equals(Function.NOT_FOUND)) { return true; } return false; } @Override public Set<Transition> getTransitions() { return transitions; } public String toString() { StringBuffer sb = new StringBuffer(); if (getFunction().equals(ResourceGETExpression.Function.OK)) sb.append("OK(").append(getState()).append(")"); if (getFunction().equals(ResourceGETExpression.Function.NOT_FOUND)) sb.append("NOT_FOUND").append(getState()).append(")"); return sb.toString(); } private EntityResource<?> resolveEntityResource(EntityResource<?> entityResource, RESTResource restResource) { if (entityResource != null) { return entityResource; } if (restResource instanceof EntityResource) { return (EntityResource<?>) restResource; } return null; } /* * Obtain path parameters to use when accessing * a resource state on an expression. */ private MultivaluedMap<String, String> getPathParametersForTargetState(ResourceStateMachine hypermediaEngine, InteractionContext ctx, Transition transition) { Map<String, Object> transitionProperties = new HashMap<String, Object>(); // by default add all the path parameters to access the target if (ctx.getPathParameters() != null) { for (String key : ctx.getPathParameters().keySet()){ transitionProperties.put(key, ctx.getPathParameters().getFirst(key)); } } RESTResource resource = ctx.getResource(); if(resource != null && resource instanceof EntityResource) { Object entity = ((EntityResource<?>) resource).getEntity(); transitionProperties.putAll(hypermediaEngine.getTransitionProperties(transition, entity, null, null)); } //apply transition properties to path parameters return HypermediaTemplateHelper.getPathParametersForTargetState(transition, transitionProperties); } }