001/**
002 *  Licensed to the Apache Software Foundation (ASF) under one or more
003 *  contributor license agreements.  See the NOTICE file distributed with
004 *  this work for additional information regarding copyright ownership.
005 *  The ASF licenses this file to You under the Apache License, Version 2.0
006 *  (the "License"); you may not use this file except in compliance with
007 *  the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 */
017package org.apache.isis.core.metamodel.specloader.specimpl;
018
019import java.util.List;
020
021import org.apache.isis.applib.Identifier;
022import org.apache.isis.applib.annotation.When;
023import org.apache.isis.applib.annotation.Where;
024import org.apache.isis.applib.filter.Filter;
025import org.apache.isis.core.commons.authentication.AuthenticationSession;
026import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
027import org.apache.isis.core.metamodel.consent.Consent;
028import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
029import org.apache.isis.core.metamodel.facetapi.Facet;
030import org.apache.isis.core.metamodel.facetapi.FacetHolder;
031import org.apache.isis.core.metamodel.facetapi.FacetHolderImpl;
032import org.apache.isis.core.metamodel.facetapi.FacetUtil;
033import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
034import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacet;
035import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacetAbstract;
036import org.apache.isis.core.metamodel.interactions.InteractionUtils;
037import org.apache.isis.core.metamodel.interactions.UsabilityContext;
038import org.apache.isis.core.metamodel.interactions.VisibilityContext;
039import org.apache.isis.core.metamodel.spec.ObjectSpecification;
040import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
041import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
042import org.apache.isis.core.progmodel.facets.members.disabled.DisabledFacet;
043import org.apache.isis.core.progmodel.facets.members.disabled.DisabledFacetImpl;
044
045public class OneToOneAssociationContributee extends OneToOneAssociationImpl implements ContributeeMember {
046
047    private final ObjectAdapter serviceAdapter;
048    private final ObjectAction serviceAction;
049    
050
051    /**
052     * Hold facets rather than delegate to the contributed action (different types might
053     * use layout metadata to position the contributee in different ways)
054     */
055    private final FacetHolder facetHolder = new FacetHolderImpl();
056    
057    private final Identifier identifier;
058
059    public OneToOneAssociationContributee(
060            final ObjectAdapter serviceAdapter, 
061            final ObjectActionImpl serviceAction, 
062            final ObjectSpecification contributeeType,
063            final ObjectMemberContext objectMemberContext) {
064        super(serviceAction.getFacetedMethod(), serviceAction.getReturnType(), objectMemberContext);
065        this.serviceAdapter = serviceAdapter;
066        this.serviceAction = serviceAction;
067        
068        // copy over facets from contributed to own.
069        FacetUtil.copyFacets(serviceAction.getFacetedMethod(), facetHolder);
070        
071        final NotPersistedFacet notPersistedFacet = new NotPersistedFacetAbstract(this) {};
072        final DisabledFacet disabledFacet = disabledFacet();
073        
074        FacetUtil.addFacet(notPersistedFacet);
075        FacetUtil.addFacet(disabledFacet);
076        
077        // calculate the identifier
078        final Identifier contributorIdentifier = serviceAction.getFacetedMethod().getIdentifier();
079        final String memberName = contributorIdentifier.getMemberName();
080        List<String> memberParameterNames = contributorIdentifier.getMemberParameterNames();
081        
082        identifier = Identifier.actionIdentifier(contributeeType.getCorrespondingClass().getName(), memberName, memberParameterNames);
083    }
084
085    private DisabledFacet disabledFacet() {
086        final DisabledFacet originalFacet = facetHolder.getFacet(DisabledFacet.class);
087        if( originalFacet != null && 
088            originalFacet.when() == When.ALWAYS && 
089            originalFacet.where() == Where.ANYWHERE) {
090            return originalFacet;
091        }
092        // ensure that the contributed association is always disabled
093        return new DisabledFacetImpl(When.ALWAYS, Where.ANYWHERE, "Contributed property", this);
094    }
095
096    @Override
097    public ObjectAdapter get(final ObjectAdapter ownerAdapter) {
098        return serviceAction.execute(serviceAdapter, new ObjectAdapter[]{ownerAdapter});
099    }
100
101    @Override
102    public Identifier getIdentifier() {
103        return identifier;
104    }
105    
106    
107    @Override
108    public Consent isVisible(final AuthenticationSession session, final ObjectAdapter contributee, Where where) {
109        final VisibilityContext<?> ic = serviceAction.createVisibleInteractionContext(session, InteractionInvocationMethod.BY_USER, serviceAdapter, where);
110        ic.putContributee(0, contributee); // by definition, the contributee will be the first arg of the service action
111        return InteractionUtils.isVisibleResult(this, ic).createConsent();
112    }
113
114    @Override
115    public Consent isUsable(final AuthenticationSession session, final ObjectAdapter contributee, Where where) {
116        final UsabilityContext<?> ic = serviceAction.createUsableInteractionContext(session, InteractionInvocationMethod.BY_USER, serviceAdapter, where);
117        ic.putContributee(0, contributee); // by definition, the contributee will be the first arg of the service action
118        return InteractionUtils.isUsableResult(this, ic).createConsent();
119    }
120
121    
122    // //////////////////////////////////////
123    // FacetHolder
124    // //////////////////////////////////////
125    
126    @Override
127    public Class<? extends Facet>[] getFacetTypes() {
128        return facetHolder.getFacetTypes();
129    }
130
131    @Override
132    public <T extends Facet> T getFacet(Class<T> cls) {
133        return facetHolder.getFacet(cls);
134    }
135
136    @Override
137    public boolean containsFacet(Class<? extends Facet> facetType) {
138        return facetHolder.containsFacet(facetType);
139    }
140
141    @Override
142    public boolean containsDoOpFacet(java.lang.Class<? extends Facet> facetType) {
143        return facetHolder.containsDoOpFacet(facetType);
144    }
145
146    @Override
147    public List<Facet> getFacets(Filter<Facet> filter) {
148        return facetHolder.getFacets(filter);
149    }
150
151    @Override
152    public void addFacet(Facet facet) {
153        facetHolder.addFacet(facet);
154    }
155
156    @Override
157    public void addFacet(MultiTypedFacet facet) {
158        facetHolder.addFacet(facet);
159    }
160    
161    @Override
162    public void removeFacet(Facet facet) {
163        facetHolder.removeFacet(facet);
164    }
165
166    @Override
167    public void removeFacet(Class<? extends Facet> facetType) {
168        facetHolder.removeFacet(facetType);
169    }
170
171}