Search code examples
javaparsingmaster-detailfixed-widthunivocity

Univocity master detail relationship beans


I have a fixed structured file like this

5 type records, GM, AB, TM, DM, IN

TM and DM as you see is a master-detail relationship

but also DM and IN are in a master-detail relationship

GM01012020
ABXX-43432
TM        CODE1
DM   DESC1
INDESC1
INDESC2
INDESC3
DM   DESC2
INDESC1
INDESC2
INDESC3
TM        CODE2
DM   DESC3
INDESC1
INDESC2
DM   DESC4
INDESC1

I managed to collect all the rows in beans but separated way..I need to find a way to associate the master records

    FixedWidthParserSettings settings;

    settings = new FixedWidthParserSettings();
    settings.setAutoConfigurationEnabled(true);
    settings.setHeaderExtractionEnabled(false);
    settings.setRecordEndsOnNewline(true);
    settings.trimValues(false);

    FixedWidthFields gm = FixedWidthFields.forParsing(Gm.class);
    FixedWidthFields ab = FixedWidthFields.forParsing(Ab.class);
    FixedWidthFields tm = FixedWidthFields.forParsing(Tm.class);
    FixedWidthFields dm = FixedWidthFields.forParsing(Dm.class);
    FixedWidthFields in = FixedWidthFields.forParsing(In.class);

    settings.addFormatForLookahead("GM", gm);
    settings.addFormatForLookahead("AB", ab);
    settings.addFormatForLookahead("TM", tm);
    settings.addFormatForLookahead("DM", dm);
    settings.addFormatForLookahead("IN", in);

    final BeanListProcessor<Gm> gmProcessor = new BeanListProcessor<Gm>(Gm.class);
    final BeanListProcessor<Ab> abprocessor = new BeanListProcessor<Ab>(Ab.class);
    final BeanListProcessor<Tm> tmProcessor = new BeanListProcessor<Tm>(Tm.class);
    final BeanListProcessor<Dm> dmProcessor = new BeanListProcessor<Dm>(Dm.class);
    final BeanListProcessor<In> inProcessor = new BeanListProcessor<In>(In.class);

    InputValueSwitch inputValueSwitch = new InputValueSwitch(0);

    inputValueSwitch.addSwitchForValue("GM", bgmProcessor);
    inputValueSwitch.addSwitchForValue("AB", abProcessor);
    inputValueSwitch.addSwitchForValue("TM", tmProcessor);
    inputValueSwitch.addSwitchForValue("DM", dmProcessor);
    inputValueSwitch.addSwitchForValue("IN", inProcessor);

    settings.setProcessor(inputValueSwitch);

    inputValueSwitch.setDefaultSwitch(bgmProcessor);
    FixedWidthParser parser = new FixedWidthParser(settings);

    parser.parse(f);

    //Gm bgmRecord = (Gm) gmProcessor.getBeans();
    List<Ab> abRecords = abProcessor.getBeans();
    List<Tm> tmRecords = tmProcessor.getBeans();
    List<Dm> dmRecords = dmProcessor.getBeans();
    List<In> inRecords = inProcessor.getBeans();

I could managed to extract all the records but still cannot associate MD relationship.. I've read the examples on univocity doc but couldn't make it work

In Tm Bean there is a list of Dm bean and of course in Dm bean the list of in Bean

UPDATE

I'm USING MasterDetailListProcessor but can get only 1 level of master-detail


Solution

  • You should implement rowProcessorSwitched like this

    InputValueSwitch inputValueSwitch = new InputValueSwitch(0) {
        private Tm currentTmMaster;
        private Dm currentDmMaster;
    
        public void rowProcessorSwitched(RowProcessor from, RowProcessor to) {
            if (from == tmProcessor && to == dmProcessor) {
                // going From TM to DM, assign as currentTm the last element of list
                currentTmMaster = tmProcessor.getBeans().get(tmProcessor.getBeans().size() - 1);
            }
    
            if (from == dmProcessor && to == inProcessor) {
                // going from a new block of In, assign to the current Tm elem, all the dm(s) elements
                currentTmMaster.getDm().addAll(dmProcessor.getBeans());
                currentDmMaster = dmProcessor.getBeans().get(dmProcessor.getBeans().size() - 1);
                dmProcessor.getBeans().clear();
            }
    
            if (from == inProcessor) {
                // each block of In, assign it to the current DM
                currentDmMaster.getIn().addAll(inProcessor.getBeans());
                inProcessor.getBeans().clear();
            }
        }
    };