001    /**
002     * Copyright 2005-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.krad.service.impl;
017    
018    import org.apache.ojb.broker.metadata.ClassDescriptor;
019    import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
020    import org.apache.ojb.broker.metadata.DescriptorRepository;
021    import org.apache.ojb.broker.metadata.FieldDescriptor;
022    import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
023    import org.kuali.rice.core.api.config.property.ConfigContext;
024    import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
025    import org.kuali.rice.core.framework.persistence.jpa.metadata.EntityDescriptor;
026    import org.kuali.rice.core.framework.persistence.jpa.metadata.MetadataManager;
027    import org.kuali.rice.core.framework.persistence.jpa.metadata.ObjectDescriptor;
028    import org.kuali.rice.core.framework.persistence.ojb.BaseOjbConfigurer;
029    import org.kuali.rice.krad.bo.PersistableBusinessObject;
030    import org.kuali.rice.krad.bo.PersistableBusinessObjectExtension;
031    import org.kuali.rice.krad.exception.ClassNotPersistableException;
032    
033    import java.util.ArrayList;
034    import java.util.List;
035    
036    public class PersistenceServiceStructureImplBase {
037    
038            private DescriptorRepository descriptorRepository;
039    
040            /**
041             * Constructs a PersistenceServiceImpl instance.
042             */
043            public PersistenceServiceStructureImplBase() {
044                    String ojbPropertyFileLocation = ConfigContext.getCurrentContextConfig().getProperty(BaseOjbConfigurer.RICE_OJB_PROPERTIES_PARAM);
045            String currentValue = System.getProperty(BaseOjbConfigurer.OJB_PROPERTIES_PROP);
046                    try {
047                            System.setProperty(BaseOjbConfigurer.OJB_PROPERTIES_PROP, ojbPropertyFileLocation);
048                            org.apache.ojb.broker.metadata.MetadataManager metadataManager = org.apache.ojb.broker.metadata.MetadataManager.getInstance();
049                            descriptorRepository = metadataManager.getGlobalRepository();
050                } finally {
051                    if (currentValue == null) {
052                        System.getProperties().remove(BaseOjbConfigurer.OJB_PROPERTIES_PROP);
053                    } else {
054                        System.setProperty(BaseOjbConfigurer.OJB_PROPERTIES_PROP, currentValue);
055                    }
056                }
057            }
058    
059            /**
060             * @return DescriptorRepository containing everything OJB knows about persistable classes
061             */
062            protected DescriptorRepository getDescriptorRepository() {
063                    return descriptorRepository;
064            }
065    
066            /**
067             *
068             * This method returns a list of primary key field names.  This method uses the CacheNoCopy caching method.
069             * "NoCopy" is the faster of the caching annotations, but because it does not make a copy the list that is
070             * returned must not be modified.  To enforce this the returned list is wrapped in a Collections.unmodifiableList
071             * method.  This will cause an exception to be thrown if the list is altered.
072             *
073             * @param clazz
074             * @return unmodifiableList of field names.  Any attempt to alter list will result in an UnsupportedOperationException
075             */
076            public List listPrimaryKeyFieldNames(Class clazz) {
077            // Rice JPA MetadataManager
078                    if (isJpaEnabledForKradClass(clazz)) {
079                            List fieldNames = new ArrayList();
080                    EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(clazz);
081                    for (org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor field : descriptor.getPrimaryKeys()) {
082                            fieldNames.add(field.getName());
083                    }
084                    return fieldNames;
085                    } else {
086                    // Legacy OJB
087                            List fieldNamesLegacy = new ArrayList();
088                            ClassDescriptor classDescriptor = getClassDescriptor(clazz);
089                            FieldDescriptor keyDescriptors[] = classDescriptor.getPkFields();
090    
091                            for (int i = 0; i < keyDescriptors.length; ++i) {
092                                    FieldDescriptor keyDescriptor = keyDescriptors[i];
093                                    fieldNamesLegacy.add(keyDescriptor.getAttributeName());
094                            }
095                            return fieldNamesLegacy;
096                    }
097            }
098    
099            /* Not used anywhere... need to check KFS and batch stuff */
100            /**
101             * @param classDescriptor
102             * @return name of the database table associated with given classDescriptor,
103             *         stripped of its leading schemaName
104             */
105            /*
106            @CacheNoCopy
107            protected String getTableName(ClassDescriptor classDescriptor) {
108                    String schemaName = classDescriptor.getSchema();
109                    String fullTableName = classDescriptor.getFullTableName();
110    
111                    String tableName = null;
112                    if (StringUtils.isNotBlank(schemaName)) {
113                            tableName = StringUtils.substringAfter(fullTableName, schemaName + ".");
114                    }
115                    if (StringUtils.isBlank(tableName)) {
116                            tableName = fullTableName;
117                    }
118    
119                    return tableName;
120            }
121            */
122    
123            /**
124             * @param persistableClass
125             * @return ClassDescriptor for the given Class
126             * @throws IllegalArgumentException
127             *             if the given Class is null
128             * @throws ClassNotPersistableException
129             *             if the given Class is unknown to OJB
130             */
131            // Legacy OJB - no need for JPA equivalent
132            protected ClassDescriptor getClassDescriptor(Class persistableClass) {
133                    if (persistableClass == null) {
134                            throw new IllegalArgumentException("invalid (null) object");
135                    }
136    
137                    ClassDescriptor classDescriptor = null;
138                    DescriptorRepository globalRepository = getDescriptorRepository();
139                    try {
140                            classDescriptor = globalRepository.getDescriptorFor(persistableClass);
141                    } catch (ClassNotPersistenceCapableException e) {
142                            throw new ClassNotPersistableException("class '" + persistableClass.getName() + "' is not persistable", e);
143                    }
144    
145                    return classDescriptor;
146            }
147            
148            /**
149             * Determines if JPA is enabled for the KNS and for the given class
150             * 
151             * @param clazz the class to check for JPA enabling of
152             * @return true if JPA is enabled for the class, false otherwise
153             */
154            public boolean isJpaEnabledForKradClass(Class clazz) {
155                    final boolean jpaAnnotated = OrmUtils.isJpaAnnotated(clazz);
156                    final boolean jpaEnabled = OrmUtils.isJpaEnabled();
157                    final boolean prefixJpaEnabled = OrmUtils.isJpaEnabled("rice.krad");
158                    return jpaAnnotated && (jpaEnabled || prefixJpaEnabled);
159            }
160    
161            /**
162             * @see org.kuali.rice.krad.service.PersistenceStructureService#getBusinessObjectAttributeClass(java.lang.Class,
163             *      java.lang.String)
164             */
165            public Class<? extends PersistableBusinessObjectExtension> getBusinessObjectAttributeClass(Class<? extends PersistableBusinessObject> clazz, String attributeName) {
166                    String baseAttributeName = attributeName;
167                    String subAttributeString = null;
168                    if (attributeName.contains(".")) {
169                            baseAttributeName = attributeName.substring(0, attributeName.indexOf('.'));
170                            subAttributeString = attributeName.substring(attributeName.indexOf('.') + 1);
171                    }
172    
173            // Rice JPA MetadataManager
174                    if (isJpaEnabledForKradClass(clazz)) {
175                            Class attributeClass = null;
176                    EntityDescriptor descriptor = MetadataManager.getEntityDescriptor(clazz);
177                    ObjectDescriptor objectDescriptor = descriptor.getObjectDescriptorByName(baseAttributeName);
178                            if (objectDescriptor != null) {
179                                    attributeClass = objectDescriptor.getTargetEntity();
180                            }
181    
182                            // recurse if necessary
183                            if (subAttributeString != null) {
184                                    attributeClass = getBusinessObjectAttributeClass(attributeClass, subAttributeString);
185                            }
186    
187                            return attributeClass;
188                    } else {
189                    // Legacy OJB
190                            Class attributeClassLegacy = null;
191                            ClassDescriptor classDescriptor = this.getClassDescriptor(clazz);
192                            ObjectReferenceDescriptor refDescriptor = classDescriptor.getObjectReferenceDescriptorByName(baseAttributeName);
193    
194                            if (refDescriptor != null) {
195                                    attributeClassLegacy = refDescriptor.getItemClass();
196                            }
197    
198                            // recurse if necessary
199                            if (subAttributeString != null) {
200                                    attributeClassLegacy = getBusinessObjectAttributeClass(attributeClassLegacy, subAttributeString);
201                            }
202    
203                            return attributeClassLegacy;
204                    }
205            }
206    
207    }