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.progmodels.dflt;
021
022import java.util.Collection;
023import java.util.Collections;
024import java.util.LinkedHashSet;
025import java.util.List;
026import java.util.Set;
027
028import com.google.common.collect.Sets;
029
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033import org.apache.isis.core.commons.config.ConfigurationConstants;
034import org.apache.isis.core.commons.config.InstallerAbstract;
035import org.apache.isis.core.commons.config.IsisConfiguration;
036import org.apache.isis.core.commons.factory.InstanceUtil;
037import org.apache.isis.core.metamodel.facetapi.ClassSubstitutorFactory;
038import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
039import org.apache.isis.core.metamodel.facetdecorator.FacetDecorator;
040import org.apache.isis.core.metamodel.facets.FacetFactory;
041import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
042import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
043import org.apache.isis.core.metamodel.specloader.FacetDecoratorInstaller;
044import org.apache.isis.core.metamodel.specloader.ObjectReflectorInstaller;
045import org.apache.isis.core.metamodel.specloader.ReflectorConstants;
046import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
047
048/**
049 * An implementation of {@link ObjectReflectorInstaller} without support for {@link FacetDecoratorInstaller}
050 * being looked up (since this functionality is only available from <tt>runtimes.dflt</tt>).
051 */
052public class JavaReflectorInstallerNoDecorators extends InstallerAbstract implements ObjectReflectorInstaller {
053
054    private static final Logger LOG = LoggerFactory.getLogger(JavaReflectorInstallerNoDecorators.class);
055
056    public static final String PROPERTY_BASE = ConfigurationConstants.ROOT;
057
058    protected final LinkedHashSet<FacetDecoratorInstaller> decoratorInstallers = Sets.newLinkedHashSet();
059
060    // /////////////////////////////////////////////////////
061    // Constructor
062    // /////////////////////////////////////////////////////
063
064    public JavaReflectorInstallerNoDecorators() {
065        this("java");
066    }
067
068    public JavaReflectorInstallerNoDecorators(final String name) {
069        super(ObjectReflectorInstaller.TYPE, name);
070        
071    }
072
073    // /////////////////////////////////////////////////////
074    // createReflector, doCreateReflector
075    // /////////////////////////////////////////////////////
076
077    /**
078     * Should call
079     * {@link #addFacetDecoratorInstaller(ReflectorDecoratorInstaller)} prior to
080     * calling this.
081     */
082    @Override
083    public SpecificationLoaderSpi createReflector(final ClassSubstitutorFactory classSubstitutorFactory, final Collection<MetaModelRefiner> metaModelRefiners) {
084
085        final ProgrammingModel programmingModel = createProgrammingModel(getConfiguration());
086        final Set<FacetDecorator> facetDecorators = createFacetDecorators(getConfiguration());
087        final MetaModelValidator mmv = createMetaModelValidator(getConfiguration());
088        
089        return JavaReflectorHelper.createObjectReflector(programmingModel, classSubstitutorFactory, metaModelRefiners, facetDecorators, mmv, getConfiguration());
090    }
091
092
093    /**
094     * Hook method to allow subclasses to specify a different implementations
095     * (that is, sets of {@link ProgrammingModel} .
096     * 
097     * <p>
098     * By default, looks up implementation from provided
099     * {@link IsisConfiguration} using
100     * {@link ReflectorConstants#PROGRAMMING_MODEL_FACETS_CLASS_NAME}. If not
101     * specified, then defaults to
102     * {@value ReflectorConstants#PROGRAMMING_MODEL_FACETS_CLASS_NAME_DEFAULT}.
103     * 
104     * <p>
105     * The list of facets can be adjusted using
106     * {@link ReflectorConstants#FACET_FACTORY_INCLUDE_CLASS_NAME_LIST} to
107     * specify additional {@link FacetFactory factories} to include, and
108     * {@link ReflectorConstants#FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST} to
109     * exclude.
110     */
111    protected ProgrammingModel createProgrammingModel(final IsisConfiguration configuration) {
112        final ProgrammingModel programmingModel = lookupAndCreateProgrammingModelFacets(configuration);
113        includeFacetFactories(configuration, programmingModel);
114        excludeFacetFactories(configuration, programmingModel);
115        return programmingModel;
116    }
117
118    private ProgrammingModel lookupAndCreateProgrammingModelFacets(final IsisConfiguration configuration) {
119        final String progModelFacetsClassName = configuration.getString(ReflectorConstants.PROGRAMMING_MODEL_FACETS_CLASS_NAME, ReflectorConstants.PROGRAMMING_MODEL_FACETS_CLASS_NAME_DEFAULT);
120        final ProgrammingModel programmingModel = InstanceUtil.createInstance(progModelFacetsClassName, ProgrammingModel.class);
121        return programmingModel;
122    }
123
124    /**
125     * Factored out of {@link #createProgrammingModel(IsisConfiguration)}
126     * so that subclasses that choose to override can still support
127     * customization of their {@link ProgrammingModel} in a similar way.
128     */
129    protected void includeFacetFactories(final IsisConfiguration configuration, final ProgrammingModel programmingModel) {
130        final String[] facetFactoriesIncludeClassNames = configuration.getList(ReflectorConstants.FACET_FACTORY_INCLUDE_CLASS_NAME_LIST);
131        if (facetFactoriesIncludeClassNames != null) {
132            for (final String facetFactoryClassName : facetFactoriesIncludeClassNames) {
133                final Class<? extends FacetFactory> facetFactory = InstanceUtil.loadClass(facetFactoryClassName, FacetFactory.class);
134                programmingModel.addFactory(facetFactory);
135            }
136        }
137    }
138
139    /**
140     * Factored out of {@link #createProgrammingModel(IsisConfiguration)}
141     * so that subclasses that choose to override can still support
142     * customization of their {@link ProgrammingModel} in a similar way.
143     */
144    protected void excludeFacetFactories(final IsisConfiguration configuration, final ProgrammingModel programmingModel) {
145        final String[] facetFactoriesExcludeClassNames = configuration.getList(ReflectorConstants.FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST);
146        for (final String facetFactoryClassName : facetFactoriesExcludeClassNames) {
147            final Class<? extends FacetFactory> facetFactory = InstanceUtil.loadClass(facetFactoryClassName, FacetFactory.class);
148            programmingModel.removeFactory(facetFactory);
149        }
150    }
151
152    /**
153     * Hook method to allow subclasses to specify a different sets of
154     * {@link FacetDecorator}s.
155     */
156    protected Set<FacetDecorator> createFacetDecorators(final IsisConfiguration configuration) {
157        return Collections.emptySet();
158    }
159
160
161    /**
162     * Hook method to allow subclasses to specify a different implementation of
163     * {@link MetaModelValidator}.
164     * 
165     * <p>
166     * By default, looks up implementation from provided
167     * {@link IsisConfiguration} using
168     * {@link ReflectorConstants#META_MODEL_VALIDATOR_CLASS_NAME}. If not
169     * specified, then defaults to
170     * {@value ReflectorConstants#META_MODEL_VALIDATOR_CLASS_NAME_DEFAULT}.
171     */
172    protected MetaModelValidator createMetaModelValidator(final IsisConfiguration configuration) {
173        final String metaModelValidatorClassName = configuration.getString(ReflectorConstants.META_MODEL_VALIDATOR_CLASS_NAME, ReflectorConstants.META_MODEL_VALIDATOR_CLASS_NAME_DEFAULT);
174        return InstanceUtil.createInstance(metaModelValidatorClassName, MetaModelValidator.class);
175    }
176
177
178
179    // /////////////////////////////////////////////////////
180    // Optionally Injected: DecoratorInstallers
181    // /////////////////////////////////////////////////////
182
183    /**
184     * Adds in {@link FacetDecoratorInstaller}; if <tt>null</tt> or if already
185     * added then request will be silently ignored.
186     */
187    @Override
188    public void addFacetDecoratorInstaller(final FacetDecoratorInstaller decoratorInstaller) {
189        if (decoratorInstaller == null) {
190            return;
191        }
192        decoratorInstallers.add(decoratorInstaller);
193    }
194
195    // /////////////////////////////////////////////////////
196    // Guice
197    // /////////////////////////////////////////////////////
198
199    @Override
200    public List<Class<?>> getTypes() {
201        return listOf(SpecificationLoaderSpi.class);
202    }
203}