1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.datadictionary;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21 import org.springframework.beans.factory.support.KualiDefaultListableBeanFactory;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29
30
31
32
33
34
35
36 public class DataDictionaryIndex implements Runnable {
37 private static final Log LOG = LogFactory.getLog(DataDictionaryIndex.class);
38
39 private KualiDefaultListableBeanFactory ddBeans;
40
41
42 private Map<String, BusinessObjectEntry> businessObjectEntries;
43 private Map<String, DataObjectEntry> objectEntries;
44
45
46 private Map<String, DocumentEntry> documentEntries;
47
48 private Map<Class, DocumentEntry> documentEntriesByBusinessObjectClass;
49 private Map<Class, DocumentEntry> documentEntriesByMaintainableClass;
50 private Map<String, DataDictionaryEntry> entriesByJstlKey;
51
52
53 private Map<Class, Set<InactivationBlockingMetadata>> inactivationBlockersForClass;
54
55 private Map<String, List<String>> dictionaryBeansByNamespace;
56
57 public DataDictionaryIndex(KualiDefaultListableBeanFactory ddBeans) {
58 this.ddBeans = ddBeans;
59
60
61 businessObjectEntries = new HashMap<String, BusinessObjectEntry>();
62 objectEntries = new HashMap<String, DataObjectEntry>();
63 documentEntries = new HashMap<String, DocumentEntry>();
64
65
66 documentEntriesByBusinessObjectClass = new HashMap<Class, DocumentEntry>();
67 documentEntriesByMaintainableClass = new HashMap<Class, DocumentEntry>();
68 entriesByJstlKey = new HashMap<String, DataDictionaryEntry>();
69
70 dictionaryBeansByNamespace = new HashMap<String, List<String>>();
71 }
72
73 private void buildDDIndicies() {
74
75 businessObjectEntries = new HashMap<String, BusinessObjectEntry>();
76 objectEntries = new HashMap<String, DataObjectEntry>();
77 documentEntries = new HashMap<String, DocumentEntry>();
78
79
80 documentEntriesByBusinessObjectClass = new HashMap<Class, DocumentEntry>();
81 documentEntriesByMaintainableClass = new HashMap<Class, DocumentEntry>();
82 entriesByJstlKey = new HashMap<String, DataDictionaryEntry>();
83
84
85 Map<String, DataObjectEntry> boBeans = ddBeans.getBeansOfType(DataObjectEntry.class);
86 for (DataObjectEntry entry : boBeans.values()) {
87
88 DataObjectEntry indexedEntry = objectEntries.get(entry.getJstlKey());
89 if (indexedEntry == null) {
90 indexedEntry = businessObjectEntries.get(entry.getJstlKey());
91 }
92
93 if ((indexedEntry != null) && !(indexedEntry.getDataObjectClass().equals(entry.getDataObjectClass()))) {
94 throw new DataDictionaryException(new StringBuffer(
95 "Two object classes may not share the same jstl key: this=").append(entry.getDataObjectClass())
96 .append(" / existing=").append(indexedEntry.getDataObjectClass()).toString());
97 }
98
99
100 objectEntries.put(entry.getDataObjectClass().getName(), entry);
101 objectEntries.put(entry.getDataObjectClass().getSimpleName(), entry);
102
103
104 if (entry instanceof BusinessObjectEntry) {
105 BusinessObjectEntry boEntry = (BusinessObjectEntry) entry;
106
107 businessObjectEntries.put(boEntry.getBusinessObjectClass().getName(), boEntry);
108 businessObjectEntries.put(boEntry.getBusinessObjectClass().getSimpleName(), boEntry);
109
110
111 if (boEntry.getBaseBusinessObjectClass() != null) {
112 businessObjectEntries.put(boEntry.getBaseBusinessObjectClass().getName(), boEntry);
113 businessObjectEntries.put(boEntry.getBaseBusinessObjectClass().getSimpleName(), boEntry);
114 }
115 }
116
117 entriesByJstlKey.put(entry.getJstlKey(), entry);
118 }
119
120
121 Map<String, DocumentEntry> docBeans = ddBeans.getBeansOfType(DocumentEntry.class);
122 for (DocumentEntry entry : docBeans.values()) {
123 String entryName = entry.getDocumentTypeName();
124
125 if ((entry instanceof TransactionalDocumentEntry) && (documentEntries.get(entry.getFullClassName()) !=
126 null) && !StringUtils.equals(documentEntries.get(entry.getFullClassName()).getDocumentTypeName(),
127 entry.getDocumentTypeName())) {
128 throw new DataDictionaryException(new StringBuffer(
129 "Two transactional document types may not share the same document class: this=").append(
130 entry.getDocumentTypeName()).append(" / existing=").append(((DocumentEntry) documentEntries.get(
131 entry.getDocumentClass().getName())).getDocumentTypeName()).toString());
132 }
133
134 if ((documentEntries.get(entry.getJstlKey()) != null) && !((DocumentEntry) documentEntries.get(
135 entry.getJstlKey())).getDocumentTypeName().equals(entry.getDocumentTypeName())) {
136 throw new DataDictionaryException(new StringBuffer(
137 "Two document types may not share the same jstl key: this=").append(entry.getDocumentTypeName())
138 .append(" / existing=").append(((DocumentEntry) documentEntries.get(entry.getJstlKey()))
139 .getDocumentTypeName()).toString());
140 }
141
142 if (entryName != null) {
143 documentEntries.put(entryName, entry);
144 }
145
146
147 documentEntries.put(entry.getDocumentClass().getName(), entry);
148 if (entry.getBaseDocumentClass() != null) {
149 documentEntries.put(entry.getBaseDocumentClass().getName(), entry);
150 }
151 entriesByJstlKey.put(entry.getJstlKey(), entry);
152
153 if (entry instanceof TransactionalDocumentEntry) {
154 TransactionalDocumentEntry tde = (TransactionalDocumentEntry) entry;
155
156 documentEntries.put(tde.getDocumentClass().getSimpleName(), entry);
157 if (tde.getBaseDocumentClass() != null) {
158 documentEntries.put(tde.getBaseDocumentClass().getSimpleName(), entry);
159 }
160 }
161
162 if (entry instanceof MaintenanceDocumentEntry) {
163 MaintenanceDocumentEntry mde = (MaintenanceDocumentEntry) entry;
164
165 documentEntriesByBusinessObjectClass.put(mde.getDataObjectClass(), entry);
166 documentEntriesByMaintainableClass.put(mde.getMaintainableClass(), entry);
167 documentEntries.put(mde.getDataObjectClass().getSimpleName() + "MaintenanceDocument", entry);
168 }
169 }
170 }
171
172 private void buildDDInactivationBlockingIndices() {
173 inactivationBlockersForClass = new HashMap<Class, Set<InactivationBlockingMetadata>>();
174
175 Map<String, DataObjectEntry> doBeans = ddBeans.getBeansOfType(DataObjectEntry.class);
176 for (DataObjectEntry entry : doBeans.values()) {
177 List<InactivationBlockingDefinition> inactivationBlockingDefinitions =
178 entry.getInactivationBlockingDefinitions();
179 if (inactivationBlockingDefinitions != null && !inactivationBlockingDefinitions.isEmpty()) {
180 for (InactivationBlockingDefinition inactivationBlockingDefinition : inactivationBlockingDefinitions) {
181 registerInactivationBlockingDefinition(inactivationBlockingDefinition);
182 }
183 }
184 }
185 }
186
187 private void registerInactivationBlockingDefinition(InactivationBlockingDefinition inactivationBlockingDefinition) {
188 Set<InactivationBlockingMetadata> inactivationBlockingDefinitions = inactivationBlockersForClass.get(
189 inactivationBlockingDefinition.getBlockedBusinessObjectClass());
190 if (inactivationBlockingDefinitions == null) {
191 inactivationBlockingDefinitions = new HashSet<InactivationBlockingMetadata>();
192 inactivationBlockersForClass.put(inactivationBlockingDefinition.getBlockedBusinessObjectClass(),
193 inactivationBlockingDefinitions);
194 }
195 boolean duplicateAdd = !inactivationBlockingDefinitions.add(inactivationBlockingDefinition);
196 if (duplicateAdd) {
197 throw new DataDictionaryException("Detected duplicate InactivationBlockingDefinition for class " +
198 inactivationBlockingDefinition.getBlockingReferenceBusinessObjectClass().getClass().getName());
199 }
200 }
201
202 public void run() {
203 LOG.info("Starting DD Index Building");
204 buildDDIndicies();
205 LOG.info("Completed DD Index Building");
206
207
208
209
210
211 LOG.info("Started DD Inactivation Blocking Index Building");
212 buildDDInactivationBlockingIndices();
213 LOG.info("Completed DD Inactivation Blocking Index Building");
214 }
215
216 public Map<String, BusinessObjectEntry> getBusinessObjectEntries() {
217 return this.businessObjectEntries;
218 }
219
220 public Map<String, DataObjectEntry> getDataObjectEntries() {
221 return this.objectEntries;
222 }
223
224 public Map<String, DocumentEntry> getDocumentEntries() {
225 return this.documentEntries;
226 }
227
228 public Map<Class, DocumentEntry> getDocumentEntriesByBusinessObjectClass() {
229 return this.documentEntriesByBusinessObjectClass;
230 }
231
232 public Map<Class, DocumentEntry> getDocumentEntriesByMaintainableClass() {
233 return this.documentEntriesByMaintainableClass;
234 }
235
236 public Map<String, DataDictionaryEntry> getEntriesByJstlKey() {
237 return this.entriesByJstlKey;
238 }
239
240 public Map<Class, Set<InactivationBlockingMetadata>> getInactivationBlockersForClass() {
241 return this.inactivationBlockersForClass;
242 }
243
244
245
246
247
248
249 public Map<String, List<String>> getDictionaryBeansByNamespace() {
250 return dictionaryBeansByNamespace;
251 }
252
253
254
255
256
257
258
259 public void addBeanNamesToNamespace(String namespaceCode, List<String> beanNames) {
260 List<String> namespaceBeans = new ArrayList<String>();
261 if (dictionaryBeansByNamespace.containsKey(namespaceCode)) {
262 namespaceBeans = dictionaryBeansByNamespace.get(namespaceCode);
263 } else {
264 dictionaryBeansByNamespace.put(namespaceCode, namespaceBeans);
265 }
266 namespaceBeans.addAll(beanNames);
267 }
268 }