private void parseApp5SubDescriptors()

in src/main/java/com/netflix/imflibrary/st2067_2/CompositionImageEssenceDescriptorModel.java [586:707]


    private void parseApp5SubDescriptors() {
        DOMNodeObjectModel subDescriptors = imageEssencedescriptorDOMNode.getDOMNode(regXMLLibDictionary.getSymbolNameFromURN(subdescriptorsUL));
        if (subDescriptors != null) {
            List<DOMNodeObjectModel> acesPictureSubDescriptors = subDescriptors.getDOMNodes(regXMLLibDictionary.getSymbolNameFromURN(acesPictureSubDescriptorUL));
            List<DOMNodeObjectModel> targetFrameSubDescriptors = subDescriptors.getDOMNodes(regXMLLibDictionary.getSymbolNameFromURN(targetFrameSubDescriptorUL));
            List<DOMNodeObjectModel> containerConstraintsSubDescriptors = subDescriptors.getDOMNodes(regXMLLibDictionary.getSymbolNameFromURN(containerConstraintsSubDescriptorUL));
            if (!acesPictureSubDescriptors.isEmpty()) {
                for (DOMNodeObjectModel domNodeObjectModel : acesPictureSubDescriptors) {
                    String authoring_information = domNodeObjectModel.getFieldAsString(regXMLLibDictionary.getSymbolNameFromURN(acesAuthoringInformationUL));
                    if ((authoring_information == null) || authoring_information.isEmpty()) {
                        imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                                IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
                                String.format("ACES Picture SubDescriptor (ID %s): Optional item ACES Authoring Information is not present or empty", domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).toString()));
                    }
                    DOMNodeObjectModel  primaries = domNodeObjectModel.getDOMNode(regXMLLibDictionary.getSymbolNameFromURN(acesMasteringDisplayPrimariesUL));
                    DOMNodeObjectModel  whitePoint = domNodeObjectModel.getDOMNode(regXMLLibDictionary.getSymbolNameFromURN(acesMasteringDisplayWhitePointChromaticityUL));
                    Integer maxLum = domNodeObjectModel.getFieldAsInteger(regXMLLibDictionary.getSymbolNameFromURN(acesMasteringDisplayDisplayMaximumLuminanceUL));
                    Integer minLum = domNodeObjectModel.getFieldAsInteger(regXMLLibDictionary.getSymbolNameFromURN(acesMasteringDisplayDisplayMinimumLuminanceUL));
                    if (!(((primaries == null) && (whitePoint == null) && (maxLum == null) && (minLum == null))
                            || ((primaries != null) && (whitePoint != null) && (maxLum != null) && (minLum != null)))) {
                        imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                                IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL,
                                String.format("ACES Picture SubDescriptor (ID %s) shall have either all or none of the following elements: Mastering Display Primaries, White Point, Maximum Luminance, Minimum Luminance", domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).toString()));
                    }
                }
            } else {
                imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                        IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
                        String.format("INFO (can be ignored): EssenceDescriptor with ID %s: No ACESPictureSubDescriptor found", imageEssencedescriptorID.toString()));
            }
            if (!targetFrameSubDescriptors.isEmpty()) {
                for (DOMNodeObjectModel domNodeObjectModel : targetFrameSubDescriptors) {
                    String missing_items = "";
                    Set<UUID> targetFrameAncillaryResourceID = domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(targetFrameAncillaryResourceIDUL));
                    // Check for missing required items
                    if (targetFrameAncillaryResourceID.isEmpty()) {
                        missing_items += "TargetFrameAncillaryResourceID, ";
                    } else {
                        //TODO Check it targetFrameAncillaryResourceID belongs to an existing GSP
                        imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                                IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
                                String.format("INFO (can be ignored): Target FrameSubDescriptor (ID %s) references an Ancillary Resource (ID %s), but Ancillary Resources cannot be checked yet", 
                                        domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).toString(), targetFrameAncillaryResourceID.toString()));
                    }
                    String media_type = domNodeObjectModel.getFieldAsString(regXMLLibDictionary.getSymbolNameFromURN(mediaTypeUL));
                    if (media_type == null) {
                        missing_items += "MediaType, ";
                    }
                    Long index = domNodeObjectModel.getFieldAsLong(regXMLLibDictionary.getSymbolNameFromURN(targetFrameIndexUL));
                    if (index == null) {
                        missing_items += "TargetFrameIndex, ";
                    }
                    UL transfer = domNodeObjectModel.getFieldAsUL(regXMLLibDictionary.getSymbolNameFromURN(targetFrameTransferCharacteristicUL));
                    if (transfer == null) {
                        missing_items += "TargetFrameTransferCharacteristic, ";
                    }
                    UL color = domNodeObjectModel.getFieldAsUL(regXMLLibDictionary.getSymbolNameFromURN(targetFrameColorPrimariesUL));
                    if (color == null) {
                        missing_items += "TargetFrameColorPrimaries, ";
                    }
                    Integer max_ref = domNodeObjectModel.getFieldAsInteger(regXMLLibDictionary.getSymbolNameFromURN(targetFrameComponentMaxRefUL));
                    if (max_ref == null) {
                        missing_items += "TargetFrameComponentMaxRef, ";
                    }
                    Integer min_ref = domNodeObjectModel.getFieldAsInteger(regXMLLibDictionary.getSymbolNameFromURN(targetFrameComponentMinRefUL));
                    if (min_ref == null) {
                        missing_items += "TargetFrameComponentMinRef, ";
                    }
                    Integer stream_id = domNodeObjectModel.getFieldAsInteger(regXMLLibDictionary.getSymbolNameFromURN(targetFrameEssenceStreamIDUL));
                    if (stream_id == null) {
                        missing_items += "TargetFrameEssenceStreamID";
                    }
                    if (!missing_items.isEmpty()) {
                        imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                                IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL,
                                String.format("Target FrameSubDescriptor (ID %s): is missing required item(s): %s", domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).toString(), missing_items));
                    }

                    // Check if acesPictureSubDescriptorInstanceID references an existing ACESPictureSubDescriptor Instance ID
                    Set<UUID> acesPictureSubDescriptorInstanceID = domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(acesPictureSubDescriptorInstanceIDUL));
                    if (!acesPictureSubDescriptorInstanceID.isEmpty()) {
                        if (acesPictureSubDescriptors.isEmpty()) {
                            imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                                    IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL,
                                    String.format("Target FrameSubDescriptor (ID %s) references an ACESPictureSubDescriptorInstanceID (%s) but no ACESPictureSubDescriptor is present", 
                                            domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).toString(), acesPictureSubDescriptorInstanceID.toString()));
                        } else {
                            if (acesPictureSubDescriptors.stream().noneMatch(e -> e.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).equals(acesPictureSubDescriptorInstanceID))) {
                                imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                                        IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL,
                                        String.format("Target FrameSubDescriptor (ID %s) references an ACESPictureSubDescriptor but no ACESPictureSubDescriptor with Instance ID (%s) is present", 
                                                domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).toString(), acesPictureSubDescriptorInstanceID.toString()));
                            }
                        }
                        
                    }
                    
                    if ((max_ref != null) && (min_ref != null)) {
                        if (max_ref <= min_ref) {
                            imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                                    IMFErrorLogger.IMFErrors.ErrorLevels.NON_FATAL,
                                    String.format("Target FrameSubDescriptor (ID %s): TargetFrameComponentMaxRef (%d) is less than or equal to TargetFrameComponentMaxRef (%d)", domNodeObjectModel.getFieldsAsUUID(regXMLLibDictionary.getSymbolNameFromURN(instanceID)).toString(), max_ref, min_ref));
                        }
                    }
                }
            } else {
                imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                        IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
                        String.format("INFO (can be ignored): EssenceDescriptor with ID %s: No TargetFrameSubDescriptor found", imageEssencedescriptorID.toString()));
            }
            if (containerConstraintsSubDescriptors.isEmpty()) {
                imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                        IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
                        String.format("EssenceDescriptor with ID %s: A ContainerConstraintsSubDescriptor shall be present per ST 379-2, but is missing", imageEssencedescriptorID.toString()));
            }
        } else {
            imfErrorLogger.addError(IMFErrorLogger.IMFErrors.ErrorCodes.APPLICATION_COMPOSITION_ERROR,
                    IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
                    String.format("INFO (can be ignored): EssenceDescriptor with ID %s: No ACESPictureSubDescriptor and no TargetFrameSubDescriptor found", imageEssencedescriptorID.toString()));
        }
        return;
    }