Package org.dcm4che3.json

Source Code of org.dcm4che3.json.JSONReader$Callback

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is part of dcm4che, an implementation of DICOM(TM) in
* Java(TM), hosted at https://github.com/gunterze/dcm4che.
*
* The Initial Developer of the Original Code is
* Agfa Healthcare.
* Portions created by the Initial Developer are Copyright (C) 2013
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* See @authors listed below
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

package org.dcm4che3.json;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumMap;

import javax.json.stream.JsonLocation;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
import javax.json.stream.JsonParsingException;

import org.dcm4che3.data.Attributes;
import org.dcm4che3.data.BulkData;
import org.dcm4che3.data.Fragments;
import org.dcm4che3.data.PersonName;
import org.dcm4che3.data.PersonName.Group;
import org.dcm4che3.data.Sequence;
import org.dcm4che3.data.VR;
import org.dcm4che3.util.Base64;
import org.dcm4che3.util.TagUtils;

/**
* @author Gunter Zeilinger <gunterze@gmail.com>
*
*/
public class JSONReader {

    public interface Callback {

        void onDataset(Attributes fmi, Attributes dataset);

    }

    private final JsonParser parser;
    private Attributes fmi;
    private JsonLocation location;
    private Event event;
    private final ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
    private final ArrayList<String> stringValues = new ArrayList<String>();
    private final ArrayList<Number> numberValues = new ArrayList<Number>();
    private final EnumMap<Group, String> personNameGroups =
            new EnumMap<PersonName.Group, String>(PersonName.Group.class);

    public JSONReader(JsonParser parser) {
        this.parser = parser;
    }

    public Attributes getFileMetaInformation() {
        return fmi;
    }

    private Event next() {
        location = parser.getLocation();
        return event = parser.next();
    }

    private String getString() {
        location = parser.getLocation();
        return parser.getString();
    }

