1 /*
2 * Copyright 2014 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.apache.juddi.validation.vsv;
17
18 import java.util.Collections;
19 import java.util.List;
20 import javax.persistence.EntityManager;
21 import javax.persistence.EntityTransaction;
22 import org.apache.juddi.config.PersistenceManager;
23 import org.apache.juddi.model.Tmodel;
24 import org.apache.juddi.v3.error.ErrorMessage;
25 import org.apache.juddi.v3.error.InvalidValueException;
26 import org.uddi.api_v3.BindingTemplate;
27 import org.uddi.api_v3.BusinessEntity;
28 import org.uddi.api_v3.BusinessService;
29 import org.uddi.api_v3.KeyedReference;
30 import org.uddi.api_v3.PublisherAssertion;
31 import org.uddi.api_v3.TModel;
32 import org.uddi.api_v3.TModelInstanceInfo;
33 import org.uddi.v3_service.DispositionReportFaultMessage;
34
35 /**
36 * UDDI provides a mechanism that may be used by publishers to tag their
37 * businessEntities and tModels with information that identifies them according
38 * to any number of identification systems. This tModel represents an identifier
39 * system that may be used to identify the tModel or businessEntity that
40 * logically replaces the tModel or businessEntity in which it is used. This
41 * version of the isReplacedBy identifier system replaces the prior version of
42 * this identifier system by providing a means for referring to replacement
43 * entities that have version 3 format keys.
44 *
45 * It is often desirable to gracefully retire a tModel in favor of a
46 * replacement. For example, when a Web service definition is replaced by an
47 * incompatible version, the publisher of the specification may wish to leave
48 * the tModel for the existing definition in place so that existing uses will
49 * not be disturbed, while at the same time making it clear that there is a
50 * replacement available. The UDDI isReplacedBy identifier system, coupled with
51 * the behavior of UDDI with respect to obsolete tModels, fills this need by
52 * allowing the obsolete tModel to point to its replacement. See Section 5.2.11
53 * delete_tModel.
54 *
55 * The isReplacedBy identifier system exists in prior versions of UDDI.
56 * keyedReferences that refer to this original isReplacedBy identifier system
57 * contain entity keys in the version 1 and 2 formats (as UUIDs with the uuid or
58 * no scheme prefix). When accessed using a prior version API in a multi-version
59 * registry, the older isReplacedBy identifier system yields valid references to
60 * businessEntity or tModel keys that are in the format of the prior version,
61 * and thus remain valid. When viewed using the version 3 UDDI API these same
62 * references to the earlier isReplacedBy identifier system contain invalid
63 * version 3 format keys. A new version of this identifier system is required to
64 * be able to reference the set of values defined by version 3 format keys.
65 *
66 * <p class="MsoBodyText">The keyValues in keyedReferences that refer to this
67 * tModel must be tModelKeys or businessKeys. Such a keyValue specifies the
68 * entity that is the replacement for the entity in which the keyedReference
69 * appears. The above and further validation requirements are as follows:</p>
70 *
71 * <p class="MsoBodyText" style="margin-left:1.0in;text-indent:-.25in">a.<span
72 * style="font:7.0pt "Times New
73 * Roman""> </span>In the case where a
74 * reference is made from an obsolete business entity the following validation
75 * rules apply:</p>
76 *
77 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">1.<span
78 * style="font:7.0pt "Times New
79 * Roman""> </span>reference to a new
80 * business entity; this is a valid operation</p>
81 *
82 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">2.<span
83 * style="font:7.0pt "Times New
84 * Roman""> </span>reference to self;
85 * this is invalid</p>
86 *
87 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">3.<span
88 * style="font:7.0pt "Times New
89 * Roman""> </span>reference to a
90 * service, binding or tModel; this is an invalid operation given that the
91 * entity being pointed to must be a business</p>
92 *
93 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">4.<span
94 * style="font:7.0pt "Times New
95 * Roman""> </span>reference to another
96 * publisher’s business; this is a valid operation; no ownership check is
97 * made</p>
98 *
99 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">5.<span
100 * style="font:7.0pt "Times New
101 * Roman""> </span>reference to another
102 * publisher’s service, binding or tModel; this is an invalid operation because
103 * of a.3 above</p>
104 *
105 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">6.<span
106 * style="font:7.0pt "Times New
107 * Roman""> </span>reference to invalid
108 * keys; this is an invalid operation; a key must be valid.</p>
109 *
110 * <p class="MsoBodyText" style="margin-left:1.0in;text-indent:-.25in">b.<span
111 * style="font:7.0pt "Times New Roman"">
112 * </span>In the case where a reference is made from an obsolete tModel the
113 * following validation rules apply:</p>
114 *
115 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">1.<span
116 * style="font:7.0pt "Times New
117 * Roman""> </span>reference to a new
118 * tModel; this is a valid operation</p>
119 *
120 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">2.<span
121 * style="font:7.0pt "Times New
122 * Roman""> </span>reference to self;
123 * this is invalid</p>
124 *
125 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">3.<span
126 * style="font:7.0pt "Times New
127 * Roman""> </span>reference to a
128 * service, binding or business; this is an invalid operation given that the
129 * entity being pointed to must be a tModel</p>
130 *
131 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">4.<span
132 * style="font:7.0pt "Times New
133 * Roman""> </span>reference to another
134 * publisher’s tModel; this is a valid operation; no ownership check is made</p>
135 *
136 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">5.<span
137 * style="font:7.0pt "Times New
138 * Roman""> </span>reference to another
139 * publisher’s service, binding or business; this is an invalid operation
140 * because of b.3 above</p>
141 *
142 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">6.<span
143 * style="font:7.0pt "Times New
144 * Roman""> </span>reference to invalid
145 * keys; this is an invalid operation; a key must be valid.</p>
146 *
147 * <p class="MsoBodyText" style="margin-left:1.25in;text-indent:-.25in">7.<span
148 * style="font:7.0pt "Times New
149 * Roman""> </span>reference to a
150 * hidden tModel; this is a valid operation</p>
151 *
152 * <p class="MsoBodyText" style="margin-left:1.0in;text-indent:-.25in">c.<span
153 * style="font:7.0pt "Times New
154 * Roman""> </span>Adding isReplacedBy
155 * to a service’s or binding’s category bag: this is a semantically wrong
156 * operation and will be rejected. </p>
157 *
158 * <p class="MsoBodyText">When returning an error encountered in the above,
159 * E_invalidValue will be returned to indicate that a value that was passed in a
160 * keyValue attribute did not pass validation.</p>
161 *
162 * <p class="MsoBodyText">While this validation is intended at save time,
163 * references to replacing business entities may become invalid if (A) the
164 * business is deleted and (B) in V3 the business is deleted and then the key is
165 * re-used for a different entity. As such, in a replicating registry, nodes
166 * processing changeRecords related to business entities or tModels that refer
167 * to (now) invalid or missing business or tModels entity keys respectively,
168 * MUST NOT raise replication errors.</p>
169 *
170 * @author Alex O'Ree
171 */
172 public class Uddiuddiorgidentifierisreplacedby implements ValueSetValidator {
173
174 public String getMyKey(){
175 return "uddi:uddi.org:identifier:isreplacedby";
176 }
177
178 @Override
179 public void validateValuesBindingTemplate(List<BindingTemplate> items, String xpath) throws DispositionReportFaultMessage {
180 if (items == null) {
181 return;
182 }
183
184 for (int i = 0; i < items.size(); i++) {
185 if (items.get(i).getCategoryBag() != null) {
186 AbstractSimpleValidator.validateKeyNotPresentKeyRef(items.get(i).getCategoryBag().getKeyedReference(), getMyKey(), "binding");
187 AbstractSimpleValidator.validateKeyNotPresentKeyRefGrp(items.get(i).getCategoryBag().getKeyedReferenceGroup(), getMyKey(), "binding");
188 }
189 if (items.get(i).getTModelInstanceDetails() != null) {
190 for (int k = 0; k < items.get(i).getTModelInstanceDetails().getTModelInstanceInfo().size(); k++) {
191 if (items.get(i).getTModelInstanceDetails().getTModelInstanceInfo().get(k) != null) {
192 if (getMyKey().equalsIgnoreCase(items.get(i).getTModelInstanceDetails().getTModelInstanceInfo().get(k).getTModelKey())) {
193 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "not allowed on binding templates"));
194 }
195 }
196 }
197 }
198 }
199 }
200
201 @Override
202 public void validateValuesBusinessEntity(List<BusinessEntity> items) throws DispositionReportFaultMessage {
203 if (items == null) {
204 return;
205 }
206 // In the case where a reference is made from an obsolete tModel the following validation rules apply:
207 EntityManager em = PersistenceManager.getEntityManager();
208 EntityTransaction tx = em.getTransaction();
209 try {
210 tx.begin();
211 for (int i = 0; i < items.size(); i++) {
212 if (items.get(i).getCategoryBag() != null) {
213 for (int k = 0; k < items.get(i).getCategoryBag().getKeyedReference().size(); k++) {
214 if (getMyKey().equalsIgnoreCase(items.get(i).getCategoryBag().getKeyedReference().get(k).getTModelKey())) {
215 //reference to self; this is invalid
216 if (items.get(i).getCategoryBag().getKeyedReference().get(k).getTModelKey().equalsIgnoreCase(items.get(i).getBusinessKey())) {
217 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue() + " can't reference itself"));
218 }
219
220 try {
221 org.apache.juddi.model.BusinessEntity find = em.find(org.apache.juddi.model.BusinessEntity.class, items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue());
222 if (find == null) {
223 // reference to a new tModel; this is a valid operation
224 if (!ContainsBusinessKey(items, items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue())) {
225 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue() + " does not exist"));
226 }
227 }
228 } catch (ClassCastException c) {
229 // reference to a service, binding or business; this is an invalid operation given that the entity being pointed to must be a tModel
230 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue() + " must be a business"));
231
232 }
233 }
234 }
235 }
236 if (items.get(i).getIdentifierBag() != null) {
237 for (int k = 0; k < items.get(i).getIdentifierBag().getKeyedReference().size(); k++) {
238 if (getMyKey().equalsIgnoreCase(items.get(i).getIdentifierBag().getKeyedReference().get(k).getTModelKey())) {
239 //reference to self; this is invalid
240 if (items.get(i).getIdentifierBag().getKeyedReference().get(k).getTModelKey().equalsIgnoreCase(items.get(i).getBusinessKey())) {
241 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue() + " can't reference itself"));
242 }
243
244 try {
245 org.apache.juddi.model.BusinessEntity find = em.find(org.apache.juddi.model.BusinessEntity.class, items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue());
246 if (find == null) {
247 // reference to a new tModel; this is a valid operation
248 if (!ContainsBusinessKey(items, items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue())) {
249 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue() + " does not exist"));
250 }
251 }
252 } catch (ClassCastException c) {
253 // reference to a service, binding or business; this is an invalid operation given that the entity being pointed to must be a tModel
254 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue() + " must be a business"));
255
256 }
257 }
258 }
259 }
260 }
261 tx.commit();
262 } catch (DispositionReportFaultMessage d) {
263 throw d;
264 } finally {
265 if (tx.isActive()) {
266 tx.rollback();
267 }
268 em.close();
269 }
270 }
271
272 @Override
273 public void validateValuesBusinessService(List<BusinessService> items, String xpath) throws DispositionReportFaultMessage {
274 if (items == null) {
275 return;
276 }
277 for (int i = 0; i < items.size(); i++) {
278 if (items.get(i).getCategoryBag() != null) {
279 AbstractSimpleValidator.validateKeyNotPresentKeyRef(items.get(i).getCategoryBag().getKeyedReference(), getMyKey(), "service");
280 AbstractSimpleValidator.validateKeyNotPresentKeyRefGrp(items.get(i).getCategoryBag().getKeyedReferenceGroup(), getMyKey(), "service");
281 }
282 if (items.get(i).getBindingTemplates() != null) {
283 validateValuesBindingTemplate(items.get(i).getBindingTemplates().getBindingTemplate(), xpath + xpath + "businessService(" + i + ").identifierBag.");
284 }
285 }
286 }
287
288 @Override
289 public void validateValuesPublisherAssertion(List<PublisherAssertion> items) throws DispositionReportFaultMessage {
290 if (items == null) {
291 return;
292 }
293 for (int i = 0; i < items.size(); i++) {
294 AbstractSimpleValidator.validateKeyNotPresentKeyRef(items.get(i).getKeyedReference(), getMyKey(), "publisherAssertion");
295 }
296 }
297
298
299 @Override
300 public void validateTmodelInstanceDetails(List<TModelInstanceInfo> tModelInstanceInfo, String xpath) throws DispositionReportFaultMessage {
301 if (tModelInstanceInfo == null) {
302 return;
303 }
304 for (int k = 0; k < tModelInstanceInfo.size(); k++) {
305 if (getMyKey().equalsIgnoreCase(tModelInstanceInfo.get(k).getTModelKey())) {
306 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "not allowed on tModel instance info"));
307 }
308 }
309 }
310
311 @Override
312 public void validateValuesTModel(List<TModel> items) throws DispositionReportFaultMessage {
313 if (items == null) {
314 return;
315 }
316 // In the case where a reference is made from an obsolete tModel the following validation rules apply:
317 EntityManager em = PersistenceManager.getEntityManager();
318 EntityTransaction tx = em.getTransaction();
319
320 try {
321 tx.begin();
322 for (int i = 0; i < items.size(); i++) {
323 if (items.get(i).getCategoryBag() != null) {
324 for (int k = 0; k < items.get(i).getCategoryBag().getKeyedReference().size(); k++) {
325 if (getMyKey().equalsIgnoreCase(items.get(i).getCategoryBag().getKeyedReference().get(k).getTModelKey())) {
326 //reference to self; this is invalid
327 if (items.get(i).getCategoryBag().getKeyedReference().get(k).getTModelKey().equalsIgnoreCase(items.get(i).getTModelKey())) {
328 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue() + " can't reference itself"));
329 }
330
331 Tmodel find = null;
332 try {
333 find = em.find(org.apache.juddi.model.Tmodel.class, items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue());
334
335 } catch (ClassCastException c) {
336 // reference to a service, binding or business; this is an invalid operation given that the entity being pointed to must be a tModel
337 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue() + " must be a tModel"));
338
339 }
340 if (find == null) {
341 // reference to a new tModel; this is a valid operation
342 if (!ContainsKey(items, items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue())) {
343 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getCategoryBag().getKeyedReference().get(k).getKeyValue() + " does not exist"));
344 }
345 }
346 }
347 }
348 }
349 if (items.get(i).getIdentifierBag() != null) {
350 for (int k = 0; k < items.get(i).getIdentifierBag().getKeyedReference().size(); k++) {
351 if (getMyKey().equalsIgnoreCase(items.get(i).getIdentifierBag().getKeyedReference().get(k).getTModelKey())) {
352 //reference to self; this is invalid
353 if (items.get(i).getIdentifierBag().getKeyedReference().get(k).getTModelKey().equalsIgnoreCase(items.get(i).getTModelKey())) {
354 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue() + " can't reference itself"));
355 }
356 Tmodel find = null;
357 try {
358 find = em.find(org.apache.juddi.model.Tmodel.class, items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue());
359
360 } catch (ClassCastException c) {
361 // reference to a service, binding or business; this is an invalid operation given that the entity being pointed to must be a tModel
362 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue() + " must be a tModel"));
363
364 }
365 if (find == null) {
366 // reference to a new tModel; this is a valid operation
367 if (!ContainsKey(items, items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue())) {
368 throw new InvalidValueException(new ErrorMessage("errors.valuesetvalidation.invalidcontent", "Referenced key " + items.get(i).getIdentifierBag().getKeyedReference().get(k).getKeyValue() + " does not exist"));
369 }
370 }
371 }
372 }
373 }
374 }
375 tx.commit();
376 } catch (DispositionReportFaultMessage d) {
377 throw d;
378 } finally {
379 if (tx.isActive()) {
380 tx.rollback();
381 }
382 em.close();
383 }
384 }
385
386 @Override
387 public List<String> getValidValues() {
388 return Collections.EMPTY_LIST;
389 }
390
391 private boolean ContainsKey(List<TModel> items, String keyValue) {
392 for (int i = 0; i < items.size(); i++) {
393 if (items.get(i).getTModelKey().equalsIgnoreCase(keyValue)) {
394 return true;
395 }
396 }
397 return false;
398 }
399
400 private boolean ContainsBusinessKey(List<BusinessEntity> items, String keyValue) {
401 for (int i = 0; i < items.size(); i++) {
402 if (items.get(i).getBusinessKey().equalsIgnoreCase(keyValue)) {
403 return true;
404 }
405 }
406 return false;
407 }
408
409 }