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.spec; 021 022import java.util.Collections; 023import java.util.Comparator; 024import java.util.List; 025 026import com.google.common.base.Function; 027 028import org.apache.isis.applib.annotation.ObjectType; 029import org.apache.isis.applib.filter.Filter; 030import org.apache.isis.applib.profiles.Localization; 031import org.apache.isis.core.commons.authentication.AuthenticationSession; 032import org.apache.isis.core.metamodel.adapter.ObjectAdapter; 033import org.apache.isis.core.metamodel.consent.Consent; 034import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod; 035import org.apache.isis.core.metamodel.consent.InteractionResult; 036import org.apache.isis.core.metamodel.deployment.DeploymentCategory; 037import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet; 038import org.apache.isis.core.metamodel.facets.describedas.DescribedAsFacet; 039import org.apache.isis.core.metamodel.facets.help.HelpFacet; 040import org.apache.isis.core.metamodel.facets.hide.HiddenFacet; 041import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet; 042import org.apache.isis.core.metamodel.facets.named.NamedFacet; 043import org.apache.isis.core.metamodel.facets.object.aggregated.ParentedFacet; 044import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet; 045import org.apache.isis.core.metamodel.facets.object.icon.IconFacet; 046import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet; 047import org.apache.isis.core.metamodel.facets.object.objecttype.ObjectSpecIdFacet; 048import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet; 049import org.apache.isis.core.metamodel.facets.object.plural.PluralFacet; 050import org.apache.isis.core.metamodel.facets.object.title.TitleFacet; 051import org.apache.isis.core.metamodel.facets.object.value.ValueFacet; 052import org.apache.isis.core.metamodel.interactions.InteractionContext; 053import org.apache.isis.core.metamodel.interactions.ObjectTitleContext; 054import org.apache.isis.core.metamodel.interactions.ObjectValidityContext; 055import org.apache.isis.core.metamodel.spec.feature.ObjectActionContainer; 056import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; 057import org.apache.isis.core.metamodel.spec.feature.ObjectAssociationContainer; 058import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor; 059 060/** 061 * Represents an entity or value (cf {@link java.lang.Class}) within the 062 * metamodel. 063 * 064 * <p> 065 * As specifications are cyclic (specifically a class will reference its 066 * subclasses, which in turn reference their superclass) they need be created 067 * first, and then later work out its internals. Hence we create 068 * {@link ObjectSpecification}s as we need them, and then introspect them later. 069 */ 070public interface ObjectSpecification extends Specification, ObjectActionContainer, ObjectAssociationContainer, Hierarchical, Dirtiable, DefaultProvider { 071 072 public final static List<ObjectSpecification> EMPTY_LIST = Collections.emptyList(); 073 074 public final static Function<ObjectSpecification, String> FUNCTION_FULLY_QUALIFIED_CLASS_NAME = new Function<ObjectSpecification, String>() { 075 @Override 076 public String apply(final ObjectSpecification from) { 077 return from.getFullIdentifier(); 078 } 079 }; 080 public final static Comparator<ObjectSpecification> COMPARATOR_FULLY_QUALIFIED_CLASS_NAME = new Comparator<ObjectSpecification>() { 081 @Override 082 public int compare(final ObjectSpecification o1, final ObjectSpecification o2) { 083 return o1.getFullIdentifier().compareTo(o2.getFullIdentifier()); 084 } 085 }; 086 public final static Comparator<ObjectSpecification> COMPARATOR_SHORT_IDENTIFIER_IGNORE_CASE = new Comparator<ObjectSpecification>() { 087 @Override 088 public int compare(final ObjectSpecification s1, final ObjectSpecification s2) { 089 return s1.getShortIdentifier().compareToIgnoreCase(s2.getShortIdentifier()); 090 } 091 }; 092 093 /** 094 * @return 095 */ 096 Class<?> getCorrespondingClass(); 097 098 /** 099 * Returns the (unique) spec Id, as per the {@link ObjectSpecIdFacet}. 100 * 101 * <p> 102 * This will typically be the value of the {@link ObjectType} annotation (or equivalent); 103 * if non has been specified then will default to the fully qualified class name (with 104 * {@link ClassSubstitutor class name substituted} if necessary to allow for runtime bytecode enhancement. 105 * 106 * <p> 107 * The {@link ObjectSpecification} can be retrieved using {@link SpecificationLoader#lookupBySpecId(ObjectSpecId)}. 108 */ 109 ObjectSpecId getSpecId(); 110 111 /** 112 * Returns an (immutable) "full" identifier for this specification. 113 * 114 * <p> 115 * This will be the fully qualified name of the Class object that this 116 * object represents (i.e. it includes the package name). 117 */ 118 String getFullIdentifier(); 119 120 /** 121 * Returns an (immutable) "short" identifier for this specification. 122 * 123 * <p> 124 * This will be the class name without the package; any text up to and 125 * including the last period is removed. 126 */ 127 String getShortIdentifier(); 128 129 /** 130 * Returns the (singular) name for objects of this specification. 131 * 132 * <p> 133 * Corresponds to the {@link NamedFacet#value()} of {@link NamedFacet}; is 134 * not necessarily immutable. 135 */ 136 String getSingularName(); 137 138 /** 139 * Returns the plural name for objects of this specification. 140 * 141 * <p> 142 * Corresponds to the {@link PluralFacet#value() value} of 143 * {@link PluralFacet}; is not necessarily immutable. 144 */ 145 String getPluralName(); 146 147 /** 148 * Returns the description, if any, of the specification. 149 * 150 * <p> 151 * Corresponds to the {@link DescribedAsFacet#value()) value} of 152 * {@link DescribedAsFacet}; is not necessarily immutable. 153 */ 154 @Override 155 String getDescription(); 156 157 /** 158 * Returns a help string or lookup reference, if any, of the specification. 159 * 160 * <p> 161 * Corresponds to the {@link HelpFacet#value()) value} of {@link HelpFacet}; 162 * is not necessarily immutable. 163 */ 164 String getHelp(); 165 166 /** 167 * Returns a css class name of the specification. 168 * 169 * <p> 170 * Corresponds to the {@link CssClass#value()) value} of {@link CssClassFacet}; 171 */ 172 String getCssClass(); 173 174 /** 175 * Returns the title string for the specified object. 176 * 177 * <p> 178 * Corresponds to the {@link TitleFacet#value()) value} of 179 * {@link TitleFacet}; is not necessarily immutable. 180 * 181 * @deprecated use {@link #getTitle(ObjectAdapter, ObjectAdapter, Localization)} 182 */ 183 @Deprecated 184 String getTitle(ObjectAdapter adapter, Localization localization); 185 186 /** 187 * Returns the title to display of target adapter, rendered within the context 188 * of some other adapter (if any). 189 * 190 * <p> 191 * @see TitleFacet#title(ObjectAdapter, ObjectAdapter, org.apache.isis.applib.profiles.Localization) 192 */ 193 String getTitle(ObjectAdapter contextAdapterIfAny, ObjectAdapter targetAdapter, Localization localization); 194 195 /** 196 * Returns the name of an icon to use for the specified object. 197 * 198 * <p> 199 * Corresponds to the {@link IconFacet#iconName(ObjectAdapter)) icon name} 200 * returned by the {@link IconFacet}; is not necessarily immutable. 201 */ 202 String getIconName(ObjectAdapter object); 203 204 boolean isAbstract(); 205 206 // ////////////////////////////////////////////////////////////// 207 // TitleContext 208 // ////////////////////////////////////////////////////////////// 209 210 /** 211 * Create an {@link InteractionContext} representing an attempt to read the 212 * object's title. 213 */ 214 ObjectTitleContext createTitleInteractionContext(AuthenticationSession session, InteractionInvocationMethod invocationMethod, ObjectAdapter targetObjectAdapter); 215 216 // ////////////////////////////////////////////////////////////// 217 // ValidityContext, Validity 218 // ////////////////////////////////////////////////////////////// 219 220 /** 221 * Create an {@link InteractionContext} representing an attempt to save the 222 * object. 223 * @param deploymentCategory TODO 224 */ 225 ObjectValidityContext createValidityInteractionContext(DeploymentCategory deploymentCategory, AuthenticationSession session, InteractionInvocationMethod invocationMethod, ObjectAdapter targetObjectAdapter); 226 227 /** 228 * Determines whether the specified object is in a valid state (for example, 229 * so can be persisted); represented as a {@link Consent}. 230 */ 231 Consent isValid(ObjectAdapter adapter); 232 233 /** 234 * Determines whether the specified object is in a valid state (for example, 235 * so can be persisted); represented as a {@link InteractionResult}. 236 */ 237 InteractionResult isValidResult(ObjectAdapter adapter); 238 239 // ////////////////////////////////////////////////////////////// 240 // Facets 241 // ////////////////////////////////////////////////////////////// 242 243 /** 244 * Determines if objects of this specification can be persisted or not. If 245 * it can be persisted (i.e. it return something other than 246 * {@link Persistability}.TRANSIENT ObjectAdapter.isPersistent() will 247 * indicated whether the object is persistent or not. If they cannot be 248 * persisted then {@link ObjectAdapter}. {@link #persistability()} should be 249 * ignored. 250 */ 251 Persistability persistability(); 252 253 /** 254 * Determines if the object represents an value or object. 255 * 256 * <p> 257 * In effect, means that it doesn't have the {@link CollectionFacet}, and 258 * therefore will return NOT {@link #isParentedOrFreeCollection()} 259 * 260 * @see #isCollection(). 261 */ 262 boolean isNotCollection(); 263 264 /** 265 * Determines if objects of this type are a parented (internal) or free-standing (external) collection. 266 * 267 * <p> 268 * In effect, means has got {@link CollectionFacet}, and therefore will 269 * return NOT {@link #isNotCollection()}. 270 * 271 * @see #isNotCollection() 272 */ 273 boolean isParentedOrFreeCollection(); 274 275 /** 276 * Determines if objects of this type are values. 277 * 278 * <p> 279 * In effect, means has got {@link ValueFacet}. 280 */ 281 boolean isValue(); 282 283 /** 284 * Determines if objects of this type are parented (a parented collection, or an aggregated entity). 285 * 286 * <p> 287 * In effect, means has got {@link ParentedFacet}. 288 */ 289 boolean isParented(); 290 291 /** 292 * Determines if objects of this type are either values or aggregated. 293 * 294 * @see #isValue() 295 * @see #isParented() 296 */ 297 boolean isValueOrIsParented(); 298 299 /** 300 * Determines if objects of this type can be set up from a text entry 301 * string. 302 * 303 * <p> 304 * In effect, means has got a {@link ParseableFacet}. 305 */ 306 boolean isParseable(); 307 308 /** 309 * Determines if objects of this type can be converted to a data-stream. 310 * 311 * <p> 312 * In effect, means has got {@link EncodableFacet}. 313 */ 314 boolean isEncodeable(); 315 316 /** 317 * Whether has the {@link ImmutableFacet}. 318 */ 319 boolean isImmutable(); 320 321 /** 322 * Whether has the {@link HiddenFacet} 323 */ 324 boolean isHidden(); 325 326 // ////////////////////////////////////////////////////////////// 327 // Creation 328 // ////////////////////////////////////////////////////////////// 329 330 Object createObject(); 331 332 /** 333 * REVIEW: should this behaviour move, eg onto ObjectAdapter? 334 */ 335 ObjectAdapter initialize(ObjectAdapter object); 336 337 338 339 // ////////////////////////////////////////////////////////////// 340 // Service 341 // ////////////////////////////////////////////////////////////// 342 343 /** 344 * Whether or not this specification represents a domain service (as opposed 345 * to a domain entity or a value etc). 346 * 347 * <p> 348 * <b>WARNING</b>: this only returns <tt>true</tt> once the metamodel has been 349 * fully built, and a <tt>PersistenceSession</tt> has been opened. This should 350 * probably be improved upon; for now, beware... 351 */ 352 boolean isService(); 353 354 public void markAsService(); 355 356 357 358 359 360 361 362}