import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
import org.apache.uima.UIMAException;
import org.apache.uima.fit.factory.JCasFactory;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.util.CasIOUtils;
import org.apache.uima.util.CasLoadMode;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;

/**
 * Example main for loading the CAS in compressed binary form 6 using 3 different settings.
 */

public class LoadCompressedBinary {

    private static void verifyContents(JCas jCas) {
        Collection<Container> containers = JCasUtil.select(jCas, Container.class);
        Container container = containers.stream().findFirst().get();
        FeatureAnnotation fr = container.getFeatures(0);
        System.out.println(String.format("%s has value %f", fr.getName(), fr.getValue()));
    }

    private static InputStream typeSystemInputStream(JCas jCas) throws IOException {
        try(ByteOutputStream bytes = new ByteOutputStream()) {
            CasIOUtils.writeTypeSystem(jCas.getCas(), bytes, true);
            return new ByteArrayInputStream(bytes.getBytes());
        }
    }

    public static void main(String[] args) throws UIMAException {
        try {
            JCas jCas = JCasFactory.createJCas();
            try (FileInputStream inputStream =
                         new FileInputStream(new File("compressed-filtered.bin"))) {
                // The following produce the same error:
                //CasIOUtils.load(inputStream, null, jCas.getCas(), CasLoadMode.REINIT);
                //CasIOUtils.load(inputStream, null, jCas.getCas());
                //CasIOUtils.load(inputStream, typeSystemInputStream(jCas), jCas.getCas());
                CasIOUtils.load(inputStream, jCas.getCas());

                // The following deserializes Container into org.apache.uima.cas.impl.AnnotationImpl:
                // CasIOUtils.load(inputStream, typeSystemInputStream(jCas), jCas.getCas(), CasLoadMode.REINIT);

                System.out.println("Loading compressed-filtered.bin completed");
                verifyContents(jCas);
            } catch (Exception e) {
                e.printStackTrace();
            }
            try (FileInputStream inputStream =
                         new FileInputStream(new File("compressed-filtered-ts.bin"))) {
                // The following produce uima.examples.types.Container:uima.examples.types.Container:features is
                // declared twice:
                // CasIOUtils.load(inputStream, null, jCas.getCas(), CasLoadMode.REINIT);
                // CasIOUtils.load(inputStream, typeSystemInputStream(jCas), jCas.getCas(), CasLoadMode.REINIT);
                // CasIOUtils.load(inputStream, typeSystemInputStream(jCas), jCas.getCas());
                CasIOUtils.load(inputStream, jCas.getCas());
                System.out.println("Loading compressed-filtered-ts.bin completed");
                verifyContents(jCas);
            } catch (Exception e) {
                e.printStackTrace();
            }
            try (FileInputStream inputStream =
                         new FileInputStream(new File("compressed-filtered-tsi.bin"))) {
                // The following deserializes Container into org.apache.uima.cas.impl.AnnotationImpl:
                // CasIOUtils.load(inputStream, typeSystemInputStream(jCas), jCas.getCas(), CasLoadMode.REINIT);
                // CasIOUtils.load(inputStream, null, jCas.getCas(), CasLoadMode.REINIT);

                // The following produce uima.examples.types.Container:uima.examples.types.Container:features is
                // declared twice:
                // CasIOUtils.load(inputStream, typeSystemInputStream(jCas), jCas.getCas());
                CasIOUtils.load(inputStream, jCas.getCas());
                System.out.println("Loading compressed-filtered-tsi.bin completed");
                verifyContents(jCas);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (UIMAException e) {
            e.printStackTrace();
            throw e;
        }

    }

}
