/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.isis.core.metamodel.interactions;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.events.InteractionEvent;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.consent.InteractionContextType;
import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.facetapi.Facet;
/**
* Represents an interaction between the framework and (a {@link Facet} of) the
* domain object.
*
* <p>
* There are two main responsibilities:
* <ul>
* <li>Wraps up a target object, parameters and a {@link AuthenticationSession}.
* Defining this as a separate interface makes for a more stable API</li>
* <li>Acts as a factory for the corresponding {@link InteractionEvent} (more on
* this below).</li>
* </ul>
*
* <p>
* The {@link InteractionContext} hierarchy is parallel to the
* {@link InteractionEvent} hierarchy. Having parallel hierarchies is a bit of a
* code-smell. However, it is required because the {@link InteractionContext
* context} hierarchy is internal to the framework (with references to
* {@link ObjectAdapter}s, {@link AuthenticationSession}s and so forth), whereas
* the {@link InteractionEvent event} hierarchy is part of the corelib, that is
* public API.
*
* <p>
* The class is genericized so that the {@link #createInteractionEvent() factory
* method} can return the correct subclass without having to downcast.
*/
public abstract class InteractionContext<T extends InteractionEvent> {
private final InteractionContextType interactionType;
private final Identifier identifier;
private final InteractionInitiatedBy interactionInitiatedBy;
private final ObjectAdapter target;
private int contributeeParam = -1; // no contributee
private ObjectAdapter contributee = null;
private ObjectAdapter mixedInAdapter = null; // for mixin members only, obviously
public InteractionContext(
final InteractionContextType interactionType,
final InteractionInitiatedBy invocationMethod,
final Identifier identifier,
final ObjectAdapter target) {
this.interactionType = interactionType;
this.interactionInitiatedBy = invocationMethod;
this.identifier = identifier;
this.target = target;
}
/**
* The type of interaction.
*
* <p>
* Available for use by {@link Facet}s that apply only in certain
* conditions. For example, some facets for collections will care only when
* an object is being added to the collection, but won't care when an object
* is being removed from the collection.
*
* <p>
* Alternatively, {@link Facet}s can use <tt>instanceof</tt>.
*/
public InteractionContextType getInteractionType() {
return interactionType;
}
/**
* The identifier of the object or member that is being identified with.
*
* <p>
* If the {@link #getInteractionType() type} is
* {@link InteractionContextType#OBJECT_VALIDATE}, will be the identifier of
* the {@link #getTarget() target} object's specification. Otherwise will be
* the identifier of the member.
*/
public Identifier getIdentifier() {
return identifier;
}
/**
* How the interaction was initiated.
*/
public InteractionInitiatedBy getInitiatedBy() {
return interactionInitiatedBy;
}
/**
* Convenience method that indicates whether the
* {@link #getInitiatedBy() interaction was invoked} by the framework.
*/
public boolean isFrameworkInitiated() {
return interactionInitiatedBy == InteractionInitiatedBy.FRAMEWORK;
}
/**
* The target object that this interaction is with.
*/
public ObjectAdapter getTarget() {
return target;
}
// //////////////////////////////////////
public void putContributee(int contributeeParam, ObjectAdapter contributee) {
this.contributeeParam = contributeeParam;
this.contributee = contributee;
}
public Map<Integer, ObjectAdapter> getContributeeAsMap() {
return contributee != null
? ImmutableMap.<Integer, ObjectAdapter>of(contributeeParam, contributee)
: ImmutableMap.<Integer, ObjectAdapter>of();
}
// //////////////////////////////////////
public void setMixedIn(final ObjectAdapter mixedInAdapter) {
this.mixedInAdapter = mixedInAdapter;
}
public ObjectAdapter getMixedIn() {
return mixedInAdapter;
}
// //////////////////////////////////////
/**
* Factory method to create corresponding {@link InteractionEvent}.
*
* @return
*/
public abstract T createInteractionEvent();
}