001/** 002 * Copyright 2005-2016 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 */ 016package org.kuali.rice.krad.data.provider.impl; 017 018import java.util.Collection; 019import java.util.Collections; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.concurrent.ConcurrentHashMap; 023 024import org.kuali.rice.krad.data.metadata.DataObjectMetadata; 025import org.kuali.rice.krad.data.provider.MetadataProvider; 026 027/** 028 * Superclass for all metadata providers which contain the basic operations and data structure. 029 * 030 * <p>All each subclass needs to implement is the initializeMetadata method.</p> 031 * 032 * @author Kuali Rice Team (rice.collab@kuali.org) 033 */ 034public abstract class MetadataProviderBase implements MetadataProvider { 035 036 /** 037 * The map of types to metadata. 038 */ 039 protected ConcurrentHashMap<Class<?>, DataObjectMetadata> masterMetadataMap = 040 new ConcurrentHashMap<Class<?>, DataObjectMetadata>(); 041 042 /** 043 * Performs the initialization of the provider with the given set of types. 044 * 045 * <p> 046 * If the list is null or empty, the provider is expected to discover the types via other means, or do nothing if 047 * the types cannot be discovered. 048 * </p> 049 */ 050 protected abstract void initializeMetadata(Collection<Class<?>> types); 051 052 /** 053 * {@inheritDoc} 054 */ 055 @Override 056 public boolean handles(Class<?> type) { 057 if (type == null) { 058 return false; 059 } 060 if (masterMetadataMap.isEmpty()) { 061 initializeMetadata(null); 062 } 063 return masterMetadataMap.containsKey(type); 064 } 065 066 /** 067 * {@inheritDoc} 068 */ 069 @Override 070 public Collection<Class<?>> getSupportedTypes() { 071 if (masterMetadataMap.isEmpty()) { 072 initializeMetadata(null); 073 } 074 return masterMetadataMap.keySet(); 075 } 076 077 /** 078 * {@inheritDoc} 079 */ 080 @Override 081 public Map<Class<?>, DataObjectMetadata> provideMetadata() { 082 return provideMetadataForTypes(null); 083 } 084 085 /** 086 * {@inheritDoc} 087 */ 088 @Override 089 public Map<Class<?>, DataObjectMetadata> provideMetadataForTypes(Collection<Class<?>> types) { 090 if (masterMetadataMap.isEmpty()) { 091 initializeMetadata(types); 092 return Collections.unmodifiableMap(masterMetadataMap); 093 } else if (types == null || types.isEmpty()) { 094 return Collections.unmodifiableMap(masterMetadataMap); 095 } else { 096 HashMap<Class<?>, DataObjectMetadata> subMap = new HashMap<Class<?>, DataObjectMetadata>(); 097 098 for (Class<?> key : masterMetadataMap.keySet()) { 099 if (types.contains(key)) { 100 subMap.put(key, masterMetadataMap.get(key)); 101 } 102 } 103 return subMap; 104 } 105 } 106 107 /** 108 * {@inheritDoc} 109 */ 110 @Override 111 public DataObjectMetadata getMetadataForType(Class<?> dataObjectType) throws IllegalArgumentException { 112 if (dataObjectType == null) { 113 throw new IllegalArgumentException("getMetadataForType: NULL passed for the dataObjectType"); 114 } 115 if (masterMetadataMap.isEmpty()) { 116 initializeMetadata(null); 117 } 118 return masterMetadataMap.get(dataObjectType); 119 } 120 121 /** 122 * Determines whether the given class can be persisted. 123 * 124 * @param clazz the class to check for persistability. 125 * @return true if the class is persistable, false otherwise. 126 */ 127 protected boolean isClassPersistable(Class<?> clazz) { 128 if (masterMetadataMap.isEmpty()) { 129 initializeMetadata(null); 130 } 131 return masterMetadataMap.containsKey(clazz); 132 } 133 134 /** 135 * {@inheritDoc} 136 * 137 * By default, providers are assumed to be able to pull the list of annotated types from somewhere. 138 */ 139 @Override 140 public boolean requiresListOfExistingTypes() { 141 return false; 142 } 143}