View Javadoc
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 &quot;Times New
73   * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
79   * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
84   * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
89   * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
95   * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
101  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
107  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
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 &quot;Times New
117  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
122  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
127  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
133  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
138  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
144  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
149  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 &quot;Times New
154  * Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </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 }