/***************************************************************** * 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.cayenne.reflect; import java.util.Collection; import org.apache.cayenne.exp.Expression; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.EntityInheritanceTree; import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.util.ToStringBuilder; /** * A ClassDescriptor wrapper that compiles decorated descriptor lazily on first access. * * @since 3.0 */ public class LazyClassDescriptorDecorator implements ClassDescriptor { protected ClassDescriptor descriptor; protected ClassDescriptorMap descriptorMap; protected String entityName; public LazyClassDescriptorDecorator(ClassDescriptorMap descriptorMap, String entityName) { this.descriptorMap = descriptorMap; this.entityName = entityName; } @Override public String toString() { return new ToStringBuilder(this).append("entity", entityName).toString(); } /** * Checks whether decorated descriptor is initialized, and if not, creates it using * parent {@link ClassDescriptorMap}. */ protected void checkDescriptorInitialized() { if (descriptor == null) { descriptor = descriptorMap.createDescriptor(entityName); } } /** * Returns underlying descriptor used to delegate all processing, resolving it if * needed. */ public ClassDescriptor getDescriptor() { checkDescriptorInitialized(); return descriptor; } public Object createObject() { checkDescriptorInitialized(); return descriptor.createObject(); } public PropertyDescriptor getDeclaredProperty(String propertyName) { checkDescriptorInitialized(); return descriptor.getDeclaredProperty(propertyName); } public ObjEntity getEntity() { checkDescriptorInitialized(); return descriptor.getEntity(); } public Collection<DbEntity> getRootDbEntities() { checkDescriptorInitialized(); return descriptor.getRootDbEntities(); } public EntityInheritanceTree getEntityInheritanceTree() { checkDescriptorInitialized(); return descriptor.getEntityInheritanceTree(); } public boolean hasSubclasses() { checkDescriptorInitialized(); return descriptor.hasSubclasses(); } public Class<?> getObjectClass() { // note that we can resolve Object class without triggering descriptor resolution. // This is very helpful when compiling POJO relationships if (descriptor == null) { ObjEntity entity = descriptorMap.getResolver().getObjEntity(entityName); if (entity != null) { return entity.getJavaClass(); } } checkDescriptorInitialized(); return descriptor.getObjectClass(); } public Collection<AttributeProperty> getIdProperties() { checkDescriptorInitialized(); return descriptor.getIdProperties(); } public Collection<ObjAttribute> getDiscriminatorColumns() { checkDescriptorInitialized(); return descriptor.getDiscriminatorColumns(); } public Expression getEntityQualifier() { checkDescriptorInitialized(); return descriptor.getEntityQualifier(); } public Collection<ArcProperty> getMapArcProperties() { checkDescriptorInitialized(); return descriptor.getMapArcProperties(); } public PropertyDescriptor getProperty(String propertyName) { checkDescriptorInitialized(); return descriptor.getProperty(propertyName); } public ClassDescriptor getSubclassDescriptor(Class<?> objectClass) { checkDescriptorInitialized(); return descriptor.getSubclassDescriptor(objectClass); } public ClassDescriptor getSuperclassDescriptor() { checkDescriptorInitialized(); return descriptor.getSuperclassDescriptor(); } public void injectValueHolders(Object object) throws PropertyException { checkDescriptorInitialized(); descriptor.injectValueHolders(object); } public boolean isFault(Object object) { checkDescriptorInitialized(); return descriptor.isFault(object); } public void shallowMerge(Object from, Object to) throws PropertyException { checkDescriptorInitialized(); descriptor.shallowMerge(from, to); } public boolean visitDeclaredProperties(PropertyVisitor visitor) { checkDescriptorInitialized(); return descriptor.visitDeclaredProperties(visitor); } public boolean visitProperties(PropertyVisitor visitor) { checkDescriptorInitialized(); return descriptor.visitProperties(visitor); } public boolean visitAllProperties(PropertyVisitor visitor) { checkDescriptorInitialized(); return descriptor.visitAllProperties(visitor); } }