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