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
103 if (entry instanceof BusinessObjectEntry) {
104 BusinessObjectEntry boEntry = (BusinessObjectEntry) entry;
105
106 businessObjectEntries.put(boEntry.getBusinessObjectClass().getName(), boEntry);
107 businessObjectEntries.put(boEntry.getBusinessObjectClass().getSimpleName(), boEntry);
108
109
110 if (boEntry.getBaseBusinessObjectClass() != null) {
111 businessObjectEntries.put(boEntry.getBaseBusinessObjectClass().getName(), boEntry);
112 businessObjectEntries.put(boEntry.getBaseBusinessObjectClass().getSimpleName(), boEntry);
113 }
114 }
115
116 entriesByJstlKey.put(entry.getJstlKey(), entry);
117 }
118
119
120 Map<String, DocumentEntry> docBeans = ddBeans.getBeansOfType(DocumentEntry.class);
121 for (DocumentEntry entry : docBeans.values()) {
122 String entryName = entry.getDocumentTypeName();
123
124 if ((entry instanceof TransactionalDocumentEntry)
125 && (documentEntries.get(entry.getFullClassName()) != null)
126 && !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(
198 "Detected duplicate InactivationBlockingDefinition for class " + inactivationBlockingDefinition
199 .getBlockingReferenceBusinessObjectClass().getClass().getName());
200 }
201 }
202
203 public void run() {
204 LOG.info("Starting DD Index Building");
205 buildDDIndicies();
206 LOG.info("Completed DD Index Building");
207
208
209
210
211
212 LOG.info("Started DD Inactivation Blocking Index Building");
213 buildDDInactivationBlockingIndices();
214 LOG.info("Completed DD Inactivation Blocking Index Building");
215 }
216
217 public Map<String, BusinessObjectEntry> getBusinessObjectEntries() {
218 return this.businessObjectEntries;
219 }
220
221 public Map<String, DataObjectEntry> getDataObjectEntries() {
222 return this.objectEntries;
223 }
224
225 public Map<String, DocumentEntry> getDocumentEntries() {
226 return this.documentEntries;
227 }
228
229 public Map<Class, DocumentEntry> getDocumentEntriesByBusinessObjectClass() {
230 return this.documentEntriesByBusinessObjectClass;
231 }
232
233 public Map<Class, DocumentEntry> getDocumentEntriesByMaintainableClass() {
234 return this.documentEntriesByMaintainableClass;
235 }
236
237 public Map<String, DataDictionaryEntry> getEntriesByJstlKey() {
238 return this.entriesByJstlKey;
239 }
240
241 public Map<Class, Set<InactivationBlockingMetadata>> getInactivationBlockersForClass() {
242 return this.inactivationBlockersForClass;
243 }
244
245
246
247
248
249
250 public Map<String, List<String>> getDictionaryBeansByNamespace() {
251 return dictionaryBeansByNamespace;
252 }
253
254
255
256
257
258
259
260 public void addBeanNamesToNamespace(String namespaceCode, List<String> beanNames) {
261 List<String> namespaceBeans = new ArrayList<String>();
262 if (dictionaryBeansByNamespace.containsKey(namespaceCode)) {
263 namespaceBeans = dictionaryBeansByNamespace.get(namespaceCode);
264 } else {
265 dictionaryBeansByNamespace.put(namespaceCode, namespaceBeans);
266 }
267 namespaceBeans.addAll(beanNames);
268 }
269 }