Package org.apache.isis.progmodels.dflt

Source Code of org.apache.isis.progmodels.dflt.JavaReflectorInstaller

/*
*  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.progmodels.dflt;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import com.google.common.collect.Lists;

import org.apache.log4j.Logger;

import org.apache.isis.core.commons.config.ConfigurationConstants;
import org.apache.isis.core.commons.config.InstallerAbstract;
import org.apache.isis.core.commons.config.IsisConfiguration;
import org.apache.isis.core.commons.factory.InstanceUtil;
import org.apache.isis.core.metamodel.facetdecorator.FacetDecorator;
import org.apache.isis.core.metamodel.facets.FacetFactory;
import org.apache.isis.core.metamodel.layout.MemberLayoutArranger;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
import org.apache.isis.core.metamodel.specloader.FacetDecoratorInstaller;
import org.apache.isis.core.metamodel.specloader.ObjectReflector;
import org.apache.isis.core.metamodel.specloader.ObjectReflectorDefault;
import org.apache.isis.core.metamodel.specloader.ObjectReflectorInstaller;
import org.apache.isis.core.metamodel.specloader.ReflectorConstants;
import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor;
import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutorComposite;
import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistryDefault;
import org.apache.isis.core.metamodel.specloader.traverser.SpecificationTraverser;
import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
import org.apache.isis.runtimes.dflt.runtime.installerregistry.InstallerLookup;
import org.apache.isis.runtimes.dflt.runtime.installerregistry.InstallerLookupAware;

public class JavaReflectorInstaller extends InstallerAbstract implements ObjectReflectorInstaller, InstallerLookupAware {

    private static final Logger LOG = Logger.getLogger(JavaReflectorInstaller.class);

    public static final String PROPERTY_BASE = ConfigurationConstants.ROOT;

    /**
     * Defaulted in the constructor.
     */
    private final LinkedHashSet<FacetDecoratorInstaller> decoratorInstallers;

    private InstallerLookup installerLookup;

    // /////////////////////////////////////////////////////
    // Constructor
    // /////////////////////////////////////////////////////

    public JavaReflectorInstaller() {
        this("java");
    }

    public JavaReflectorInstaller(final String name) {
        super(ObjectReflectorInstaller.TYPE, name);
        decoratorInstallers = new LinkedHashSet<FacetDecoratorInstaller>();
    }

    // /////////////////////////////////////////////////////
    // createReflector, doCreateReflector
    // /////////////////////////////////////////////////////

    /**
     * Should call
     * {@link #addFacetDecoratorInstaller(ReflectorDecoratorInstaller)} prior to
     * calling this.
     */
    @Override
    public ObjectReflectorDefault createReflector() {
        final ClassSubstitutor classSubstitutor = createClassSubstitutor(getConfiguration());
        final CollectionTypeRegistry collectionTypeRegistry = createCollectionTypeRegistry(getConfiguration());
        final SpecificationTraverser specificationTraverser = createSpecificationTraverser(getConfiguration());
        final MemberLayoutArranger memberLayoutArranger = createMemberLayoutArranger(getConfiguration());
        final ProgrammingModel programmingModel = createProgrammingModelFacets(getConfiguration());
        final Set<FacetDecorator> facetDecorators = createFacetDecorators(getConfiguration());
        final MetaModelValidator metaModelValidator = createMetaModelValidator(getConfiguration());

        final ObjectReflectorDefault reflector = doCreateReflector(getConfiguration(), classSubstitutor, collectionTypeRegistry, specificationTraverser, memberLayoutArranger, programmingModel, facetDecorators, metaModelValidator);

        return reflector;
    }

    /**
     * Hook method to allow subclasses to specify a different implementation of
     * {@link ClassSubstitutor}.
     *
     * <p>
     * By default, looks up implementation from provided
     * {@link IsisConfiguration} using
     * {@link ReflectorConstants#CLASS_SUBSTITUTOR_CLASS_NAME_LIST}. If not
     * specified, then defaults to
     * {@value ReflectorConstants#CLASS_SUBSTITUTOR_CLASS_NAME_DEFAULT}.
     *
     * <p>
     *
     */
    protected ClassSubstitutor createClassSubstitutor(final IsisConfiguration configuration) {
        final String[] configuredClassNames = configuration.getList(ReflectorConstants.CLASS_SUBSTITUTOR_CLASS_NAME_LIST);
        if (configuredClassNames == null || configuredClassNames.length == 0) {
            return InstanceUtil.createInstance(ReflectorConstants.CLASS_SUBSTITUTOR_CLASS_NAME_DEFAULT, ClassSubstitutor.class);
        }
        final List<ClassSubstitutor> substitutors = Lists.newArrayList();
        for (final String className : configuredClassNames) {
            final ClassSubstitutor substitutor = InstanceUtil.createInstance(className, ClassSubstitutor.class);
            substitutors.add(substitutor);
        }
        return substitutors.size() == 1 ? substitutors.get(0) : new ClassSubstitutorComposite(substitutors);
    }

    /**
     * Hook method to allow subclasses to specify a different implementation of
     * {@link SpecificationTraverser}.
     *
     * <p>
     * By default, looks up implementation from provided
     * {@link IsisConfiguration} using
     * {@link ReflectorConstants#SPECIFICATION_TRAVERSER_CLASS_NAME}. If not
     * specified, then defaults to
     * {@value ReflectorConstants#SPECIFICATION_TRAVERSER_CLASS_NAME_DEFAULT}.
     */
    protected SpecificationTraverser createSpecificationTraverser(final IsisConfiguration configuration) {
        final String specificationTraverserClassName = configuration.getString(ReflectorConstants.SPECIFICATION_TRAVERSER_CLASS_NAME, ReflectorConstants.SPECIFICATION_TRAVERSER_CLASS_NAME_DEFAULT);
        final SpecificationTraverser specificationTraverser = InstanceUtil.createInstance(specificationTraverserClassName, SpecificationTraverser.class);
        return specificationTraverser;
    }

    /**
     * Hook method to allow subclasses to specify a different implementation of
     * {@link MemberLayoutArranger}.
     *
     * <p>
     * By default, looks up implementation from provided
     * {@link IsisConfiguration} using
     * {@link ReflectorConstants#MEMBER_LAYOUT_ARRANGER_CLASS_NAME}. If not
     * specified, then defaults to
     * {@value ReflectorConstants#MEMBER_LAYOUT_ARRANGER_CLASS_NAME_DEFAULT}.
     */
    protected MemberLayoutArranger createMemberLayoutArranger(final IsisConfiguration configuration) {
        final String memberLayoutArrangerClassName = configuration.getString(ReflectorConstants.MEMBER_LAYOUT_ARRANGER_CLASS_NAME, ReflectorConstants.MEMBER_LAYOUT_ARRANGER_CLASS_NAME_DEFAULT);
        final MemberLayoutArranger memberLayoutArranger = InstanceUtil.createInstance(memberLayoutArrangerClassName, MemberLayoutArranger.class);
        return memberLayoutArranger;
    }

    /**
     * Hook method to allow subclasses to specify a different implementations
     * (that is, sets of {@link ProgrammingModel} .
     *
     * <p>
     * By default, looks up implementation from provided
     * {@link IsisConfiguration} using
     * {@link ReflectorConstants#PROGRAMMING_MODEL_FACETS_CLASS_NAME}. If not
     * specified, then defaults to
     * {@value ReflectorConstants#PROGRAMMING_MODEL_FACETS_CLASS_NAME_DEFAULT}.
     *
     * <p>
     * The list of facets can be adjusted using
     * {@link ReflectorConstants#FACET_FACTORY_INCLUDE_CLASS_NAME_LIST} to
     * specify additional {@link FacetFactory factories} to include, and
     * {@link ReflectorConstants#FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST} to
     * exclude.
     */
    protected ProgrammingModel createProgrammingModelFacets(final IsisConfiguration configuration) {
        final ProgrammingModel programmingModel = lookupAndCreateProgrammingModelFacets(configuration);
        includeFacetFactories(configuration, programmingModel);
        excludeFacetFactories(configuration, programmingModel);
        return programmingModel;
    }

    private ProgrammingModel lookupAndCreateProgrammingModelFacets(final IsisConfiguration configuration) {
        final String progModelFacetsClassName = configuration.getString(ReflectorConstants.PROGRAMMING_MODEL_FACETS_CLASS_NAME, ReflectorConstants.PROGRAMMING_MODEL_FACETS_CLASS_NAME_DEFAULT);
        final ProgrammingModel programmingModel = InstanceUtil.createInstance(progModelFacetsClassName, ProgrammingModel.class);
        return programmingModel;
    }

    /**
     * Factored out of {@link #createProgrammingModelFacets(IsisConfiguration)}
     * so that subclasses that choose to override can still support
     * customization of their {@link ProgrammingModel} in a similar way.
     */
    protected void includeFacetFactories(final IsisConfiguration configuration, final ProgrammingModel programmingModel) {
        final String[] facetFactoriesIncludeClassNames = configuration.getList(ReflectorConstants.FACET_FACTORY_INCLUDE_CLASS_NAME_LIST);
        if (facetFactoriesIncludeClassNames != null) {
            for (final String facetFactoryClassName : facetFactoriesIncludeClassNames) {
                final Class<? extends FacetFactory> facetFactory = InstanceUtil.loadClass(facetFactoryClassName, FacetFactory.class);
                programmingModel.addFactory(facetFactory);
            }
        }
    }

    /**
     * Factored out of {@link #createProgrammingModelFacets(IsisConfiguration)}
     * so that subclasses that choose to override can still support
     * customization of their {@link ProgrammingModel} in a similar way.
     */
    protected void excludeFacetFactories(final IsisConfiguration configuration, final ProgrammingModel programmingModel) {
        final String[] facetFactoriesExcludeClassNames = configuration.getList(ReflectorConstants.FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST);
        for (final String facetFactoryClassName : facetFactoriesExcludeClassNames) {
            final Class<? extends FacetFactory> facetFactory = InstanceUtil.loadClass(facetFactoryClassName, FacetFactory.class);
            programmingModel.removeFactory(facetFactory);
        }
    }

    /**
     * Hook method to allow subclasses to specify a different sets of
     * {@link FacetDecorator}s.
     *
     * <p>
     * By default, returns the {@link FacetDecorator}s that are specified in the
     * {@link IsisConfiguration} (using
     * {@link ReflectorConstants#FACET_DECORATOR_CLASS_NAMES}) along with any
     * {@link FacetDecorator}s explicitly registered using
     * {@link #addFacetDecoratorInstaller(FacetDecoratorInstaller)}. created
     * using the {@link FacetDecoratorInstaller}s.
     */
    protected Set<FacetDecorator> createFacetDecorators(final IsisConfiguration configuration) {
        addFacetDecoratorInstallers(configuration);
        return createFacetDecorators(decoratorInstallers);
    }

    private void addFacetDecoratorInstallers(final IsisConfiguration configuration) {
        final String[] decoratorNames = configuration.getList(ReflectorConstants.FACET_DECORATOR_CLASS_NAMES);
        for (final String decoratorName : decoratorNames) {
            if (LOG.isInfoEnabled()) {
                LOG.info("adding reflector facet decorator from configuration " + decoratorName);
            }
            addFacetDecoratorInstaller(lookupFacetDecorator(decoratorName));
        }
    }

    private FacetDecoratorInstaller lookupFacetDecorator(final String decoratorClassName) {
        return installerLookup.getInstaller(FacetDecoratorInstaller.class, decoratorClassName);
    }

    private Set<FacetDecorator> createFacetDecorators(final Set<FacetDecoratorInstaller> decoratorInstallers) {
        final LinkedHashSet<FacetDecorator> decorators = new LinkedHashSet<FacetDecorator>();
        if (decoratorInstallers.size() == 0) {
            if (LOG.isInfoEnabled()) {
                LOG.info("No facet decorators installers added");
            }
        }
        for (final FacetDecoratorInstaller installer : decoratorInstallers) {
            decorators.addAll(installer.createDecorators());
        }
        return Collections.unmodifiableSet(decorators);
    }

    /**
     * Hook method to allow subclasses to specify a different implementation of
     * {@link MetaModelValidator}.
     *
     * <p>
     * By default, looks up implementation from provided
     * {@link IsisConfiguration} using
     * {@link ReflectorConstants#META_MODEL_VALIDATOR_CLASS_NAME}. If not
     * specified, then defaults to
     * {@value ReflectorConstants#META_MODEL_VALIDATOR_CLASS_NAME_DEFAULT}.
     */
    protected MetaModelValidator createMetaModelValidator(final IsisConfiguration configuration) {
        final String metaModelValidatorClassName = configuration.getString(ReflectorConstants.META_MODEL_VALIDATOR_CLASS_NAME, ReflectorConstants.META_MODEL_VALIDATOR_CLASS_NAME_DEFAULT);
        final MetaModelValidator metaModelValidator = InstanceUtil.createInstance(metaModelValidatorClassName, MetaModelValidator.class);
        return metaModelValidator;
    }

    /**
     * Creates the {@link CollectionTypeRegistry}, hardcoded to be the
     * {@link CollectionTypeRegistryDefault}.
     *
     * <p>
     * Note: the intention is to remove this interface and instead to use a
     * mechanism similar to the <tt>@Value</tt> annotation to specify which
     * types represent collections. For now, have factored out this method
     * similar to be similar to the creation methods of other subcomponents such
     * as the {@link #createClassSubstitutor(IsisConfiguration)
     * ClassSubstitutor}. Note however that this method is <tt>final</tt> so
     * that it cannot be overridden.
     */
    protected final CollectionTypeRegistry createCollectionTypeRegistry(final IsisConfiguration configuration) {
        return new CollectionTypeRegistryDefault();
    }

    /**
     * Hook method to allow for other implementations (still based on
     * {@link ObjectReflectorDefault}).
     */
    protected ObjectReflectorDefault doCreateReflector(final IsisConfiguration configuration, final ClassSubstitutor classSubstitutor, final CollectionTypeRegistry collectionTypeRegistry, final SpecificationTraverser specificationTraverser, final MemberLayoutArranger memberLayoutArranger,
            final ProgrammingModel programmingModel, final Set<FacetDecorator> facetDecorators, final MetaModelValidator metaModelValidator) {
        return new ObjectReflectorDefault(configuration, classSubstitutor, collectionTypeRegistry, specificationTraverser, memberLayoutArranger, programmingModel, facetDecorators, metaModelValidator);
    }

    // /////////////////////////////////////////////////////
    // Optionally Injected: InstallerLookup
    // /////////////////////////////////////////////////////

    /**
     * Injected by virtue of being {@link InstallerLookupAware}.
     */
    @Override
    public void setInstallerLookup(final InstallerLookup installerLookup) {
        this.installerLookup = installerLookup;
    }

    // /////////////////////////////////////////////////////
    // Optionally Injected: DecoratorInstallers
    // /////////////////////////////////////////////////////

    /**
     * Adds in {@link FacetDecoratorInstaller}; if <tt>null</tt> or if already
     * added then request will be silently ignored.
     */
    @Override
    public void addFacetDecoratorInstaller(final FacetDecoratorInstaller decoratorInstaller) {
        if (decoratorInstaller == null) {
            return;
        }
        decoratorInstallers.add(decoratorInstaller);
    }

    // /////////////////////////////////////////////////////
    // Guice
    // /////////////////////////////////////////////////////

    @Override
    public List<Class<?>> getTypes() {
        return listOf(ObjectReflector.class);
    }
}
TOP

Related Classes of org.apache.isis.progmodels.dflt.JavaReflectorInstaller

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.