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.progmodel.facets.object.value.annotation;
021
022import com.google.common.base.Strings;
023
024import org.apache.isis.applib.adapters.EncoderDecoder;
025import org.apache.isis.applib.adapters.Parser;
026import org.apache.isis.applib.annotation.Value;
027import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
028import org.apache.isis.core.commons.authentication.AuthenticationSessionProviderAware;
029import org.apache.isis.core.commons.config.IsisConfiguration;
030import org.apache.isis.core.commons.config.IsisConfigurationAware;
031import org.apache.isis.core.commons.lang.StringExtensions;
032import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
033import org.apache.isis.core.metamodel.adapter.mgr.AdapterManagerAware;
034import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
035import org.apache.isis.core.metamodel.facetapi.FacetHolder;
036import org.apache.isis.core.metamodel.facetapi.FacetUtil;
037import org.apache.isis.core.metamodel.facetapi.FeatureType;
038import org.apache.isis.core.metamodel.facets.Annotations;
039import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
040import org.apache.isis.core.metamodel.facets.ebc.EqualByContentFacet;
041import org.apache.isis.core.metamodel.facets.object.aggregated.ParentedFacet;
042import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
043import org.apache.isis.core.metamodel.facets.object.icon.IconFacet;
044import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet;
045import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
046import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
047import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
048import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
049import org.apache.isis.core.metamodel.runtimecontext.RuntimeContextAware;
050import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
051import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
052import org.apache.isis.core.progmodel.facets.object.value.ValueFacetFromConfiguration;
053import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderContext;
054import org.apache.isis.core.progmodel.facets.object.value.ValueSemanticsProviderUtil;
055
056/**
057 * Processes the {@link Value} annotation.
058 * 
059 * <p>
060 * As a result, will always install the following facets:
061 * <ul>
062 * <li> {@link TitleFacet} - based on the <tt>title()</tt> method if present,
063 * otherwise uses <tt>toString()</tt></li>
064 * <li> {@link IconFacet} - based on the <tt>iconName()</tt> method if present,
065 * otherwise derived from the class name</li>
066 * </ul>
067 * <p>
068 * In addition, the following facets may be installed:
069 * <ul>
070 * <li> {@link ParseableFacet} - if a {@link Parser} has been specified
071 * explicitly in the annotation (or is picked up through an external
072 * configuration file)</li>
073 * <li> {@link EncodableFacet} - if an {@link EncoderDecoder} has been specified
074 * explicitly in the annotation (or is picked up through an external
075 * configuration file)</li>
076 * <li> {@link ImmutableFacet} - if specified explicitly in the annotation
077 * <li> {@link EqualByContentFacet} - if specified explicitly in the annotation
078 * </ul>
079 * <p>
080 * Note that {@link ParentedFacet} is <i>not</i> installed.
081 */
082public class ValueFacetFactory extends FacetFactoryAbstract implements IsisConfigurationAware, AuthenticationSessionProviderAware, AdapterManagerAware, ServicesInjectorAware, RuntimeContextAware {
083
084    private IsisConfiguration configuration;
085    private RuntimeContext runtimeContext;
086    private AuthenticationSessionProvider authenticationSessionProvider;
087    private AdapterManager adapterManager;
088    private ServicesInjector servicesInjector;
089
090    public ValueFacetFactory() {
091        super(FeatureType.OBJECTS_ONLY);
092    }
093
094    @Override
095    public void process(final ProcessClassContext processClassContaxt) {
096        FacetUtil.addFacet(create(processClassContaxt.getCls(), processClassContaxt.getFacetHolder()));
097    }
098
099    /**
100     * Returns a {@link ValueFacet} implementation.
101     */
102    private ValueFacet create(final Class<?> cls, final FacetHolder holder) {
103
104        // create from annotation, if present
105        final Value annotation = Annotations.getAnnotation(cls, Value.class);
106        if (annotation != null) {
107            final ValueFacetAnnotation facet = new ValueFacetAnnotation(cls, holder, getIsisConfiguration(), createValueSemanticsProviderContext());
108            if (facet.isValid()) {
109                return facet;
110            }
111        }
112
113        // otherwise, try to create from configuration, if present
114        final String semanticsProviderName = ValueSemanticsProviderUtil.semanticsProviderNameFromConfiguration(cls, configuration);
115        if (!Strings.isNullOrEmpty(semanticsProviderName)) {
116            final ValueFacetFromConfiguration facet = new ValueFacetFromConfiguration(semanticsProviderName, holder, getIsisConfiguration(), createValueSemanticsProviderContext());
117            if (facet.isValid()) {
118                return facet;
119            }
120        }
121
122        // otherwise, no value semantic
123        return null;
124    }
125
126    protected ValueSemanticsProviderContext createValueSemanticsProviderContext() {
127        return new ValueSemanticsProviderContext(getDeploymentCategory(), getAuthenticationSessionProvider(), getSpecificationLoader(), getAdapterManager(), getServicesInjector());
128    }
129
130    // ////////////////////////////////////////////////////////////////////
131    // Injected
132    // ////////////////////////////////////////////////////////////////////
133
134    /**
135     * Derived from {@link #setRuntimeContext(RuntimeContext)} (since {@link RuntimeContextAware}).
136     */
137    private DeploymentCategory getDeploymentCategory() {
138        return runtimeContext.getDeploymentCategory();
139    }
140
141    public IsisConfiguration getIsisConfiguration() {
142        return configuration;
143    }
144
145    @Override
146    public void setConfiguration(final IsisConfiguration configuration) {
147        this.configuration = configuration;
148    }
149
150    public AuthenticationSessionProvider getAuthenticationSessionProvider() {
151        return authenticationSessionProvider;
152    }
153
154    @Override
155    public void setAuthenticationSessionProvider(final AuthenticationSessionProvider authenticationSessionProvider) {
156        this.authenticationSessionProvider = authenticationSessionProvider;
157    }
158
159    public AdapterManager getAdapterManager() {
160        return adapterManager;
161    }
162
163    @Override
164    public void setAdapterManager(final AdapterManager adapterManager) {
165        this.adapterManager = adapterManager;
166    }
167
168    public ServicesInjector getServicesInjector() {
169        return servicesInjector;
170    }
171
172    @Override
173    public void setServicesInjector(final ServicesInjector dependencyInjector) {
174        this.servicesInjector = dependencyInjector;
175    }
176
177    @Override
178    public void setRuntimeContext(RuntimeContext runtimeContext) {
179        this.runtimeContext = runtimeContext;
180    }
181
182}