1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.openehealth.ipf.commons.ihe.xds.core.validate.requests;
17
18 import org.apache.commons.lang3.StringUtils;
19 import org.openehealth.ipf.commons.core.modules.api.Validator;
20 import org.openehealth.ipf.commons.ihe.xds.*;
21 import org.openehealth.ipf.commons.ihe.xds.core.ebxml.*;
22 import org.openehealth.ipf.commons.ihe.xds.core.metadata.*;
23 import org.openehealth.ipf.commons.ihe.xds.core.validate.*;
24
25 import java.util.*;
26 import java.util.stream.Collectors;
27
28 import static org.apache.commons.lang3.Validate.notNull;
29 import static org.openehealth.ipf.commons.ihe.xds.core.metadata.Vocabulary.*;
30 import static org.openehealth.ipf.commons.ihe.xds.core.metadata.Vocabulary.DisplayNameUsage.OPTIONAL;
31 import static org.openehealth.ipf.commons.ihe.xds.core.metadata.Vocabulary.DisplayNameUsage.REQUIRED;
32 import static org.openehealth.ipf.commons.ihe.xds.core.validate.ValidationMessage.*;
33 import static org.openehealth.ipf.commons.ihe.xds.core.validate.ValidatorAssertions.metaDataAssert;
34
35
36
37
38
39 public class ObjectContainerValidator implements Validator<EbXMLObjectContainer, ValidationProfile> {
40
41 private final SlotLengthAndNameUniquenessValidator slotLengthAndNameUniquenessValidator =
42 new SlotLengthAndNameUniquenessValidator();
43 private final OIDValidator oidValidator = new OIDValidator();
44 private final TimeValidator timeValidator = new TimeValidator();
45 private final TimeValidator timeValidatorSec = new TimeValidator(14);
46 private final XCNValidator xcnValidator = new XCNValidator();
47 private final XONValidator xonValidator = new XONValidator();
48 private final HashValidator hashValidator = new HashValidator();
49 private final NopValidator nopValidator = new NopValidator();
50 private final LanguageCodeValidator languageCodeValidator = new LanguageCodeValidator();
51 private final PositiveNumberValidator positiveNumberValidator = new PositiveNumberValidator();
52 private final PidValidator pidValidator = new PidValidator();
53 private final UriValidator uriValidator = new UriValidator();
54 private final RecipientListValidator recipientListValidator = new RecipientListValidator();
55 private final CXValidator cxValidatorRequiredAA = new CXValidator(true);
56 private final CXValidator cxValidatorOptionalAA = new CXValidator(false);
57 private final XTNValidator xtnValidator = new XTNValidator();
58 private final CXiValidator cxiValidator = new CXiValidator();
59 private final UUIDValidator uuidValidator = new UUIDValidator();
60
61 private final SlotValueValidation[] authorValidations = new SlotValueValidation[] {
62 new SlotValueValidation(SLOT_NAME_AUTHOR_PERSON, xcnValidator, 0, 1),
63 new SlotValueValidation(SLOT_NAME_AUTHOR_INSTITUTION, xonValidator, 0, Integer.MAX_VALUE),
64 new SlotValueValidation(SLOT_NAME_AUTHOR_ROLE, cxValidatorOptionalAA, 0, Integer.MAX_VALUE),
65 new SlotValueValidation(SLOT_NAME_AUTHOR_SPECIALTY, cxValidatorOptionalAA, 0, Integer.MAX_VALUE),
66 new SlotValueValidation(SLOT_NAME_AUTHOR_TELECOM, xtnValidator, 0, Integer.MAX_VALUE)};
67
68 private final SlotValueValidation[] codingSchemeValidations = new SlotValueValidation[] {
69 new SlotValueValidation(SLOT_NAME_CODING_SCHEME, nopValidator)};
70
71
72 private List<RegistryObjectValidator> documentEntrySlotValidators(ValidationProfile profile, boolean onDemandProvided, boolean limitedMetadata) {
73 List<RegistryObjectValidator> validators = new ArrayList<>();
74 boolean isContinuaHRN = (profile == CONTINUA_HRN.Interactions.ITI_41);
75 DisplayNameUsage requiredOnlyForContinuaHRN = isContinuaHRN ? REQUIRED : OPTIONAL;
76
77 boolean isOnDemand = (profile == XDS.Interactions.ITI_61) ||
78 (profile.isQuery() && onDemandProvided);
79
80 boolean needHashAndSize = (! isOnDemand) &&
81 (isContinuaHRN || profile.isQuery()
82 || (profile == XDS.Interactions.ITI_42)
83 || (profile == XDM.Interactions.ITI_41)
84 );
85
86 Collections.addAll(validators,
87 new SlotValueValidation(SLOT_NAME_CREATION_TIME, timeValidator,
88 (limitedMetadata || isOnDemand) ? 0 : 1,
89 isOnDemand ? 0 : 1),
90 new SlotValueValidation(SLOT_NAME_SERVICE_START_TIME, timeValidator, 0, 1),
91 new SlotValueValidation(SLOT_NAME_SERVICE_STOP_TIME, timeValidator, 0, 1),
92 new SlotValueValidation(SLOT_NAME_HASH, hashValidator,
93 needHashAndSize ? 1 : 0,
94 isOnDemand ? 0 : 1),
95 new SlotValueValidation(SLOT_NAME_LANGUAGE_CODE, languageCodeValidator, limitedMetadata ? 0 : 1, 1),
96 new SlotValueValidation(SLOT_NAME_LEGAL_AUTHENTICATOR, xcnValidator, 0,
97 (isOnDemand || isContinuaHRN) ? 0 : 1),
98 new SlotValueValidation(SLOT_NAME_SIZE, positiveNumberValidator,
99 needHashAndSize ? 1 : 0,
100 isOnDemand ? 0 : 1),
101 new SlotValueValidation(SLOT_NAME_SOURCE_PATIENT_ID, cxValidatorRequiredAA,
102 (profile.isEbXml30Based() && (! limitedMetadata)) ? 1 : 0, 1),
103 new SlotValueValidation(SLOT_NAME_SOURCE_PATIENT_INFO, pidValidator,
104 isContinuaHRN ? 1 : 0, Integer.MAX_VALUE),
105 new SlotValueValidation(SLOT_NAME_REFERENCE_ID_LIST, cxiValidator, 0, Integer.MAX_VALUE),
106 new SlotValueValidation(SLOT_NAME_URI, uriValidator, 0, 1),
107 new AuthorClassificationValidation(DOC_ENTRY_AUTHOR_CLASS_SCHEME, authorValidations),
108 new ClassificationValidation(DOC_ENTRY_CLASS_CODE_CLASS_SCHEME,
109 limitedMetadata ? 0 : 1, 1, requiredOnlyForContinuaHRN, codingSchemeValidations),
110 new ClassificationValidation(DOC_ENTRY_CONFIDENTIALITY_CODE_CLASS_SCHEME,
111 limitedMetadata ? 0 : 1, Integer.MAX_VALUE,
112 requiredOnlyForContinuaHRN, codingSchemeValidations),
113 new ClassificationValidation(DOC_ENTRY_EVENT_CODE_CLASS_SCHEME, 0, Integer.MAX_VALUE,
114 requiredOnlyForContinuaHRN, codingSchemeValidations),
115 new ClassificationValidation(DOC_ENTRY_FORMAT_CODE_CLASS_SCHEME,
116 limitedMetadata ? 0 : 1, 1, OPTIONAL, codingSchemeValidations),
117 new ClassificationValidation(DOC_ENTRY_HEALTHCARE_FACILITY_TYPE_CODE_CLASS_SCHEME,
118 limitedMetadata ? 0 : 1, 1, requiredOnlyForContinuaHRN, codingSchemeValidations),
119 new ClassificationValidation(DOC_ENTRY_PRACTICE_SETTING_CODE_CLASS_SCHEME,
120 limitedMetadata ? 0 : 1, 1, requiredOnlyForContinuaHRN, codingSchemeValidations),
121 new ClassificationValidation(DOC_ENTRY_TYPE_CODE_CLASS_SCHEME,
122 limitedMetadata ? 0 : 1, 1, requiredOnlyForContinuaHRN, codingSchemeValidations));
123
124 if (! limitedMetadata) {
125 validators.add(new ExternalIdentifierValidation(DOC_ENTRY_PATIENT_ID_EXTERNAL_ID, cxValidatorRequiredAA));
126 }
127
128 if ((profile.getInteractionId() == XDS.Interactions.ITI_42) || isOnDemand || profile.isQuery()) {
129 validators.add(new SlotValueValidation(SLOT_NAME_REPOSITORY_UNIQUE_ID, oidValidator));
130 }
131 return validators;
132 }
133
134 private List<RegistryObjectValidator> getSubmissionSetSlotValidations(ValidationProfile profile, boolean limitedMetadata) {
135 boolean isContinuaHRN = (profile == CONTINUA_HRN.Interactions.ITI_41);
136 DisplayNameUsage requiredOnlyForContinuaHRN = isContinuaHRN ? REQUIRED : OPTIONAL;
137
138 List<RegistryObjectValidator> validators = new ArrayList<>();
139 Collections.addAll(validators,
140 new SlotValidation(SLOT_NAME_INTENDED_RECIPIENT, recipientListValidator),
141 new SlotValueValidation(SLOT_NAME_SUBMISSION_TIME, timeValidator),
142 new AuthorClassificationValidation(SUBMISSION_SET_AUTHOR_CLASS_SCHEME, authorValidations),
143 new ClassificationValidation(SUBMISSION_SET_CONTENT_TYPE_CODE_CLASS_SCHEME,
144 limitedMetadata ? 0 : 1, 1, requiredOnlyForContinuaHRN, codingSchemeValidations),
145 new ExternalIdentifierValidation(SUBMISSION_SET_SOURCE_ID_EXTERNAL_ID, oidValidator));
146 if (! limitedMetadata) {
147 validators.add(new ExternalIdentifierValidation(SUBMISSION_SET_PATIENT_ID_EXTERNAL_ID, cxValidatorRequiredAA));
148 }
149 return validators;
150 }
151
152
153 private List<RegistryObjectValidator> getFolderSlotValidations(boolean limitedMetadata) {
154 List<RegistryObjectValidator> validators = new ArrayList<>();
155 Collections.addAll(validators,
156 new SlotValueValidation(SLOT_NAME_LAST_UPDATE_TIME, timeValidatorSec, 0, 1),
157 new ClassificationValidation(FOLDER_CODE_LIST_CLASS_SCHEME,
158 limitedMetadata ? 0 : 1, Integer.MAX_VALUE, OPTIONAL, codingSchemeValidations));
159 if (! limitedMetadata) {
160 validators.add(new ExternalIdentifierValidation(FOLDER_PATIENT_ID_EXTERNAL_ID, cxValidatorRequiredAA));
161 }
162 return validators;
163 }
164
165 private boolean checkLimitedMetadata(EbXMLRegistryObject object, String limitedMetadataClassScheme, ValidationProfile profile) {
166 boolean limitedMetadata = ! object.getClassifications(limitedMetadataClassScheme).isEmpty();
167 if (limitedMetadata) {
168 metaDataAssert((profile == XDM.Interactions.ITI_41) || (profile == XDR.Interactions.ITI_41),
169 ValidationMessage.LIMITED_METADATA_PROHIBITED, object.getId());
170 } else {
171 metaDataAssert(profile != XDM.Interactions.ITI_41,
172 ValidationMessage.LIMITED_METADATA_REQUIRED, object.getId());
173 }
174 return limitedMetadata;
175 }
176
177
178 @Override
179 public void validate(EbXMLObjectContainer container, ValidationProfile profile) {
180 notNull(container, "container cannot be null");
181 notNull(profile, "profile must be set");
182
183 slotLengthAndNameUniquenessValidator.validateContainer(container);
184
185
186 validateSubmissionSet(container, profile);
187 if (!profile.isQuery()) {
188 validateUniquenessOfUUIDs(container);
189 validateUniqueIds(container);
190 }
191 validateAssociations(container, profile);
192 validateDocumentEntries(container, profile);
193 validateFolders(container, profile);
194 if (!profile.isQuery()) {
195 validatePatientIdsAreIdentical(container);
196 }
197 }
198
199 private void validateFolders(EbXMLObjectContainer container, ValidationProfile profile) throws XDSMetaDataException {
200 Set<String> logicalIds = new HashSet<>();
201 for (EbXMLRegistryPackage folder : container.getRegistryPackages(FOLDER_CLASS_NODE)) {
202 boolean limitedMetadata = checkLimitedMetadata(folder, FOLDER_LIMITED_METADATA_CLASS_SCHEME, profile);
203 runValidations(folder, getFolderSlotValidations(limitedMetadata));
204
205 AvailabilityStatus status = folder.getStatus();
206 if (profile.isQuery() || status != null) {
207 metaDataAssert(status == AvailabilityStatus.APPROVED,
208 FOLDER_INVALID_AVAILABILITY_STATUS, status);
209 }
210
211 metaDataAssert(StringUtils.isBlank(folder.getLid()) || logicalIds.add(folder.getLid()),
212 LOGICAL_ID_SAME, folder.getLid());
213
214 LocalizedString name = folder.getName();
215 metaDataAssert(limitedMetadata || ((name != null) && (name.getValue() != null)),
216 MISSING_FOLDER_NAME, folder.getId());
217
218 if ((profile == XDS.Interactions.ITI_57) || (profile == XCMU.Interactions.CH_XCMU)) {
219 validateUpdateObject(folder, container);
220 }
221 }
222 }
223
224 private void validateSubmissionSet(EbXMLObjectContainer container, ValidationProfile profile) throws XDSMetaDataException {
225 List<EbXMLRegistryPackage> submissionSets = container.getRegistryPackages(SUBMISSION_SET_CLASS_NODE);
226 if (!profile.isQuery()) {
227 metaDataAssert(submissionSets.size() == 1, EXACTLY_ONE_SUBMISSION_SET_MUST_EXIST);
228 }
229
230 for (EbXMLRegistryPackage submissionSet : submissionSets) {
231 boolean limitedMetadata = checkLimitedMetadata(submissionSet, SUBMISSION_SET_LIMITED_METADATA_CLASS_SCHEME, profile);
232 runValidations(submissionSet, getSubmissionSetSlotValidations(profile, limitedMetadata));
233
234 AvailabilityStatus status = submissionSet.getStatus();
235 if (profile.isQuery() || (status != null)) {
236 metaDataAssert(status == AvailabilityStatus.APPROVED,
237 SUBMISSION_SET_INVALID_AVAILABILITY_STATUS, status);
238 }
239 }
240 }
241
242 private void validateDocumentEntries(EbXMLObjectContainer container, ValidationProfile profile) throws XDSMetaDataException {
243 Set<String> logicalIds = new HashSet<>();
244 for (EbXMLExtrinsicObject docEntry : container.getExtrinsicObjects(DocumentEntryType.STABLE_OR_ON_DEMAND)) {
245 boolean limitedMetadata = checkLimitedMetadata(docEntry, DOC_ENTRY_LIMITED_METADATA_CLASS_SCHEME, profile);
246
247 boolean onDemandExpected = (profile == XDS.Interactions.ITI_61);
248 boolean onDemandProvided = DocumentEntryType.ON_DEMAND.getUuid().equals(docEntry.getObjectType());
249 metaDataAssert(profile.isQuery() || (onDemandExpected == onDemandProvided),
250 WRONG_DOCUMENT_ENTRY_TYPE, docEntry.getObjectType());
251
252 runValidations(docEntry, documentEntrySlotValidators(profile, onDemandProvided, limitedMetadata));
253
254 if (profile.isQuery()) {
255 AvailabilityStatus status = docEntry.getStatus();
256 metaDataAssert(status == AvailabilityStatus.APPROVED || status == AvailabilityStatus.DEPRECATED,
257 DOC_ENTRY_INVALID_AVAILABILITY_STATUS, status);
258 }
259
260 LocalizedString name = docEntry.getName();
261 if (name != null && name.getValue() != null) {
262 metaDataAssert("UTF8".equals(name.getCharset()) || "UTF-8".equals(name.getCharset()),
263 INVALID_TITLE_ENCODING, name.getCharset());
264
265 metaDataAssert(name.getValue().length() <= 128,
266 TITLE_TOO_LONG, name.getValue());
267 }
268
269 boolean attachmentExpected = (profile.getInteractionId() == XCF.Interactions.ITI_63);
270 boolean attachmentProvided = (docEntry.getDataHandler() != null);
271 metaDataAssert(attachmentProvided == attachmentExpected,
272 attachmentExpected ? MISSING_DOCUMENT_FOR_DOC_ENTRY : DOCUMENT_NOT_ALLOWED_IN_DOC_ENTRY,
273 docEntry.getId());
274
275 metaDataAssert(profile.isQuery() || StringUtils.isBlank(docEntry.getLid()) || logicalIds.add(docEntry.getLid()),
276 LOGICAL_ID_SAME, docEntry.getLid());
277
278 if ((profile == XDS.Interactions.ITI_57) || (profile == XCMU.Interactions.CH_XCMU)) {
279 validateUpdateObject(docEntry, container);
280 }
281 }
282 }
283
284 private void runValidations(EbXMLRegistryObject obj, List<RegistryObjectValidator> validations) throws XDSMetaDataException {
285 for (RegistryObjectValidator validation : validations) {
286 validation.validate(obj);
287 }
288 }
289
290 private void validateUniqueIds(EbXMLObjectContainer container) throws XDSMetaDataException {
291 validateUniqueIds(container.getExtrinsicObjects(DocumentEntryType.STABLE_OR_ON_DEMAND), DOC_ENTRY_UNIQUE_ID_EXTERNAL_ID);
292 validateUniqueIds(container.getRegistryPackages(FOLDER_CLASS_NODE), FOLDER_UNIQUE_ID_EXTERNAL_ID);
293 validateUniqueIds(container.getRegistryPackages(SUBMISSION_SET_CLASS_NODE), SUBMISSION_SET_UNIQUE_ID_EXTERNAL_ID);
294 }
295
296 private void validateUniqueIds(List<? extends EbXMLRegistryObject> objects, String scheme) throws XDSMetaDataException {
297 for (EbXMLRegistryObject obj : objects) {
298 String uniqueId = obj.getExternalIdentifierValue(scheme);
299 metaDataAssert(uniqueId != null, UNIQUE_ID_MISSING);
300 metaDataAssert(uniqueId.length() <= 128, UNIQUE_ID_TOO_LONG);
301 }
302 }
303
304 private void validateUniquenessOfUUIDs(EbXMLObjectContainer container) throws XDSMetaDataException {
305 Set<String> uuids = new HashSet<>();
306 addUUIDs(container.getAssociations(), uuids);
307 addUUIDs(container.getExtrinsicObjects(), uuids);
308 addUUIDs(container.getRegistryPackages(), uuids);
309 }
310
311 private void addUUIDs(List<? extends EbXMLRegistryObject> objects, Set<String> uuids) throws XDSMetaDataException {
312 for (EbXMLRegistryObject obj : objects) {
313 String uuid = obj.getId();
314 if (uuid != null) {
315 metaDataAssert(!uuids.contains(uuid), UUID_NOT_UNIQUE);
316 uuids.add(uuid);
317 }
318 }
319 }
320
321 private void validatePatientIdsAreIdentical(EbXMLObjectContainer container) throws XDSMetaDataException {
322 List<EbXMLRegistryPackage> submissionSets = container.getRegistryPackages(SUBMISSION_SET_CLASS_NODE);
323 EbXMLRegistryPackage submissionSet = submissionSets.get(0);
324
325 String patientId = submissionSet.getExternalIdentifierValue(SUBMISSION_SET_PATIENT_ID_EXTERNAL_ID);
326
327 for (EbXMLExtrinsicObject docEntry : container.getExtrinsicObjects(DocumentEntryType.STABLE_OR_ON_DEMAND)) {
328 String patientIdDocEntry = docEntry.getExternalIdentifierValue(DOC_ENTRY_PATIENT_ID_EXTERNAL_ID);
329 metaDataAssert(StringUtils.equals(patientId, patientIdDocEntry), DOC_ENTRY_PATIENT_ID_WRONG);
330 }
331
332 for (EbXMLRegistryPackage folder : container.getRegistryPackages(FOLDER_CLASS_NODE)) {
333 String patientIdFolder = folder.getExternalIdentifierValue(FOLDER_PATIENT_ID_EXTERNAL_ID);
334 metaDataAssert(StringUtils.equals(patientId, patientIdFolder), FOLDER_PATIENT_ID_WRONG);
335 }
336 }
337
338 private void validateAssociations(EbXMLObjectContainer container, ValidationProfile profile) throws XDSMetaDataException {
339 Set<String> logicalIds = new HashSet<>();
340 Set<String> docEntryIds = container.getExtrinsicObjects(DocumentEntryType.STABLE_OR_ON_DEMAND).stream()
341 .filter(docEntry -> docEntry.getId() != null)
342 .map(EbXMLRegistryObject::getId)
343 .collect(Collectors.toSet());
344 Set<String> submissionSetIds = container.getRegistryPackages(SUBMISSION_SET_CLASS_NODE).stream()
345 .map(EbXMLRegistryObject::getId)
346 .collect(Collectors.toSet());
347 Set<String> associationIds = new HashSet<>();
348 boolean hasSubmitAssociationType = false;
349 for (EbXMLAssociation association : container.getAssociations()) {
350
351 associationIds.add(association.getId());
352
353 AssociationType type = association.getAssociationType();
354 metaDataAssert(type != null, INVALID_ASSOCIATION_TYPE);
355 hasSubmitAssociationType = hasSubmitAssociationType
356 || (type == AssociationType.SUBMIT_ASSOCIATION)
357 || (type == AssociationType.UPDATE_AVAILABILITY_STATUS);
358
359 metaDataAssert(StringUtils.isBlank(association.getLid()) || logicalIds.add(association.getLid()),
360 LOGICAL_ID_SAME, association.getLid());
361 }
362
363 for (EbXMLAssociation association : container.getAssociations()) {
364 switch (association.getAssociationType()) {
365 case HAS_MEMBER:
366 boolean isSubmissionSetToDocEntry =
367 submissionSetIds.contains(association.getSource()) && docEntryIds.contains(association.getTarget());
368 validateAssociation(association, docEntryIds, profile, isSubmissionSetToDocEntry);
369 break;
370
371 case IS_SNAPSHOT_OF:
372 if (!profile.isQuery()) {
373 EbXMLExtrinsicObject sourceDocEntry = getExtrinsicObject(
374 container, association.getSource(), DocumentEntryType.STABLE.getUuid());
375 metaDataAssert(sourceDocEntry != null, MISSING_SNAPSHOT_ASSOCIATION, "sourceObject", association.getSource());
376 metaDataAssert(hasSubmitAssociationType || docEntryIds.contains(association.getSource()), SOURCE_UUID_NOT_FOUND);
377 }
378 break;
379
380 case UPDATE_AVAILABILITY_STATUS:
381 if (!profile.isQuery()) {
382 metaDataAssert(submissionSetIds.contains(association.getSource()), MISSING_SUBMISSION_SET, association.getSource());
383 metaDataAssert(association.getOriginalStatus() != null, MISSING_ORIGINAL_STATUS);
384 metaDataAssert(association.getNewStatus() != null, MISSING_NEW_STATUS);
385 }
386 break;
387
388 case SUBMIT_ASSOCIATION:
389 if (!profile.isQuery()) {
390 metaDataAssert(submissionSetIds.contains(association.getSource()), MISSING_SUBMISSION_SET, association.getSource());
391 metaDataAssert(associationIds.contains(association.getTarget()), MISSING_ASSOCIATION, association.getTarget());
392 }
393 break;
394
395 default:
396 metaDataAssert(profile.isQuery() || hasSubmitAssociationType || docEntryIds.contains(association.getSource()), SOURCE_UUID_NOT_FOUND);
397 }
398 }
399 }
400
401 private void validateAssociation(EbXMLAssociation association, Set<String> docEntryIds,
402 ValidationProfile profile, boolean isSubmissionSetToDocEntry) throws XDSMetaDataException {
403 metaDataAssert(association.getSingleClassification(Vocabulary.ASSOCIATION_DOC_CODE_CLASS_SCHEME) == null,
404 DOC_CODE_NOT_ALLOWED_ON_HAS_MEMBER);
405
406 List<String> slotValues = association.getSlotValues(SLOT_NAME_SUBMISSION_SET_STATUS);
407 if (isSubmissionSetToDocEntry){
408 metaDataAssert(!slotValues.isEmpty(), SUBMISSION_SET_STATUS_MANDATORY);
409 }
410 if (!slotValues.isEmpty()) {
411 metaDataAssert(slotValues.size() == 1, TOO_MANY_SUBMISSION_SET_STATES);
412
413 AssociationLabel status = AssociationLabel.fromOpcode(slotValues.get(0));
414 metaDataAssert(status != null, INVALID_SUBMISSION_SET_STATUS);
415
416 if (status == AssociationLabel.ORIGINAL && !profile.isQuery()) {
417 metaDataAssert(docEntryIds.contains(association.getTarget()), MISSING_ORIGINAL);
418 }
419 }
420 }
421
422 private EbXMLExtrinsicObject getExtrinsicObject(EbXMLObjectContainer container, String docEntryId, String... objectTypes) {
423 for (EbXMLExtrinsicObject docEntry : container.getExtrinsicObjects(objectTypes)) {
424 if (docEntry.getId() != null && docEntry.getId().equals(docEntryId)) {
425 return docEntry;
426 }
427 }
428 return null;
429 }
430
431 private EbXMLRegistryPackage getRegistryPackage(EbXMLObjectContainer container, String submissionSetId, String classificationNode) {
432 for (EbXMLRegistryPackage registryPackage : container.getRegistryPackages(classificationNode)) {
433 if (registryPackage.getId() != null && registryPackage.getId().equals(submissionSetId)) {
434 return registryPackage;
435 }
436 }
437 return null;
438 }
439
440 private void validateUpdateObject(EbXMLRegistryObject registryObject, EbXMLObjectContainer container) {
441 metaDataAssert(registryObject.getLid() != null, LOGICAL_ID_MISSING);
442 uuidValidator.validate(registryObject.getLid());
443 metaDataAssert(!registryObject.getLid().equals(registryObject.getId()), LOGICAL_ID_EQUALS_ENTRY_UUID,
444 registryObject.getLid(), registryObject.getId());
445
446 boolean foundHasMemberAssociation = false;
447 for (EbXMLAssociation association : container.getAssociations()) {
448 if (association.getAssociationType() == AssociationType.HAS_MEMBER
449 && association.getTarget().equals(registryObject.getId())
450 && (getRegistryPackage(container, association.getSource(), SUBMISSION_SET_CLASS_NODE) != null))
451 {
452 metaDataAssert(association.getPreviousVersion() != null, MISSING_PREVIOUS_VERSION);
453 foundHasMemberAssociation = true;
454 }
455 }
456 metaDataAssert(foundHasMemberAssociation, MISSING_HAS_MEMBER_ASSOCIATION, registryObject.getId());
457 }
458 }