View Javadoc

1   /*
2    * Copyright 2005-2007 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  
17  package org.kuali.rice.krad.datadictionary;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.kuali.rice.core.util.ClassLoaderUtils;
23  import org.kuali.rice.krad.bo.BusinessObject;
24  import org.kuali.rice.krad.bo.PersistableBusinessObjectExtension;
25  import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
26  import org.kuali.rice.krad.datadictionary.exception.CompletionException;
27  import org.kuali.rice.krad.datadictionary.parse.StringListConverter;
28  import org.kuali.rice.krad.datadictionary.parse.StringMapConverter;
29  import org.kuali.rice.krad.service.KRADServiceLocator;
30  import org.kuali.rice.krad.service.PersistenceStructureService;
31  import org.kuali.rice.krad.uif.container.View;
32  import org.kuali.rice.krad.uif.util.ComponentBeanPostProcessor;
33  import org.kuali.rice.krad.util.ObjectUtils;
34  import org.springframework.beans.factory.config.BeanPostProcessor;
35  import org.springframework.beans.factory.support.DefaultListableBeanFactory;
36  import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
37  import org.springframework.context.expression.StandardBeanExpressionResolver;
38  import org.springframework.core.convert.support.GenericConversionService;
39  import org.springframework.core.io.DefaultResourceLoader;
40  import org.springframework.core.io.Resource;
41  
42  import java.beans.IntrospectionException;
43  import java.beans.PropertyDescriptor;
44  import java.io.File;
45  import java.io.IOException;
46  import java.util.ArrayList;
47  import java.util.Collection;
48  import java.util.HashMap;
49  import java.util.List;
50  import java.util.Map;
51  import java.util.Set;
52  import java.util.TreeMap;
53  
54  /**
55   * Collection of named BusinessObjectEntry objects, each of which contains
56   * information relating to the display, validation, and general maintenance of a
57   * BusinessObject.
58   */
59  public class DataDictionary  {
60  
61  	protected DefaultListableBeanFactory ddBeans = new DefaultListableBeanFactory();
62      protected XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ddBeans);
63  
64  	// logger
65  	private static final Log LOG = LogFactory.getLog(DataDictionary.class);
66  
67  	/**
68  	 * The encapsulation of DataDictionary indices
69  	 */
70  	protected DataDictionaryIndex ddIndex = new DataDictionaryIndex(ddBeans);
71  	
72  	// View indices
73  	protected UifDictionaryIndex uifIndex = new UifDictionaryIndex(ddBeans);
74  
75  	/**
76  	 * The DataDictionaryMapper
77  	 * The default mapper simply consults the initialized indices
78  	 * on workflow document type
79  	 */
80  	protected DataDictionaryMapper ddMapper = new DataDictionaryIndexMapper();
81  
82  	protected List<String> configFileLocations = new ArrayList<String>();
83  	
84  
85  	public List<String> getConfigFileLocations() {
86          return this.configFileLocations;
87      }
88  
89      public void setConfigFileLocations(List<String> configFileLocations) {
90          this.configFileLocations = configFileLocations;
91      }
92      
93      public void addConfigFileLocation( String location ) throws IOException {
94          indexSource( location );
95      }
96  
97      /**
98       * Sets the DataDictionaryMapper
99       * @param mapper the datadictionary mapper
100      */
101     public void setDataDictionaryMapper(DataDictionaryMapper mapper) {
102     	this.ddMapper = mapper;
103     }
104     
105     private void indexSource(String sourceName) throws IOException {        
106         if (sourceName == null) {
107             throw new DataDictionaryException("Source Name given is null");
108         }
109 
110         if (!sourceName.endsWith(".xml") ) {
111             Resource resource = getFileResource(sourceName);
112             if (resource.exists()) {
113                 indexSource(resource.getFile());
114             } else {
115                 LOG.warn("Could not find " + sourceName);
116                 throw new DataDictionaryException("DD Resource " + sourceName + " not found");
117             }
118         } else {
119             if ( LOG.isDebugEnabled() ) {
120                 LOG.debug("adding sourceName " + sourceName + " ");
121             }
122             Resource resource = getFileResource(sourceName);
123             if (! resource.exists()) {
124                 throw new DataDictionaryException("DD Resource " + sourceName + " not found");  
125             }
126             
127             String indexName = sourceName.substring(sourceName.lastIndexOf("/") + 1, sourceName.indexOf(".xml"));
128             configFileLocations.add( sourceName );
129         }
130     }    
131 
132     protected Resource getFileResource(String sourceName) {
133         DefaultResourceLoader resourceLoader = new DefaultResourceLoader(ClassLoaderUtils.getDefaultClassLoader());
134         return resourceLoader.getResource(sourceName);
135     }
136 
137     private void indexSource(File dir) {
138         for (File file : dir.listFiles()) {
139             if (file.isDirectory()) {
140                 indexSource(file);
141             } else if (file.getName().endsWith(".xml") ) {
142                 configFileLocations.add( "file:" + file.getAbsolutePath());
143             } else {
144                 if ( LOG.isDebugEnabled() ) {
145                     LOG.debug("Skipping non xml file " + file.getAbsolutePath() + " in DD load");
146                 }
147             }
148         }
149     }
150     
151     public void parseDataDictionaryConfigurationFiles( boolean allowConcurrentValidation ) {
152 		// configure the bean factory, setup component decorator post processor
153 		// and allow Spring EL
154 		try {
155 			BeanPostProcessor idPostProcessor = ComponentBeanPostProcessor.class.newInstance();
156 			ddBeans.addBeanPostProcessor(idPostProcessor);
157 			ddBeans.setBeanExpressionResolver(new StandardBeanExpressionResolver());
158 
159             GenericConversionService conversionService = new GenericConversionService();
160             conversionService.addConverter(new StringMapConverter());
161             conversionService.addConverter(new StringListConverter());
162             ddBeans.setConversionService(conversionService);
163 		}
164 		catch (Exception e1) {
165 			LOG.error("Cannot create component decorator post processor: " + e1.getMessage(), e1);
166 			throw new RuntimeException("Cannot create component decorator post processor: " + e1.getMessage(), e1);
167 		}
168     	
169         // expand configuration locations into files
170         LOG.info( "Starting DD XML File Load" );
171         
172         String[] configFileLocationsArray = new String[configFileLocations.size()];
173         configFileLocationsArray = configFileLocations.toArray( configFileLocationsArray );
174         configFileLocations.clear(); // empty the list out so other items can be added
175         try {
176             xmlReader.loadBeanDefinitions( configFileLocationsArray );
177         } catch (Exception e) {
178             LOG.error("Error loading bean definitions", e);
179             throw new DataDictionaryException("Error loading bean definitions: " + e.getLocalizedMessage());
180         }
181         LOG.info( "Completed DD XML File Load" );
182         if ( allowConcurrentValidation ) {
183             Thread t = new Thread(ddIndex);
184             t.start();
185             
186             Thread t2 = new Thread(uifIndex);
187             t2.start();   
188         } else {
189             ddIndex.run();
190             uifIndex.run();
191         }
192     }
193 
194 	static boolean validateEBOs = true;
195     
196     public void validateDD( boolean validateEbos ) {
197     	DataDictionary.validateEBOs = validateEbos;
198     	Map<String,DataObjectEntry> doBeans = ddBeans.getBeansOfType(DataObjectEntry.class);
199         for ( DataObjectEntry entry : doBeans.values() ) {
200             entry.completeValidation();
201         }
202         Map<String,DocumentEntry> docBeans = ddBeans.getBeansOfType(DocumentEntry.class);
203         for ( DocumentEntry entry : docBeans.values() ) {
204             entry.completeValidation();
205         }
206     }
207     
208     public void validateDD() {
209     	validateDD(true);
210     }
211 
212 	/**
213 	 * @param className
214 	 * @return BusinessObjectEntry for the named class, or null if none exists
215 	 */
216     @Deprecated
217 	public BusinessObjectEntry getBusinessObjectEntry(String className ) {
218 		return ddMapper.getBusinessObjectEntry(ddIndex, className);
219 	}
220 
221 	/**
222      * @param className
223      * @return BusinessObjectEntry for the named class, or null if none exists
224      */
225     public DataObjectEntry getDataObjectEntry(String className ) {
226         return ddMapper.getDataObjectEntry(ddIndex, className);
227     }
228 
229 	/**
230 	 * This method gets the business object entry for a concrete class
231 	 * 
232 	 * @param className
233 	 * @return
234 	 */
235 	public BusinessObjectEntry getBusinessObjectEntryForConcreteClass(String className){
236 		return ddMapper.getBusinessObjectEntryForConcreteClass(ddIndex, className);
237 	}
238 	
239 	/**
240 	 * @return List of businessObject classnames
241 	 */
242 	public List<String> getBusinessObjectClassNames() {
243 		return ddMapper.getBusinessObjectClassNames(ddIndex);
244 	}
245 
246 	/**
247 	 * @return Map of (classname, BusinessObjectEntry) pairs
248 	 */
249 	public Map<String, BusinessObjectEntry> getBusinessObjectEntries() {
250 		return ddMapper.getBusinessObjectEntries(ddIndex);
251 	}
252 
253 	/**
254 	 * @param className
255 	 * @return DataDictionaryEntryBase for the named class, or null if none
256 	 *         exists
257 	 */
258 	public DataDictionaryEntry getDictionaryObjectEntry(String className) {
259 		return ddMapper.getDictionaryObjectEntry(ddIndex, className);
260 	}
261 
262 	/**
263 	 * Returns the KNS document entry for the given lookup key.  The documentTypeDDKey is interpreted
264 	 * successively in the following ways until a mapping is found (or none if found):
265 	 * <ol>
266 	 * <li>KEW/workflow document type</li>
267 	 * <li>business object class name</li>
268 	 * <li>maintainable class name</li>
269 	 * </ol>
270 	 * This mapping is compiled when DataDictionary files are parsed on startup (or demand).  Currently this
271 	 * means the mapping is static, and one-to-one (one KNS document maps directly to one and only
272 	 * one key).
273 	 * 
274 	 * @param documentTypeDDKey the KEW/workflow document type name
275 	 * @return the KNS DocumentEntry if it exists
276 	 */
277 	public DocumentEntry getDocumentEntry(String documentTypeDDKey ) {
278 		return ddMapper.getDocumentEntry(ddIndex, documentTypeDDKey);
279 	}
280 
281 	/**
282 	 * Note: only MaintenanceDocuments are indexed by businessObject Class
283 	 * 
284 	 * This is a special case that is referenced in one location. Do we need
285 	 * another map for this stuff??
286 	 * 
287 	 * @param businessObjectClass
288 	 * @return DocumentEntry associated with the given Class, or null if there
289 	 *         is none
290 	 */
291 	public MaintenanceDocumentEntry getMaintenanceDocumentEntryForBusinessObjectClass(Class<?> businessObjectClass) {
292 		return ddMapper.getMaintenanceDocumentEntryForBusinessObjectClass(ddIndex, businessObjectClass);
293 	}
294 
295 	public Map<String, DocumentEntry> getDocumentEntries() {
296 		return ddMapper.getDocumentEntries(ddIndex);
297 	}
298 	
299 	/**
300 	 * Returns the View entry identified by the given id
301 	 * 
302 	 * @param viewId - unique id for view
303 	 * @return View instance associated with the id
304 	 */
305 	public View getViewById(String viewId) {
306 		return ddMapper.getViewById(uifIndex, viewId);
307 	}
308 	
309 	/**
310 	 * Returns View instance identified by the view type name and index
311 	 * 
312 	 * @param viewTypeName
313 	 *            - type name for the view
314 	 * @param indexKey
315 	 *            - Map of index key parameters, these are the parameters the
316 	 *            indexer used to index the view initially and needs to identify
317 	 *            an unique view instance
318 	 * @return View instance that matches the given index
319 	 */
320 	public View getViewByTypeIndex(String viewTypeName, Map<String, String> indexKey) {
321 		return ddMapper.getViewByTypeIndex(uifIndex, viewTypeName, indexKey);
322 	}
323 	
324 	/**
325 	 * Gets all <code>View</code> prototypes configured for the given view type
326 	 * name
327 	 * 
328 	 * @param viewTypeName
329 	 *            - view type name to retrieve
330 	 * @return List<View> view prototypes with the given type name, or empty
331 	 *         list
332 	 */
333 	public List<View> getViewsForType(String viewTypeName) {
334 		return ddMapper.getViewsForType(uifIndex, viewTypeName);
335 	}
336 
337     /**
338      * @param clazz
339      * @param propertyName
340      * @return true if the given propertyName names a property of the given class
341      * @throws CompletionException if there is a problem accessing the named property on the given class
342      */
343     public static boolean isPropertyOf(Class targetClass, String propertyName) {
344         if (targetClass == null) {
345             throw new IllegalArgumentException("invalid (null) targetClass");
346         }
347         if (StringUtils.isBlank(propertyName)) {
348             throw new IllegalArgumentException("invalid (blank) propertyName");
349         }
350 
351         PropertyDescriptor propertyDescriptor = buildReadDescriptor(targetClass, propertyName);
352 
353         boolean isPropertyOf = (propertyDescriptor != null);
354         return isPropertyOf;
355     }
356 
357     /**
358      * @param clazz
359      * @param propertyName
360      * @return true if the given propertyName names a Collection property of the given class
361      * @throws CompletionException if there is a problem accessing the named property on the given class
362      */
363     public static boolean isCollectionPropertyOf(Class targetClass, String propertyName) {
364         boolean isCollectionPropertyOf = false;
365 
366         PropertyDescriptor propertyDescriptor = buildReadDescriptor(targetClass, propertyName);
367         if (propertyDescriptor != null) {
368             Class clazz = propertyDescriptor.getPropertyType();
369 
370             if ((clazz != null) && Collection.class.isAssignableFrom(clazz)) {
371                 isCollectionPropertyOf = true;
372             }
373         }
374 
375         return isCollectionPropertyOf;
376     }
377 
378     public static PersistenceStructureService persistenceStructureService;
379     
380     /**
381      * @return the persistenceStructureService
382      */
383     public static PersistenceStructureService getPersistenceStructureService() {
384         if ( persistenceStructureService == null ) {
385             persistenceStructureService = KRADServiceLocator.getPersistenceStructureService();
386         }
387         return persistenceStructureService;
388     }
389     
390     /**
391      * This method determines the Class of the attributeName passed in. Null will be returned if the member is not available, or if
392      * a reflection exception is thrown.
393      * 
394      * @param rootClass - Class that the attributeName property exists in.
395      * @param attributeName - Name of the attribute you want a class for.
396      * @return The Class of the attributeName, if the attribute exists on the rootClass. Null otherwise.
397      */
398     public static Class getAttributeClass(Class boClass, String attributeName) {
399 
400         // fail loudly if the attributeName isnt a member of rootClass
401         if (!isPropertyOf(boClass, attributeName)) {
402             throw new AttributeValidationException("unable to find attribute '" + attributeName + "' in rootClass '" + boClass.getName() + "'");
403         }
404 
405     	//Implementing Externalizable Business Object Services...
406         //The boClass can be an interface, hence handling this separately, 
407         //since the original method was throwing exception if the class could not be instantiated.
408         if(boClass.isInterface())
409         	return getAttributeClassWhenBOIsInterface(boClass, attributeName);
410         else
411         	return getAttributeClassWhenBOIsClass(boClass, attributeName);        	
412 
413     }
414 
415     /**
416      * 
417      * This method gets the property type of the given attributeName when the bo class is a concrete class
418      * 
419      * @param boClass
420      * @param attributeName
421      * @return
422      */
423     private static Class getAttributeClassWhenBOIsClass(Class boClass, String attributeName){
424     	BusinessObject boInstance;
425         try {
426             boInstance = (BusinessObject) boClass.newInstance();
427         } catch (Exception e) {
428         	throw new RuntimeException("Unable to instantiate BO: " + boClass, e);
429         }
430 
431         // attempt to retrieve the class of the property
432         try {
433             return ObjectUtils.getPropertyType(boInstance, attributeName, getPersistenceStructureService());
434         } catch (Exception e) {
435             throw new RuntimeException("Unable to determine property type for: " + boClass.getName() + "." + attributeName, e);
436         }
437     }
438 
439     /**
440      * 
441      * This method gets the property type of the given attributeName when the bo class is an interface
442      * This method will also work if the bo class is not an interface, 
443      * but that case requires special handling, hence a separate method getAttributeClassWhenBOIsClass 
444      * 
445      * @param boClass
446      * @param attributeName
447      * @return
448      */
449     private static Class getAttributeClassWhenBOIsInterface(Class boClass, String attributeName){
450         if (boClass == null) {
451             throw new IllegalArgumentException("invalid (null) boClass");
452         }
453         if (StringUtils.isBlank(attributeName)) {
454             throw new IllegalArgumentException("invalid (blank) attributeName");
455         }
456 
457         PropertyDescriptor propertyDescriptor = null;
458 
459         String[] intermediateProperties = attributeName.split("\\.");
460         int lastLevel = intermediateProperties.length - 1;
461         Class currentClass = boClass;
462 
463         for (int i = 0; i <= lastLevel; ++i) {
464 
465             String currentPropertyName = intermediateProperties[i];
466             propertyDescriptor = buildSimpleReadDescriptor(currentClass, currentPropertyName);
467 
468             if (propertyDescriptor != null) {
469 
470                 Class propertyType = propertyDescriptor.getPropertyType();
471                 if ( propertyType.equals( PersistableBusinessObjectExtension.class ) ) {
472                     propertyType = getPersistenceStructureService().getBusinessObjectAttributeClass( currentClass, currentPropertyName );                    
473                 }
474                 if (Collection.class.isAssignableFrom(propertyType)) {
475                 	// TODO: determine property type using generics type definition
476                 	throw new AttributeValidationException("Can't determine the Class of Collection elements because when the business object is an (possibly ExternalizableBusinessObject) interface.");
477                 }
478                 else {
479                     currentClass = propertyType;
480                 }
481             }
482             else {
483             	throw new AttributeValidationException("Can't find getter method of " + boClass.getName() + " for property " + attributeName);
484             }
485         }
486         return currentClass;
487     }
488     
489     /**
490      * This method determines the Class of the elements in the collectionName passed in.
491      * 
492      * @param boClass Class that the collectionName collection exists in.
493      * @param collectionName the name of the collection you want the element class for
494      * @return
495      */
496     public static Class getCollectionElementClass(Class boClass, String collectionName) {
497         if (boClass == null) {
498             throw new IllegalArgumentException("invalid (null) boClass");
499         }
500         if (StringUtils.isBlank(collectionName)) {
501             throw new IllegalArgumentException("invalid (blank) collectionName");
502         }
503 
504         PropertyDescriptor propertyDescriptor = null;
505 
506         String[] intermediateProperties = collectionName.split("\\.");
507         Class currentClass = boClass;
508 
509         for (int i = 0; i <intermediateProperties.length; ++i) {
510 
511             String currentPropertyName = intermediateProperties[i];
512             propertyDescriptor = buildSimpleReadDescriptor(currentClass, currentPropertyName);
513 
514 
515                 if (propertyDescriptor != null) {
516 
517                     Class type = propertyDescriptor.getPropertyType();
518                     if (Collection.class.isAssignableFrom(type)) {
519 
520                         if (getPersistenceStructureService().isPersistable(currentClass)) {
521 
522                             Map<String, Class> collectionClasses = new HashMap<String, Class>();
523                             collectionClasses = getPersistenceStructureService().listCollectionObjectTypes(currentClass);
524                             currentClass = collectionClasses.get(currentPropertyName);
525 
526                         }
527                         else {
528                             throw new RuntimeException("Can't determine the Class of Collection elements because persistenceStructureService.isPersistable(" + currentClass.getName() + ") returns false.");
529                         }
530 
531                     }
532                     else {
533 
534                         currentClass = propertyDescriptor.getPropertyType();
535 
536                     }
537                 }
538             }
539 
540         return currentClass;
541     }
542 
543     static private Map<String, Map<String, PropertyDescriptor>> cache = new TreeMap<String, Map<String, PropertyDescriptor>>();
544 
545     /**
546      * @param propertyClass
547      * @param propertyName
548      * @return PropertyDescriptor for the getter for the named property of the given class, if one exists.
549      */
550     public static PropertyDescriptor buildReadDescriptor(Class propertyClass, String propertyName) {
551         if (propertyClass == null) {
552             throw new IllegalArgumentException("invalid (null) propertyClass");
553         }
554         if (StringUtils.isBlank(propertyName)) {
555             throw new IllegalArgumentException("invalid (blank) propertyName");
556         }
557 
558         PropertyDescriptor propertyDescriptor = null;
559 
560         String[] intermediateProperties = propertyName.split("\\.");
561         int lastLevel = intermediateProperties.length - 1;
562         Class currentClass = propertyClass;
563 
564         for (int i = 0; i <= lastLevel; ++i) {
565 
566             String currentPropertyName = intermediateProperties[i];
567             propertyDescriptor = buildSimpleReadDescriptor(currentClass, currentPropertyName);
568 
569             if (i < lastLevel) {
570 
571                 if (propertyDescriptor != null) {
572 
573                     Class propertyType = propertyDescriptor.getPropertyType();
574                     if ( propertyType.equals( PersistableBusinessObjectExtension.class ) ) {
575                         propertyType = getPersistenceStructureService().getBusinessObjectAttributeClass( currentClass, currentPropertyName );                    
576                     }
577                     if (Collection.class.isAssignableFrom(propertyType)) {
578 
579                         if (getPersistenceStructureService().isPersistable(currentClass)) {
580 
581                             Map<String, Class> collectionClasses = new HashMap<String, Class>();
582                             collectionClasses = getPersistenceStructureService().listCollectionObjectTypes(currentClass);
583                             currentClass = collectionClasses.get(currentPropertyName);
584 
585                         }
586                         else {
587 
588                             throw new RuntimeException("Can't determine the Class of Collection elements because persistenceStructureService.isPersistable(" + currentClass.getName() + ") returns false.");
589 
590                         }
591 
592                     }
593                     else {
594 
595                         currentClass = propertyType;
596 
597                     }
598 
599                 }
600 
601             }
602 
603         }
604 
605         return propertyDescriptor;
606     }
607 
608     /**
609      * @param propertyClass
610      * @param propertyName
611      * @return PropertyDescriptor for the getter for the named property of the given class, if one exists.
612      */
613     public static PropertyDescriptor buildSimpleReadDescriptor(Class propertyClass, String propertyName) {
614         if (propertyClass == null) {
615             throw new IllegalArgumentException("invalid (null) propertyClass");
616         }
617         if (StringUtils.isBlank(propertyName)) {
618             throw new IllegalArgumentException("invalid (blank) propertyName");
619         }
620 
621         PropertyDescriptor p = null;
622 
623         // check to see if we've cached this descriptor already. if yes, return true.
624         String propertyClassName = propertyClass.getName();
625         Map<String, PropertyDescriptor> m = cache.get(propertyClassName);
626         if (null != m) {
627             p = m.get(propertyName);
628             if (null != p) {
629                 return p;
630             }
631         }
632 
633         String prefix = StringUtils.capitalize(propertyName);
634         String getName = "get" + prefix;
635         String isName = "is" + prefix;
636 
637         try {
638 
639             p = new PropertyDescriptor(propertyName, propertyClass, getName, null);
640 
641         }
642         catch (IntrospectionException e) {
643             try {
644 
645                 p = new PropertyDescriptor(propertyName, propertyClass, isName, null);
646 
647             }
648             catch (IntrospectionException f) {
649                 // ignore it
650             }
651         }
652 
653         // cache the property descriptor if we found it.
654         if (null != p) {
655 
656             if (null == m) {
657 
658                 m = new TreeMap<String, PropertyDescriptor>();
659                 cache.put(propertyClassName, m);
660 
661             }
662 
663             m.put(propertyName, p);
664 
665         }
666 
667         return p;
668     }
669 
670     public Set<InactivationBlockingMetadata> getAllInactivationBlockingMetadatas(Class blockedClass) {
671     	return ddMapper.getAllInactivationBlockingMetadatas(ddIndex, blockedClass);
672     }
673     
674     /**
675      * This method gathers beans of type BeanOverride and invokes each one's performOverride() method.
676      */
677     // KULRICE-4513
678     public void performBeanOverrides()
679     {
680     	Collection<BeanOverride> beanOverrides = ddBeans.getBeansOfType(BeanOverride.class).values();
681     	
682     	if (beanOverrides.isEmpty()){
683     		LOG.info("DataDictionary.performOverrides(): No beans to override");
684     	}
685 		for (BeanOverride beanOverride : beanOverrides) {
686 			
687 			Object bean = ddBeans.getBean(beanOverride.getBeanName());
688 			beanOverride.performOverride(bean);
689 			LOG.info("DataDictionary.performOverrides(): Performing override on bean: " + bean.toString());
690 		}
691     }
692 }