All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rcsb.cif.binary.BinaryCifReader Maven / Gradle / Ivy

package org.rcsb.cif.binary;

import org.rcsb.cif.CifOptions;
import org.rcsb.cif.ParsingException;
import org.rcsb.cif.binary.codec.BinaryCifCodec;
import org.rcsb.cif.binary.codec.MessagePackCodec;
import org.rcsb.cif.model.Block;
import org.rcsb.cif.model.Category;
import org.rcsb.cif.model.CifFile;
import org.rcsb.cif.model.LinkedCaseInsensitiveMap;
import org.rcsb.cif.model.binary.BinaryBlock;
import org.rcsb.cif.model.binary.BinaryCategory;
import org.rcsb.cif.model.binary.BinaryFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class BinaryCifReader {
    public BinaryCifReader(CifOptions options) {
    }

    @SuppressWarnings("unchecked")
    public CifFile read(InputStream inputStream) throws ParsingException {
        Map unpacked;
        try {
            unpacked = MessagePackCodec.decode(inputStream);
        } catch (ClassCastException e) {
            throw new ParsingException("File seems to not be in binary CIF format. Encountered unexpected cast.", e);
        } catch (Exception e) {
            throw new ParsingException("Parsing failed.", e);
        } finally {
            try {
                inputStream.close();
            } catch (IOException ignored) {

            }
        }

        String versionString = (String) unpacked.get("version");
        if (!versionString.startsWith(BinaryCifCodec.MIN_VERSION)) {
            throw new ParsingException("Unsupported format version. Current " + versionString +
                    ", required " + BinaryCifCodec.MIN_VERSION + ".");
        }

        String encoder = (String) unpacked.get("encoder");
        Object[] rawBlocks = (Object[]) unpacked.get("dataBlocks");
        List dataBlocks = new ArrayList<>(rawBlocks.length);

        for (Object rawBlock : rawBlocks) {
            Map map = (Map) rawBlock;
            String header = (String) map.get("header");
            Map categories = new LinkedCaseInsensitiveMap<>();

            try {
                for (Object o : (Object[]) map.get("categories")) {
                    Map cat = (Map) o;
                    String name = (String) cat.get("name");
                    categories.put(name.substring(1), createBinaryCategory(cat));
                }

                dataBlocks.add(new BinaryBlock(categories, header));
            } catch (NullPointerException e) {
                // don't really need this but the parser may be tricked by malformed files into exploring data and dying with NPE
                dataBlocks.add(new BinaryBlock(Collections.emptyMap(), header));
            }
        }

        return new BinaryFile(dataBlocks, versionString, encoder);
    }

    private Category createBinaryCategory(Map encodedCategory) {
        // if rowCount ever throws NPEs again: the problem is a wrongly parsed map length in MessagePackCodec
        String name = ((String) encodedCategory.get("name")).substring(1);
        Object rawColumns = encodedCategory.get("columns");
        int rowCount = (int) encodedCategory.get("rowCount");

        Object[] encodedFields = (Object[]) rawColumns;
        return new BinaryCategory(name, rowCount, encodedFields);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy