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}