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)
126 && (documentEntries.get(entry.getFullClassName()) != null)
127 && !StringUtils.equals(documentEntries.get(entry.getFullClassName()).getDocumentTypeName(),
128 entry.getDocumentTypeName())) {
129 throw new DataDictionaryException(new StringBuffer(
130 "Two transactional document types may not share the same document class: this=").append(
131 entry.getDocumentTypeName()).append(" / existing=").append(((DocumentEntry) documentEntries.get(
132 entry.getDocumentClass().getName())).getDocumentTypeName()).toString());
133 }
134
135 if ((documentEntries.get(entry.getJstlKey()) != null) && !((DocumentEntry) documentEntries.get(
136 entry.getJstlKey())).getDocumentTypeName().equals(entry.getDocumentTypeName())) {
137 throw new DataDictionaryException(new StringBuffer(
138 "Two document types may not share the same jstl key: this=").append(entry.getDocumentTypeName())
139 .append(" / existing=").append(((DocumentEntry) documentEntries.get(entry.getJstlKey()))
140 .getDocumentTypeName()).toString());
141 }
142
143 if (entryName != null) {
144 documentEntries.put(entryName, entry);
145 }
146
147
148 documentEntries.put(entry.getDocumentClass().getName(), entry);
149 if (entry.getBaseDocumentClass() != null) {
150 documentEntries.put(entry.getBaseDocumentClass().getName(), entry);
151 }
152 entriesByJstlKey.put(entry.getJstlKey(), entry);
153
154 if (entry instanceof TransactionalDocumentEntry) {
155 TransactionalDocumentEntry tde = (TransactionalDocumentEntry) entry;
156
157 documentEntries.put(tde.getDocumentClass().getSimpleName(), entry);
158 if (tde.getBaseDocumentClass() != null) {
159 documentEntries.put(tde.getBaseDocumentClass().getSimpleName(), entry);
160 }
161 }
162
163 if (entry instanceof MaintenanceDocumentEntry) {
164 MaintenanceDocumentEntry mde = (MaintenanceDocumentEntry) entry;
165
166 documentEntriesByBusinessObjectClass.put(mde.getDataObjectClass(), entry);
167 documentEntriesByMaintainableClass.put(mde.getMaintainableClass(), entry);
168 documentEntries.put(mde.getDataObjectClass().getSimpleName() + "MaintenanceDocument", entry);
169 }
170 }
171 }
172
173 private void buildDDInactivationBlockingIndices() {
174 inactivationBlockersForClass = new HashMap<Class, Set<InactivationBlockingMetadata>>();
175
176 Map<String, DataObjectEntry> doBeans = ddBeans.getBeansOfType(DataObjectEntry.class);
177 for (DataObjectEntry entry : doBeans.values()) {
178 List<InactivationBlockingDefinition> inactivationBlockingDefinitions =
179 entry.getInactivationBlockingDefinitions();
180 if (inactivationBlockingDefinitions != null && !inactivationBlockingDefinitions.isEmpty()) {
181 for (InactivationBlockingDefinition inactivationBlockingDefinition : inactivationBlockingDefinitions) {
182 registerInactivationBlockingDefinition(inactivationBlockingDefinition);
183 }
184 }
185 }
186 }
187
188 private void registerInactivationBlockingDefinition(InactivationBlockingDefinition inactivationBlockingDefinition) {
189 Set<InactivationBlockingMetadata> inactivationBlockingDefinitions = inactivationBlockersForClass.get(
190 inactivationBlockingDefinition.getBlockedBusinessObjectClass());
191 if (inactivationBlockingDefinitions == null) {
192 inactivationBlockingDefinitions = new HashSet<InactivationBlockingMetadata>();
193 inactivationBlockersForClass.put(inactivationBlockingDefinition.getBlockedBusinessObjectClass(),
194 inactivationBlockingDefinitions);
195 }
196 boolean duplicateAdd = !inactivationBlockingDefinitions.add(inactivationBlockingDefinition);
197 if (duplicateAdd) {
198 throw new DataDictionaryException(
199 "Detected duplicate InactivationBlockingDefinition for class " + inactivationBlockingDefinition
200 .getBlockingReferenceBusinessObjectClass().getClass().getName());
201 }
202 }
203
204 public void run() {
205 LOG.info("Starting DD Index Building");
206 buildDDIndicies();
207 LOG.info("Completed DD Index Building");
208
209
210
211
212
213 LOG.info("Started DD Inactivation Blocking Index Building");
214 buildDDInactivationBlockingIndices();
215 LOG.info("Completed DD Inactivation Blocking Index Building");
216 }
217
218 public Map<String, BusinessObjectEntry> getBusinessObjectEntries() {
219 return this.businessObjectEntries;
220 }
221
222 public Map<String, DataObjectEntry> getDataObjectEntries() {
223 return this.objectEntries;
224 }
225
226 public Map<String, DocumentEntry> getDocumentEntries() {
227 return this.documentEntries;
228 }
229
230 public Map<Class, DocumentEntry> getDocumentEntriesByBusinessObjectClass() {
231 return this.documentEntriesByBusinessObjectClass;
232 }
233
234 public Map<Class, DocumentEntry> getDocumentEntriesByMaintainableClass() {
235 return this.documentEntriesByMaintainableClass;
236 }
237
238 public Map<String, DataDictionaryEntry> getEntriesByJstlKey() {
239 return this.entriesByJstlKey;
240 }
241
242 public Map<Class, Set<InactivationBlockingMetadata>> getInactivationBlockersForClass() {
243 return this.inactivationBlockersForClass;
244 }
245
246
247
248
249
250
251 public Map<String, List<String>> getDictionaryBeansByNamespace() {
252 return dictionaryBeansByNamespace;
253 }
254
255
256
257
258
259
260
261 public void addBeanNamesToNamespace(String namespaceCode, List<String> beanNames) {
262 List<String> namespaceBeans = new ArrayList<String>();
263 if (dictionaryBeansByNamespace.containsKey(namespaceCode)) {
264 namespaceBeans = dictionaryBeansByNamespace.get(namespaceCode);
265 } else {
266 dictionaryBeansByNamespace.put(namespaceCode, namespaceBeans);
267 }
268 namespaceBeans.addAll(beanNames);
269 }
270 }