View Javadoc
1   /*
2    * Copyright 2008 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.sys.service.impl;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.HashSet;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Set;
24  import java.util.regex.Pattern;
25  import java.util.regex.PatternSyntaxException;
26  
27  import org.apache.commons.beanutils.PropertyUtils;
28  import org.apache.commons.lang.StringUtils;
29  import org.apache.log4j.Logger;
30  import org.apache.ojb.broker.metadata.ClassDescriptor;
31  import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
32  import org.kuali.ole.sys.OLEPropertyConstants;
33  import org.kuali.ole.sys.businessobject.BusinessObjectComponent;
34  import org.kuali.ole.sys.businessobject.BusinessObjectProperty;
35  import org.kuali.ole.sys.businessobject.DataMappingFieldDefinition;
36  import org.kuali.ole.sys.businessobject.FunctionalFieldDescription;
37  import org.kuali.ole.sys.dataaccess.BusinessObjectMetaDataDao;
38  import org.kuali.ole.sys.service.NonTransactional;
39  import org.kuali.ole.sys.service.OleBusinessObjectMetaDataService;
40  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
41  import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
42  import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
43  import org.kuali.rice.kns.service.DataDictionaryService;
44  import org.kuali.rice.krad.bo.BusinessObject;
45  import org.kuali.rice.krad.bo.DataObjectRelationship;
46  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
47  import org.kuali.rice.krad.service.BusinessObjectService;
48  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
49  import org.kuali.rice.krad.service.LookupService;
50  
51  @NonTransactional
52  public class OleBusinessObjectMetaDataServiceImpl implements OleBusinessObjectMetaDataService {
53      private Logger LOG = Logger.getLogger(OleBusinessObjectMetaDataServiceImpl.class);
54      private DataDictionaryService dataDictionaryService;
55      private ParameterService parameterService;
56      private BusinessObjectService businessObjectService;
57      private BusinessObjectMetaDataService businessObjectMetaDataService;
58      private BusinessObjectMetaDataDao businessObjectMetaDataDao;
59      private LookupService lookupService;
60  
61      public void setParameterService(ParameterService parameterService) {
62          this.parameterService = parameterService;
63      }
64  
65      protected BusinessObjectComponent getBusinessObjectComponent(Class<?> componentClass) {
66          return new BusinessObjectComponent(KRADServiceLocatorWeb.getKualiModuleService().getNamespaceCode(componentClass), (org.kuali.rice.kns.datadictionary.BusinessObjectEntry) dataDictionaryService.getDataDictionary().getBusinessObjectEntry(componentClass.getName()));
67      }
68  
69      @Override
70      public BusinessObjectProperty getBusinessObjectProperty(String componentClass, String propertyName) {
71          try {
72              return new BusinessObjectProperty(getBusinessObjectComponent(Class.forName(componentClass)), dataDictionaryService.getDataDictionary().getBusinessObjectEntry(componentClass).getAttributeDefinition(propertyName));
73          }
74          catch (ClassNotFoundException ex) {
75              LOG.error( "Unable to resolve component class name: " + componentClass );
76          }
77          return null;
78      }
79  
80      @Override
81      public DataMappingFieldDefinition getDataMappingFieldDefinition(String componentClass, String propertyName) {
82          Map<String, String> primaryKeys = new HashMap<String, String>();
83          primaryKeys.put(OLEPropertyConstants.COMPONENT_CLASS, componentClass);
84          primaryKeys.put(OLEPropertyConstants.PROPERTY_NAME, propertyName);
85          FunctionalFieldDescription functionalFieldDescription = businessObjectService.findByPrimaryKey(FunctionalFieldDescription.class, primaryKeys);
86          if (functionalFieldDescription == null) {
87              functionalFieldDescription = new FunctionalFieldDescription(componentClass, propertyName);
88          }
89          functionalFieldDescription.refreshNonUpdateableReferences();
90          return getDataMappingFieldDefinition(functionalFieldDescription);
91      }
92  
93      @Override
94      public DataMappingFieldDefinition getDataMappingFieldDefinition(FunctionalFieldDescription functionalFieldDescription) {
95          BusinessObjectEntry businessObjectEntry = (BusinessObjectEntry) dataDictionaryService.getDataDictionary().getBusinessObjectEntry(functionalFieldDescription.getComponentClass());
96          String propertyType = "";
97          try {
98              propertyType = PropertyUtils.getPropertyType(businessObjectEntry.getBusinessObjectClass().newInstance(), functionalFieldDescription.getPropertyName()).getSimpleName();
99          }
100         catch (Exception e) {
101             if (LOG.isDebugEnabled()) {
102                 LOG.debug("OleBusinessObjectMetaDataServiceImpl unable to get type of property: " + functionalFieldDescription.getPropertyName(), e);
103             }
104         }
105         return new DataMappingFieldDefinition(functionalFieldDescription, businessObjectEntry,
106                 businessObjectEntry.getAttributeDefinition(functionalFieldDescription.getPropertyName()),
107                 businessObjectMetaDataDao.getFieldMetaData(businessObjectEntry.getBusinessObjectClass(), functionalFieldDescription.getPropertyName()),
108                 propertyType,
109                 getReferenceComponentLabel(businessObjectEntry.getBusinessObjectClass(), functionalFieldDescription.getPropertyName()));
110     }
111 
112     @Override
113     public List<BusinessObjectComponent> findBusinessObjectComponents(String namespaceCode, String componentLabel) {
114         Map<Class, BusinessObjectComponent> matchingBusinessObjectComponents = new HashMap<Class, BusinessObjectComponent>();
115         Pattern componentLabelRegex = null;
116         if (StringUtils.isNotBlank(componentLabel)) {
117             String patternStr = componentLabel.replace("*", ".*").toUpperCase();
118             try {
119                 componentLabelRegex = Pattern.compile(patternStr);
120             }
121             catch (PatternSyntaxException ex) {
122                 LOG.error("OleBusinessObjectMetaDataServiceImpl unable to parse componentLabel pattern, ignoring.", ex);
123             }
124         }
125         for (org.kuali.rice.krad.datadictionary.BusinessObjectEntry businessObjectEntry : dataDictionaryService.getDataDictionary().getBusinessObjectEntries().values()) {
126             if ((StringUtils.isBlank(namespaceCode) || namespaceCode.equals(KRADServiceLocatorWeb.getKualiModuleService().getNamespaceCode(businessObjectEntry.getBusinessObjectClass())))
127                     && ((componentLabelRegex == null) || (StringUtils.isNotBlank(businessObjectEntry.getObjectLabel()) && componentLabelRegex.matcher(businessObjectEntry.getObjectLabel().toUpperCase()).matches()))) {
128                 matchingBusinessObjectComponents.put(businessObjectEntry.getBusinessObjectClass(), new BusinessObjectComponent(KRADServiceLocatorWeb.getKualiModuleService().getNamespaceCode(businessObjectEntry.getBusinessObjectClass()), (BusinessObjectEntry) businessObjectEntry));
129             }
130         }
131         return new ArrayList<BusinessObjectComponent>(matchingBusinessObjectComponents.values());
132     }
133 
134     @Override
135     public List<BusinessObjectProperty> findBusinessObjectProperties(String namespaceCode, String componentLabel, String propertyLabel) {
136         List<BusinessObjectComponent> businessObjectComponents = findBusinessObjectComponents(namespaceCode, componentLabel);
137 
138         Pattern propertyLabelRegex = null;
139         if (StringUtils.isNotBlank(propertyLabel)) {
140             String patternStr = propertyLabel.replace("*", ".*").toUpperCase();
141             try {
142                 propertyLabelRegex = Pattern.compile(patternStr);
143             }
144             catch (PatternSyntaxException ex) {
145                 LOG.error("OleBusinessObjectMetaDataServiceImpl unable to parse propertyLabel pattern, ignoring.", ex);
146             }
147         }
148 
149         List<BusinessObjectProperty> matchingBusinessObjectProperties = new ArrayList<BusinessObjectProperty>();
150         for (BusinessObjectComponent businessObjectComponent : businessObjectComponents) {
151             for (AttributeDefinition attributeDefinition : dataDictionaryService.getDataDictionary().getBusinessObjectEntry(businessObjectComponent.getComponentClass().toString()).getAttributes()) {
152                 if (!attributeDefinition.getName().endsWith(OLEPropertyConstants.VERSION_NUMBER) && !attributeDefinition.getName().endsWith(OLEPropertyConstants.OBJECT_ID) && ((propertyLabelRegex == null) || propertyLabelRegex.matcher(attributeDefinition.getLabel().toUpperCase()).matches())) {
153                     matchingBusinessObjectProperties.add(new BusinessObjectProperty(businessObjectComponent, attributeDefinition));
154                 }
155             }
156         }
157 
158         return matchingBusinessObjectProperties;
159     }
160 
161     @Override
162     public List<FunctionalFieldDescription> findFunctionalFieldDescriptions(String namespaceCode, String componentLabel, String propertyLabel, String description, String active) {
163         Set<String> componentClasses = new HashSet<String>();
164         Set<String> propertyNames = new HashSet<String>();
165         for (BusinessObjectProperty businessObjectProperty : findBusinessObjectProperties(namespaceCode, componentLabel, propertyLabel)) {
166             componentClasses.add(businessObjectProperty.getComponentClass());
167             propertyNames.add(businessObjectProperty.getPropertyName());
168         }
169         Map<String, String> fieldValues = new HashMap<String, String>();
170         fieldValues.put(OLEPropertyConstants.NAMESPACE_CODE, namespaceCode);
171         fieldValues.put(OLEPropertyConstants.COMPONENT_CLASS, buildOrCriteria(componentClasses));
172         fieldValues.put(OLEPropertyConstants.PROPERTY_NAME, buildOrCriteria(propertyNames));
173         fieldValues.put(OLEPropertyConstants.DESCRIPTION, description);
174         fieldValues.put(OLEPropertyConstants.ACTIVE, active);
175         List<FunctionalFieldDescription> searchResults = (List<FunctionalFieldDescription>) lookupService.findCollectionBySearchHelper(FunctionalFieldDescription.class, fieldValues, false);
176         for (FunctionalFieldDescription functionalFieldDescription : searchResults) {
177             functionalFieldDescription.refreshNonUpdateableReferences();
178         }
179         return searchResults;
180     }
181 
182     protected String buildOrCriteria(Set<String> values) {
183         StringBuffer orCriteria = new StringBuffer();
184         List<String> valueList = new ArrayList<String>(values);
185         for (int i = 0; i < valueList.size(); i++) {
186             orCriteria.append(valueList.get(i));
187             if (i < (valueList.size() - 1)) {
188                 orCriteria.append("|");
189             }
190         }
191         return orCriteria.toString();
192     }
193 
194     @Override
195     public boolean isMatch(String componentClass, String propertyName, String tableNameSearchCriterion, String fieldNameSearchCriterion) {
196         ClassDescriptor classDescriptor = null;
197         try {
198             classDescriptor = org.apache.ojb.broker.metadata.MetadataManager.getInstance().getGlobalRepository().getDescriptorFor(componentClass);
199             Pattern tableNameRegex = null;
200             if (StringUtils.isNotBlank(tableNameSearchCriterion)) {
201                 String patternStr = tableNameSearchCriterion.replace("*", ".*").toUpperCase();
202                 try {
203                     tableNameRegex = Pattern.compile(patternStr);
204                 }
205                 catch (PatternSyntaxException ex) {
206                     LOG.error("DataMappingFieldDefinitionLookupableHelperServiceImpl unable to parse tableName pattern, ignoring.", ex);
207                 }
208             }
209             Pattern fieldNameRegex = null;
210             if (StringUtils.isNotBlank(fieldNameSearchCriterion)) {
211                 String patternStr = fieldNameSearchCriterion.replace("*", ".*").toUpperCase();
212                 try {
213                     fieldNameRegex = Pattern.compile(patternStr);
214                 }
215                 catch (PatternSyntaxException ex) {
216                     LOG.error("DataMappingFieldDefinitionLookupableHelperServiceImpl unable to parse fieldName pattern, ignoring.", ex);
217                 }
218             }
219             return ((tableNameRegex == null) || tableNameRegex.matcher(classDescriptor.getFullTableName().toUpperCase()).matches()) && ((fieldNameRegex == null) || ((classDescriptor.getFieldDescriptorByName(propertyName) != null) && fieldNameRegex.matcher(classDescriptor.getFieldDescriptorByName(propertyName).getColumnName().toUpperCase()).matches()));
220         }
221         catch (ClassNotPersistenceCapableException e) {
222             return StringUtils.isBlank(tableNameSearchCriterion) && StringUtils.isBlank(fieldNameSearchCriterion);
223         }
224     }
225 
226     @Override
227     public String getReferenceComponentLabel(Class componentClass, String propertyName) {
228         DataObjectRelationship relationship = null;
229         try {
230             relationship = businessObjectMetaDataService.getBusinessObjectRelationship((BusinessObject) componentClass.newInstance(), propertyName);
231         }
232         catch (Exception e) {
233             if ( LOG.isDebugEnabled() ) {
234                 LOG.debug("KfsBusinessObjectMetadataServiceImpl unable to instantiate componentClass: " + componentClass, e);
235             }
236         }
237         if (relationship != null) {
238             return dataDictionaryService.getDataDictionary().getBusinessObjectEntry(relationship.getRelatedClass().getName()).getObjectLabel();
239         }
240         return "";
241     }
242 
243     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
244         this.dataDictionaryService = dataDictionaryService;
245     }
246 
247     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
248         this.businessObjectService = businessObjectService;
249     }
250 
251     public void setBusinessObjectMetaDataService(BusinessObjectMetaDataService businessObjectMetaDataService) {
252         this.businessObjectMetaDataService = businessObjectMetaDataService;
253     }
254 
255     public void setBusinessObjectMetaDataDao(BusinessObjectMetaDataDao businessObjectMetaDataDao) {
256         this.businessObjectMetaDataDao = businessObjectMetaDataDao;
257     }
258 
259     public void setLookupService(LookupService lookupService) {
260         this.lookupService = lookupService;
261     }
262 }