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.metamodel.specloader.specimpl; 021 022import java.util.List; 023 024import org.apache.isis.applib.Identifier; 025import org.apache.isis.applib.annotation.When; 026import org.apache.isis.applib.annotation.Where; 027import org.apache.isis.applib.filter.Filter; 028import org.apache.isis.core.commons.authentication.AuthenticationSession; 029import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider; 030import org.apache.isis.core.commons.lang.StringExtensions; 031import org.apache.isis.core.metamodel.adapter.ObjectAdapter; 032import org.apache.isis.core.metamodel.adapter.QuerySubmitter; 033import org.apache.isis.core.metamodel.adapter.ServicesProvider; 034import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager; 035import org.apache.isis.core.metamodel.consent.Consent; 036import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod; 037import org.apache.isis.core.metamodel.consent.InteractionResult; 038import org.apache.isis.core.metamodel.deployment.DeploymentCategory; 039import org.apache.isis.core.metamodel.facetapi.Facet; 040import org.apache.isis.core.metamodel.facetapi.FeatureType; 041import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet; 042import org.apache.isis.core.metamodel.facets.FacetedMethod; 043import org.apache.isis.core.metamodel.facets.describedas.DescribedAsFacet; 044import org.apache.isis.core.metamodel.facets.help.HelpFacet; 045import org.apache.isis.core.metamodel.facets.hide.HiddenFacet; 046import org.apache.isis.core.metamodel.facets.named.NamedFacet; 047import org.apache.isis.core.metamodel.interactions.DisablingInteractionAdvisor; 048import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor; 049import org.apache.isis.core.metamodel.interactions.InteractionUtils; 050import org.apache.isis.core.metamodel.interactions.UsabilityContext; 051import org.apache.isis.core.metamodel.interactions.VisibilityContext; 052import org.apache.isis.core.metamodel.spec.ObjectSpecification; 053import org.apache.isis.core.metamodel.spec.SpecificationLoader; 054import org.apache.isis.core.metamodel.spec.feature.ObjectMember; 055import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext; 056import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry; 057 058public abstract class ObjectMemberAbstract implements ObjectMember { 059 060 public static ObjectSpecification getSpecification(final SpecificationLoader specificationLookup, final Class<?> type) { 061 return type == null ? null : specificationLookup.loadSpecification(type); 062 } 063 064 protected final String defaultName; 065 private final String id; 066 private final FacetedMethod facetedMethod; 067 private final FeatureType featureType; 068 private final AuthenticationSessionProvider authenticationSessionProvider; 069 private final SpecificationLoader specificationLookup; 070 private final AdapterManager adapterManager; 071 private final ServicesProvider servicesProvider; 072 private final QuerySubmitter querySubmitter; 073 private final CollectionTypeRegistry collectionTypeRegistry; 074 private final DeploymentCategory deploymentCategory; 075 076 protected ObjectMemberAbstract(final FacetedMethod facetedMethod, final FeatureType featureType, final ObjectMemberContext objectMemberContext) { 077 final String id = facetedMethod.getIdentifier().getMemberName(); 078 if (id == null) { 079 throw new IllegalArgumentException("Name must always be set"); 080 } 081 this.facetedMethod = facetedMethod; 082 this.featureType = featureType; 083 this.id = id; 084 this.defaultName = StringExtensions.asNaturalName2(this.id); 085 086 this.deploymentCategory = objectMemberContext.getDeploymentCategory(); 087 this.authenticationSessionProvider = objectMemberContext.getAuthenticationSessionProvider(); 088 this.specificationLookup = objectMemberContext.getSpecificationLookup(); 089 this.adapterManager = objectMemberContext.getAdapterManager(); 090 this.servicesProvider = objectMemberContext.getServicesProvider(); 091 this.querySubmitter = objectMemberContext.getQuerySubmitter(); 092 this.collectionTypeRegistry = objectMemberContext.getCollectionTypeRegistry(); 093 } 094 095 // ///////////////////////////////////////////////////////////// 096 // from context 097 // ///////////////////////////////////////////////////////////// 098 099 public DeploymentCategory getDeploymentCategory() { 100 return deploymentCategory; 101 } 102 103 // ///////////////////////////////////////////////////////////// 104 // Identifiers 105 // ///////////////////////////////////////////////////////////// 106 107 @Override 108 public String getId() { 109 return id; 110 } 111 112 /** 113 * @return the facetedMethod 114 */ 115 public FacetedMethod getFacetedMethod() { 116 return facetedMethod; 117 } 118 119 @Override 120 public Identifier getIdentifier() { 121 return getFacetedMethod().getIdentifier(); 122 } 123 124 @Override 125 public FeatureType getFeatureType() { 126 return featureType; 127 } 128 129 // ///////////////////////////////////////////////////////////// 130 // Facets 131 // ///////////////////////////////////////////////////////////// 132 133 @Override 134 public boolean containsFacet(final Class<? extends Facet> facetType) { 135 return getFacetedMethod().containsFacet(facetType); 136 } 137 138 @Override 139 public boolean containsDoOpFacet(final Class<? extends Facet> facetType) { 140 return getFacetedMethod().containsDoOpFacet(facetType); 141 } 142 143 @Override 144 public <T extends Facet> T getFacet(final Class<T> cls) { 145 return getFacetedMethod().getFacet(cls); 146 } 147 148 @Override 149 public Class<? extends Facet>[] getFacetTypes() { 150 return getFacetedMethod().getFacetTypes(); 151 } 152 153 @Override 154 public List<Facet> getFacets(final Filter<Facet> filter) { 155 return getFacetedMethod().getFacets(filter); 156 } 157 158 @Override 159 public void addFacet(final Facet facet) { 160 getFacetedMethod().addFacet(facet); 161 } 162 163 @Override 164 public void addFacet(final MultiTypedFacet facet) { 165 getFacetedMethod().addFacet(facet); 166 } 167 168 @Override 169 public void removeFacet(final Facet facet) { 170 getFacetedMethod().removeFacet(facet); 171 } 172 173 @Override 174 public void removeFacet(final Class<? extends Facet> facetType) { 175 getFacetedMethod().removeFacet(facetType); 176 } 177 178 // ///////////////////////////////////////////////////////////// 179 // Name, Description, Help (convenience for facets) 180 // ///////////////////////////////////////////////////////////// 181 182 /** 183 * Return the default label for this member. This is based on the name of 184 * this member. 185 * 186 * @see #getId() 187 */ 188 @Override 189 public String getName() { 190 final NamedFacet facet = getFacet(NamedFacet.class); 191 final String name = facet.value(); 192 return name != null ? name : defaultName; 193 } 194 195 @Override 196 public String getDescription() { 197 final DescribedAsFacet facet = getFacet(DescribedAsFacet.class); 198 return facet.value(); 199 } 200 201 @Override 202 public String getHelp() { 203 final HelpFacet facet = getFacet(HelpFacet.class); 204 return facet.value(); 205 } 206 207 // ///////////////////////////////////////////////////////////// 208 // Hidden (or visible) 209 // ///////////////////////////////////////////////////////////// 210 211 @Override 212 public boolean isAlwaysHidden() { 213 final HiddenFacet hiddenFacet = getFacet(HiddenFacet.class); 214 return hiddenFacet != null && hiddenFacet.when() == When.ALWAYS && hiddenFacet.where() == Where.ANYWHERE; 215 } 216 217 /** 218 * Loops over all {@link HidingInteractionAdvisor} {@link Facet}s and 219 * returns <tt>true</tt> only if none hide the member. 220 * 221 * <p> 222 * TODO: currently this method is hard-coded to assume all interactions are 223 * initiated {@link InteractionInvocationMethod#BY_USER by user}. 224 */ 225 @Override 226 public Consent isVisible(final AuthenticationSession session, final ObjectAdapter target, Where where) { 227 return isVisibleResult(deploymentCategory, session, target, where).createConsent(); 228 } 229 230 private InteractionResult isVisibleResult(DeploymentCategory deploymentCategory, final AuthenticationSession session, final ObjectAdapter target, Where where) { 231 final VisibilityContext<?> ic = createVisibleInteractionContext(session, InteractionInvocationMethod.BY_USER, target, where); 232 return InteractionUtils.isVisibleResult(this, ic); 233 } 234 235 // ///////////////////////////////////////////////////////////// 236 // Disabled (or enabled) 237 // ///////////////////////////////////////////////////////////// 238 239 /** 240 * Loops over all {@link DisablingInteractionAdvisor} {@link Facet}s and 241 * returns <tt>true</tt> only if none disables the member. 242 * 243 * <p> 244 * TODO: currently this method is hard-coded to assume all interactions are 245 * initiated {@link InteractionInvocationMethod#BY_USER by user}. 246 */ 247 @Override 248 public Consent isUsable(final AuthenticationSession session, final ObjectAdapter target, Where where) { 249 return isUsableResult(session, target, where).createConsent(); 250 } 251 252 private InteractionResult isUsableResult(final AuthenticationSession session, final ObjectAdapter target, Where where) { 253 final UsabilityContext<?> ic = createUsableInteractionContext(session, InteractionInvocationMethod.BY_USER, target, where); 254 return InteractionUtils.isUsableResult(this, ic); 255 } 256 257 // ////////////////////////////////////////////////////////////////// 258 // isAssociation, isAction 259 // ////////////////////////////////////////////////////////////////// 260 261 @Override 262 public boolean isAction() { 263 return featureType.isAction(); 264 } 265 266 @Override 267 public boolean isPropertyOrCollection() { 268 return featureType.isPropertyOrCollection(); 269 } 270 271 @Override 272 public boolean isOneToManyAssociation() { 273 return featureType.isCollection(); 274 } 275 276 @Override 277 public boolean isOneToOneAssociation() { 278 return featureType.isProperty(); 279 } 280 281 // ////////////////////////////////////////////////////////////////// 282 // Convenience 283 // ////////////////////////////////////////////////////////////////// 284 285 /** 286 * The current {@link AuthenticationSession} (can change over time so do not 287 * cache). 288 */ 289 protected AuthenticationSession getAuthenticationSession() { 290 return authenticationSessionProvider.getAuthenticationSession(); 291 } 292 293 // ////////////////////////////////////////////////////////////////// 294 // toString 295 // ////////////////////////////////////////////////////////////////// 296 297 @Override 298 public String toString() { 299 return String.format("id=%s,name='%s'", getId(), getName()); 300 } 301 302 // ////////////////////////////////////////////////////////////////// 303 // Dependencies 304 // ////////////////////////////////////////////////////////////////// 305 306 public AuthenticationSessionProvider getAuthenticationSessionProvider() { 307 return authenticationSessionProvider; 308 } 309 310 public SpecificationLoader getSpecificationLookup() { 311 return specificationLookup; 312 } 313 314 public AdapterManager getAdapterManager() { 315 return adapterManager; 316 } 317 318 public ServicesProvider getServicesProvider() { 319 return servicesProvider; 320 } 321 322 public QuerySubmitter getQuerySubmitter() { 323 return querySubmitter; 324 } 325 326 public CollectionTypeRegistry getCollectionTypeRegistry() { 327 return collectionTypeRegistry; 328 } 329}