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