    public Attributes readDataset(Attributes attrs) {
        if (next() != Event.START_OBJECT) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected Data Set object", location);
        }
        if (attrs == null) {
            attrs = new Attributes();
        }
        fmi = null;
        doReadDataset(attrs);
        return attrs;
    }

    public void readDatasets(Callback callback) {
        if (next() != Event.START_ARRAY) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected array of Data Set objects", location);
        }
        Attributes attrs;
        for (;;) {
            switch (next()) {
            case END_ARRAY:
                return;
            case START_OBJECT:
                fmi = null;
                attrs = new Attributes();
                doReadDataset(attrs);
                callback.onDataset(fmi, attrs);
                break;
            default:
                throw new JsonParsingException("Unexpected " + event
                        + ", expected Data Set object", location);
            }
        }
    }

    private void doReadDataset(Attributes attrs) {
        for (;;) {
            switch (next()) {
            case KEY_NAME:
                readAttribute(attrs);
                break;
            case END_OBJECT:
                attrs.trimToSize();
                return;
            default:
                throw new JsonParsingException("Unexpected " + event
                        + ", expected Tag value", location);
            }
        }
    }

    private void readAttribute(Attributes attrs) {
        String key = getString();
        int tag = (int) Long.parseLong(key, 16);
        if (TagUtils.isFileMetaInformation(tag)) {
            if (fmi == null)
                fmi = new Attributes();
            attrs = fmi;
        }
        if (next() != Event.START_OBJECT) {
            throw new JsonParsingException("Unexpected " + event
                    + " expected attribute object", location);
        }
        if (next() != Event.KEY_NAME) {
            throw new JsonParsingException("Unexpected " + event
                    + "\", expected \"vr\"", location);
        }
        key = getString();
        if (!"vr".equals(key)) {
            throw new JsonParsingException("Unexpected \"" + key
                    + "\", expected: \"vr\"", location);
        }
        if (next() != Event.VALUE_STRING) {
            throw new JsonParsingException("Unexpected " + event
                    + " expected vr value", location);
        }
        VR vr = VR.valueOf(parser.getString());
        switch (next()) {
        case END_OBJECT:
            attrs.setNull(tag, vr);
            break;
        case KEY_NAME:
            key = getString();
            if ("Value".equals(key)) {
                switch (vr) {
                case AE:
                case AS:
                case AT:
                case CS:
                case DA:
                case DT:
                case LO:
                case LT:
                case SH:
                case ST:
                case TM:
                case UI:
                case UT:
                    readStringValues(attrs, tag, vr);
                    break;
                case DS:
                case FL:
                case FD:
                case IS:
                case SL:
                case SS:
                case UL:
                case US:
                    readNumberValues(attrs, tag, vr);
                    break;
                case PN:
                    readPersonNames(attrs, tag);
                    break;
                case SQ:
                    readSequence(attrs, tag);
                    break;
                case OB:
                case OF:
                case OW:
                case UN:
                    throw new JsonParsingException("Unexpected \"Value\""
                            + "\", expected \"InlineBinary\""
                            + " or \"BulkDataURI\" or  \"DataFragment\"", location);
                }
            } else if ("InlineBinary".equals(key)) {
                attrs.setBytes(tag, vr, readInlineBinary());
            } else if ("BulkDataURI".equals(key)) {
                attrs.setValue(tag, vr, readBulkData(attrs.bigEndian()));
            } else if ("DataFragment".equals(key)) {
                readDataFragment(attrs, tag, vr);
            } else {
                throw new JsonParsingException("Unexpected \"" + key
                        + "\", expected \"Value\" or \"InlineBinary\""
                        + " or \"BulkDataURI\" or  \"DataFragment\"", location);
            }
            if (next() != Event.END_OBJECT) {
                throw new JsonParsingException("Unexpected " + event
                        + " expected end of attribute object", location);
            }
            break;
        default:
            throw new JsonParsingException("Unexpected " + event
                    + "\", expected \"Value\" or \"InlineBinary\""
                    + " or \"BulkDataURI\"", location);
        }
    }

    private void readStringValues(Attributes attrs, int tag, VR vr) {
        if (next() != Event.START_ARRAY) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected array of values", location);
        }
        for (;;) {
            switch (next()) {
            case END_ARRAY:
                attrs.setString(tag, vr,
                        stringValues.toArray(new String[stringValues.size()]));
                stringValues.clear();
                return;
            case VALUE_NULL:
                stringValues.add(null);
                break;
            case VALUE_STRING:
                stringValues.add(parser.getString());
                break;
            default:
                throw new JsonParsingException("Unexpected " + event
                        + ", expected string value", location);
            }
        }
    }

    private void readNumberValues(Attributes attrs, int tag, VR vr) {
        if (next() != Event.START_ARRAY) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected array of values", location);
        }
        for (;;) {
            switch (next()) {
            case END_ARRAY:
                switch(vr) {
                case DS:
                case FL:
                case FD:
                    attrs.setDouble(tag, vr, toDoubles(numberValues));
                    break;
                case IS:
                case SL:
                case SS:
                case UL:
                case US:
                    attrs.setInt(tag, vr, toInts(numberValues));
                    break;
                default:
                    assert true;
                }
                numberValues.clear();
                return;
            case VALUE_NUMBER:
                numberValues.add(parser.getBigDecimal());
                break;
            default:
                throw new JsonParsingException("Unexpected " + event
                        + ", expected number value", location);
            }
        }
    }

    private double[] toDoubles(ArrayList<Number> values) {
        double[] ds = new double[values.size()];
        for (int i = 0; i < ds.length; i++) {
            ds[i] = values.get(i).doubleValue();
        }
        return ds;
    }

    private int[] toInts(ArrayList<Number> values) {
        int[] is = new int[values.size()];
        for (int i = 0; i < is.length; i++) {
            is[i] = values.get(i).intValue();
        }
        return is;
    }

    private void readPersonNames(Attributes attrs, int tag) {
        if (next() != Event.START_ARRAY) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected array of person name objects", location);
        }
        for (;;) {
            switch (next()) {
            case END_ARRAY:
                attrs.setString(tag, VR.PN,
                        stringValues.toArray(new String[stringValues.size()]));
                stringValues.clear();
                return;
            case VALUE_NULL:
                stringValues.add(null);
                break;
            case START_OBJECT:
                stringValues.add(readPersonName());
                break;
            default:
                throw new JsonParsingException("Unexpected " + event
                        + ", expected person name object", location);
            }
        }
    }

    private String readPersonName() {
        PersonName.Group key;
        for (;;) {
            switch (next()) {
            case END_OBJECT:
                String retval = toString(personNameGroups);
                personNameGroups.clear();
                return retval;
            case KEY_NAME:
                try {
                    key = PersonName.Group.valueOf(getString());
                } catch (IllegalArgumentException e) {
                    throw new JsonParsingException("Unexpected \"" + e.getMessage()
                            + "\", expected \"Alphabetic\" or \"Ideographic\""
                            + " or \"Phonetic\"", location);
                }
                if (next() != Event.VALUE_STRING) {
                    throw new JsonParsingException("Unexpected " + event
                            + "\", expected person name value", location);
                }
                personNameGroups.put(key, parser.getString());
                break;
            default:
                 throw new JsonParsingException("Unexpected " + event
                         + ", expected \"Alphabetic\" or \"Ideographic\""
                         + " or \"Phonetic\"", location);
            }
        }
    }

    private String toString(EnumMap<Group, String> groups) {
        String s = groups.get(PersonName.Group.Alphabetic);
        if (s != null && groups.size() == 1)
            return s;
       
        StringBuilder sb = new StringBuilder(64);
        if (s != null)
            sb.append(s);
       
        sb.append('=');
        s = groups.get(PersonName.Group.Ideographic);
        if (s != null)
            sb.append(s);

        s = groups.get(PersonName.Group.Phonetic);
        if (s != null)
            sb.append('=').append(s);
       
        return sb.toString();
    }

    private void readSequence(Attributes attrs, int tag) {
        final Sequence seq = attrs.newSequence(tag, 10);
        Attributes fmi0 = fmi;
        readDatasets(new Callback(){

            @Override
            public void onDataset(Attributes fmi, Attributes item) {
                seq.add(item);
            }});

        fmi = fmi0;
        seq.trimToSize();
    }

    private byte[] readInlineBinary() {
        if (next() != Event.VALUE_STRING) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected bulk data URI", location);
        }
        char[] base64 = parser.getString().toCharArray();
        bout.reset();
        try {
            Base64.decode(base64, 0, base64.length, bout);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return bout.toByteArray();
    }

    private BulkData readBulkData(boolean bigEndian) {
        if (next() != Event.VALUE_STRING) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected bulk data URI", location);
        }
        String uri = parser.getString();
        return new BulkData(null, uri, bigEndian);
    }

    private void readDataFragment(Attributes attrs, int tag, VR vr) {
        if (next() != Event.START_ARRAY) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected array of data fragment objects", location);
        }
        Fragments frags = attrs.newFragments(tag, vr, 10);
        for (;;) {
            switch (next()) {
            case END_ARRAY:
                frags.trimToSize();
                return;
            case VALUE_NULL:
                frags.add(null);
                break;
            case START_OBJECT:
                frags.add(readDataFragment(attrs.bigEndian()));
                break;
            default:
                throw new JsonParsingException("Unexpected " + event
                        + ", expected data fragment object", location);
            }
        }
    }

    private Object readDataFragment(boolean bigEndian) {
        if (next() != Event.KEY_NAME) {
            throw new JsonParsingException("Unexpected " + event
                    + ", expected \"InlineBinary\""
                    + " or \"BulkDataURI\"", location);
        }
        String key = getString();
        Object value;
        if ("BulkDataURI".equals(key)) {
            value = readBulkData(bigEndian);
        } else if ("InlineBinary".equals(key)) {
            value = readInlineBinary();
        } else {
            throw new JsonParsingException("Unexpected \"" + key
                    + "\", expected \"InlineBinary\""
                    + " or \"BulkDataURI\"", location);
        }
        if (next() != Event.END_OBJECT) {
            throw new JsonParsingException("Unexpected " + event
                    + " expected end of data fragment object", location);
        }
        return value;
    }

}
TOP

Related Classes of org.dcm4che3.json.JSONReader$Callback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.