001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 */
019
020package org.apache.isis.core.metamodel.interactions;
021
022import java.util.Map;
023
024import com.google.common.collect.ImmutableMap;
025
026import org.apache.isis.applib.Identifier;
027import org.apache.isis.applib.events.InteractionEvent;
028import org.apache.isis.core.commons.authentication.AuthenticationSession;
029import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
030import org.apache.isis.core.metamodel.consent.InteractionContextType;
031import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
032import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
033import org.apache.isis.core.metamodel.facetapi.Facet;
034
035/**
036 * Represents an interaction between the framework and (a {@link Facet} of) the
037 * domain object.
038 * 
039 * <p>
040 * There are two main responsibilities:
041 * <ul>
042 * <li>Wraps up a target object, parameters and a {@link AuthenticationSession}.
043 * Defining this as a separate interface makes for a more stable API</li>
044 * <li>Acts as a factory for the corresponding {@link InteractionEvent} (more on
045 * this below).</li>
046 * </ul>
047 * 
048 * <p>
049 * The {@link InteractionContext} hierarchy is parallel to the
050 * {@link InteractionEvent} hierarchy. Having parallel hierarchies is a bit of a
051 * code-smell. However, it is required because the {@link InteractionContext
052 * context} hierarchy is internal to the framework (with references to
053 * {@link ObjectAdapter}s, {@link AuthenticationSession}s and so forth), whereas
054 * the {@link InteractionEvent event} hierarchy is part of the corelib, that is
055 * public API.
056 * 
057 * <p>
058 * The class is genericized so that the {@link #createInteractionEvent() factory
059 * method} can return the correct subclass without having to downcast.
060 */
061public abstract class InteractionContext<T extends InteractionEvent> {
062
063    private final InteractionContextType interactionType;
064    private final Identifier identifier;
065    private final InteractionInvocationMethod invocation;
066    private final AuthenticationSession session;
067    private final ObjectAdapter target;
068    private final DeploymentCategory deploymentCategory;
069    
070    private int contributeeParam = -1; // no contributee
071    private ObjectAdapter contributee = null;
072
073    public InteractionContext(final InteractionContextType interactionType, DeploymentCategory deploymentCategory, final AuthenticationSession session, final InteractionInvocationMethod invocationMethod, final Identifier identifier, final ObjectAdapter target) {
074        this.interactionType = interactionType;
075        this.invocation = invocationMethod;
076        this.identifier = identifier;
077        this.session = session;
078        this.target = target;
079        this.deploymentCategory = deploymentCategory;
080    }
081
082    public DeploymentCategory getDeploymentCategory() {
083        return deploymentCategory;
084    }
085
086    /**
087     * The type of interaction.
088     * 
089     * <p>
090     * Available for use by {@link Facet}s that apply only in certain
091     * conditions. For example, some facets for collections will care only when
092     * an object is being added to the collection, but won't care when an object
093     * is being removed from the collection.
094     * 
095     * <p>
096     * Alternatively, {@link Facet}s can use <tt>instanceof</tt>.
097     */
098    public InteractionContextType getInteractionType() {
099        return interactionType;
100    }
101
102    /**
103     * The identifier of the object or member that is being identified with.
104     * 
105     * <p>
106     * If the {@link #getInteractionType() type} is
107     * {@link InteractionContextType#OBJECT_VALIDATE}, will be the identifier of
108     * the {@link #getTarget() target} object's specification. Otherwise will be
109     * the identifier of the member.
110     */
111    public Identifier getIdentifier() {
112        return identifier;
113    }
114
115    /**
116     * The {@link AuthenticationSession user or role} that is performing this
117     * interaction.
118     */
119    public AuthenticationSession getSession() {
120        return session;
121    }
122
123    /**
124     * How the interaction was initiated.
125     */
126    public InteractionInvocationMethod getInvocationMethod() {
127        return invocation;
128    }
129
130    /**
131     * Convenience method that indicates whether the
132     * {@link #getInvocationMethod() interaction was invoked} programmatically.
133     */
134    public boolean isProgrammatic() {
135        return invocation == InteractionInvocationMethod.PROGRAMMATIC;
136    }
137
138    /**
139     * The target object that this interaction is with.
140     */
141    public ObjectAdapter getTarget() {
142        return target;
143    }
144
145    // //////////////////////////////////////
146
147    public void putContributee(int contributeeParam, ObjectAdapter contributee) {
148        this.contributeeParam = contributeeParam;
149        this.contributee = contributee;
150    }
151    
152    public Map<Integer, ObjectAdapter> getContributeeAsMap() {
153        return contributee != null
154                ? ImmutableMap.<Integer, ObjectAdapter>of(contributeeParam, contributee)
155                : ImmutableMap.<Integer, ObjectAdapter>of();
156    }
157
158    // //////////////////////////////////////
159
160    
161    
162    /**
163     * Factory method to create corresponding {@link InteractionEvent}.
164     * 
165     * @return
166     */
167    public abstract T createInteractionEvent();
168
169}