private void processDataStructureComponents()

in SdmxEdiParser/src/main/java/org/sdmxsource/sdmx/ediparser/engine/reader/impl/EDIStructureReaderEngineImpl.java [328:565]


        private void processDataStructureComponents(DataStructureMutableBean dataStructure) throws IOException {
            //Create a new map for the dimensions and attributes
            Map<Integer, DimensionMutableBean> dimensions = new TreeMap<Integer, DimensionMutableBean>();

            //Process DSD Dimensions, expecting 3 segments
            //1 = SCD+ defining dimension id, type (frequency or normal) and position (Required)
            //2 = ATT+3+5+::: defining field length (Required)
            //3 = IDE+1+ defining codelist reference (Required)
            boolean usingStatedPositions = false;
            int i = 1;
            List<String> dimensionGroup = new ArrayList<String>();
            try {
                while (true) {
                    readNextLine();
                    if (currentLine.startsWith("1+")) {
                        //Break as we are no longer processing 'basic' dimensions (1 is the time dimension)
                        int checkPos = 1;
                        for (Integer pos : dimensions.keySet()) {
                            if (pos.equals(checkPos)) {
                                checkPos++;
                                dataStructure.addDimension(dimensions.get(pos));
                            } else {
                                throw new IllegalArgumentException("Dimension position '" + checkPos + "' is missing, please ensure dimension positions are sequential starting from 1");
                            }
                        }
                        break;
                    }
                    Object[] scdSegment = processSCDSegment();

                    Integer dimPos = (Integer) scdSegment[2];
                    if (dimPos != null) {
                        if (i > 1) {
                            throw new IllegalArgumentException("Dimension positions specified for some dimensions but not others.  Please aither specify dimension positions for all dimensions, or do not specify positions.  Unspecified positions will be processed in file order.");
                        }
                        usingStatedPositions = true;
                    } else {
                        if (usingStatedPositions) {
                            throw new IllegalArgumentException("Dimension positions specified for some dimensions but not others.  Please aither specify dimension positions for all dimensions, or do not specify positions.  Unspecified positions will be processed in file order.");
                        }
                        dimPos = i;
                        i++;
                    }
                    if (dimensions.containsKey(dimPos)) {
                        throw new IllegalArgumentException("Duplicate dimension position : " + dimPos);
                    }
                    if (dimPos <= 0) {
                        throw new IllegalArgumentException("Dimension position must be a positive integer, can not process given position '" + dimPos + "'");
                    }
                    DimensionMutableBean dim = new DimensionMutableBeanImpl();
                    if (scdSegment[0].equals(13)) {
                        dim.setFrequencyDimension(true);
                        if (!dimPos.equals(1)) {
                            throw new IllegalArgumentException("Frequency dimension must be the first dimension, but has been given as dimension position : " + dimPos);
                        }
                    } else if (scdSegment[0].equals(4)) {
                        //dim.setFrequencyDimension(true);


                    } else {
                        throwSCDSegmentException("either", (Integer) scdSegment[0], 14, 13);
                    }

                    StructureReferenceBean conceptRef = getComponentConceptReference((String) scdSegment[1]);
                    dim.setConceptRef(conceptRef);
                    dimensionGroup.add(conceptRef.getIdentifiableIds()[0]);
                    readNextLine();
                    RepresentationMutableBean rep = new RepresentationMutableBeanImpl();
                    dim.setRepresentation(rep);

                    TextFormatMutableBean textFormat = processFieldLength();
                    rep.setTextFormat(textFormat);

                    readNextLine();
                    rep.setRepresentation(processCodelistReference());

                    dimensions.put(dimPos, dim);
                }
            } catch (Throwable th) {
                throw new IllegalArgumentException("Error while attempting to process key family dimension", th);
            }
            //Process Time Dimension, expecting 2 segments
            //1 = SCD+ defining dimension id, type (time 1) and position (Required)
            //2 = ATT+3+5+::: defining field length (Required)
            //The next line (SCD+1) should already have been read from the above loop
            try {
                Object[] scdSegment = processSCDSegment();
                readNextLine();
                RepresentationMutableBean tdRepresentation = new RepresentationMutableBeanImpl();
                TextFormatMutableBean textFormat = processFieldLength();
                textFormat.setTextType(TEXT_TYPE.OBSERVATIONAL_TIME_PERIOD);  //Override Time format to become OBSERVATIONAL TIME PERIOD
                tdRepresentation.setTextFormat(textFormat);
                DimensionMutableBean timeDimension = new DimensionMutableBeanImpl();
                timeDimension.setTimeDimension(true);
                timeDimension.setRepresentation(tdRepresentation);
                timeDimension.setConceptRef(getComponentConceptReference((String) scdSegment[1]));
                dataStructure.addDimension(timeDimension);
            } catch (Throwable th) {
                throw new IllegalArgumentException("Error while attempting to process time dimension", th);
            }

            readNextLine();
            try {
                //Process Time Format, expecting 3 segments
                //1 = SCD+ defining dimension id (TIME_FORMAT), type (time format 1) and position (Required)
                //2 = ATT+3+5+::: defining field length (Required)
                //3 = IDE+1+ defining codelist reference (Optional)
                //In reality this does not map to an SDMX Structure, so we can ignore it..
                AttributeMutableBean timeFormatAttribute = new AttributeMutableBeanImpl();
                Object[] scdSegment = processSCDSegment();
                if (!scdSegment[0].equals(1)) {
                    throwSCDSegmentException("time format", (Integer) scdSegment[0], 1);
                }
                timeFormatAttribute.setConceptRef(getComponentConceptReference((String) scdSegment[1]));
                timeFormatAttribute.setAttachmentLevel(ATTRIBUTE_ATTACHMENT_LEVEL.DIMENSION_GROUP);
                timeFormatAttribute.setAssignmentStatus("Mandatory");
                timeFormatAttribute.setDimensionReferences(dimensionGroup);
                readNextLine();
                RepresentationMutableBean tfRepresentation = new RepresentationMutableBeanImpl();
                timeFormatAttribute.setRepresentation(tfRepresentation);
                TextFormatMutableBean textFormat = processFieldLength();
                tfRepresentation.setTextFormat(textFormat);
                readNextLine();
                if (ediReader.getLineType().isCodelistReference()) {
                    tfRepresentation.setRepresentation(processCodelistReference());
                } else {
                    goBackLine();
                }
                dataStructure.addAttribute(timeFormatAttribute);
            } catch (Throwable th) {
                throw new IllegalArgumentException("Error while attempting to process time format", th);
            }
            //Process Primary Measure, expecting 2 segments
            //1 = SCD+ defining dimension id , type (3) and position (Required)
            //2 = ATT+3+5+::: defining field length (Required)
            readNextLine();
            try {
                Object[] scdSegment = processSCDSegment();
                if (!scdSegment[0].equals(3)) {
                    throwSCDSegmentException("primary measure", (Integer) scdSegment[0], 3);
                }
                readNextLine();
                TextFormatMutableBean textFormat = processFieldLength();
                PrimaryMeasureMutableBean primaryMeasure = new PrimaryMeasureMutableBeanImpl();
                RepresentationMutableBean pmRepresentation = new RepresentationMutableBeanImpl();
                pmRepresentation.setTextFormat(textFormat);
                primaryMeasure.setRepresentation(pmRepresentation);
                primaryMeasure.setConceptRef(getComponentConceptReference((String) scdSegment[1]));

                dataStructure.setPrimaryMeasure(primaryMeasure);
            } catch (Throwable th) {
                throw new IllegalArgumentException("Error while attempting to process primary measure", th);
            }
            //Process Observation Attributes, of which there are 1-3 each of which has 4-5 segments
            //1 = SCD+ defining dimension id , type (3) and position (Required)
            //2 = ATT+3+5+::: defining field length (Required)
            //3 = ATT+3+35+::: defining useage status (1=Optional, 2=Mandatory) (Required)
            //4 = ATT+3+32+::: defining attribute attachment level - in this case we are expecting observation (Required)
            //5 = IDE+1+ defining codelist reference (Optional)
            readNextLine();
            try {
                Object[] scdSegment = processSCDSegment();
                if (!scdSegment[0].equals(3)) {
                    throwSCDSegmentException("observation attribute", (Integer) scdSegment[0], 3);
                }
                AttributeMutableBean obsAttribute = new AttributeMutableBeanImpl();
                processAttribute(obsAttribute, (String) scdSegment[1]);
                dataStructure.addAttribute(obsAttribute);


                readNextLine();
                if (currentLine.startsWith("3+")) {
                    scdSegment = processSCDSegment();
                    if (!scdSegment[0].equals(3)) {
                        throwSCDSegmentException("Observation attribute", (Integer) scdSegment[0], 3);
                    }
                    obsAttribute = new AttributeMutableBeanImpl();
                    processAttribute(obsAttribute, (String) scdSegment[1]);
                    dataStructure.addAttribute(obsAttribute);


                    readNextLine();
                }

                if (currentLine.startsWith("3+")) {
                    scdSegment = processSCDSegment();
                    if (!scdSegment[0].equals(3)) {
                        throwSCDSegmentException("Observation attribute", (Integer) scdSegment[0], 3);
                    }
                    obsAttribute = new AttributeMutableBeanImpl();
                    processAttribute(obsAttribute, (String) scdSegment[1]);
                    dataStructure.addAttribute(obsAttribute);
                    readNextLine();
                }
            } catch (Throwable th) {
                throw new IllegalArgumentException("Error while attempting to process observation attributes, expecting observation status, followed by observation confidentiality, followed by observation pre-break", th);
            }


            //Process Other attributes
            //1 = SCD+Z09 defining attribute id (Required)
            //2 = ATT+3+5+::: defining field length (Required)
            //3 = ATT+3+35+::: defining useage status (1=Optional, 2=Mandatory) (Required)
            //4 = ATT+3+32+::: defining attribute attachment level - in this case we are expecting observation (Required)
            //5 = IDE+1+ defining codelist reference (Optional)

            //Can only have one group level attribute, so make sure we do not process 2
            boolean processedGroupAttribute = false;
            try {
                while (ediReader.getLineType().isAttribute()) {
                    AttributeMutableBean attribute = new AttributeMutableBeanImpl();
                    processAttribute(attribute, currentLine);
                    if (attribute.getAttachmentLevel() == ATTRIBUTE_ATTACHMENT_LEVEL.GROUP) {
                        if (!processedGroupAttribute) {
                            GroupMutableBean siblingGroup = new GroupMutableBeanImpl();
                            siblingGroup.setId(EDIUtil.getSiblingGroupId());
                            dataStructure.addGroup(siblingGroup);
                            List<String> dimensionRef = new ArrayList<String>();
                            for (DimensionMutableBean currentDim : dataStructure.getDimensions()) {
                                if (!currentDim.isFrequencyDimension() && !currentDim.isTimeDimension()) {
                                    dimensionRef.add(currentDim.getConceptRef().getChildReference().getId());
                                }
                            }
                            siblingGroup.setDimensionRef(dimensionRef);
                        }
                        attribute.setAttachmentGroup(EDIUtil.getSiblingGroupId());
                        processedGroupAttribute = true;
                    } else if (attribute.getAttachmentLevel() == ATTRIBUTE_ATTACHMENT_LEVEL.DIMENSION_GROUP) {
                        attribute.setDimensionReferences(dimensionGroup);
                    }
                    dataStructure.addAttribute(attribute);
                    readNextLine();
                }
            } catch (Throwable th) {
                throw new IllegalArgumentException("Error while attempting to process key family attribute", th);
            }
            //Go back line, as we have gone past the end of the key famliy
            goBackLine();
        }