Innovimax-SARL/QuiXDM

View on GitHub
src/main/java/innovimax/quixproc/datamodel/event/AQuiXEvent.java

Summary

Maintainability
F
4 days
Test Coverage
/*
 * QuiXProc: efficient evaluation of XProc Pipelines.
 * Copyright (C) 2011-2018 Innovimax
 * All rights reserved.
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  You may obtain a copy of the License at
 *        http://www.apache.org/licenses/LICENSE-2.0*/
package innovimax.quixproc.datamodel.event;

import java.util.HashMap;
import java.util.Map;

import innovimax.quixproc.datamodel.IQuiXToken;
import innovimax.quixproc.datamodel.QuiXCharStream;
import innovimax.quixproc.datamodel.QuiXQName;
import innovimax.quixproc.datamodel.QuiXToken;

public abstract class AQuiXEvent implements IQuiXEvent, IQuiXToken {

    // TODO : store namespace context
    // TODO : store type information for PSVI

    // to enable CACHING for specific kind of type
    private static final boolean SEQUENCE_CACHING_ENABLED = false;
    private static final boolean DOCUMENT_CACHING_ENABLED = false;
    private static final boolean ELEMENT_CACHING_ENABLED = false;
    private static final boolean NAME_CACHING_ENABLED = false;

    private static long createCount = 0;
    private static long createCallCount = 0;
    private static long createDocCount = 0;
    private static long createAttrCount = 0;

    final QuiXToken type;

    /* constructors */
    AQuiXEvent(final QuiXToken type) {
        this.type = type;
        createCount++;
    }

    public abstract static class AXMLQuiXEvent extends AQuiXEvent {
        AXMLQuiXEvent(final QuiXToken token) {
            super(token);
        }
    }

    public abstract static class AJSONQuiXEvent extends AQuiXEvent {
        AJSONQuiXEvent(final QuiXToken token) {
            super(token);
        }
    }

    public abstract static class ARDFQuiXEvent extends AQuiXEvent {
        ARDFQuiXEvent(final QuiXToken token) {
            super(token);
        }
    }

    public abstract static class ACSVQuiXEvent extends AQuiXEvent {
        ACSVQuiXEvent(final QuiXToken token) {
            super(token);
        }
    }

    public static final class StartSequence extends AQuiXEvent {
        StartSequence() {
            super(QuiXToken.START_SEQUENCE);
        }

        @Override
        public String toString() {
            return this.type.toString();
        }
    }

    public static final class EndSequence extends AQuiXEvent {
        EndSequence() {
            super(QuiXToken.END_SEQUENCE);
        }

        @Override
        public String toString() {
            return this.type.toString();
        }
    }

    public static final class StartDocument extends AXMLQuiXEvent {
        private final QuiXCharStream uri;

        StartDocument(final QuiXCharStream uri) {
            super(QuiXToken.START_DOCUMENT);
            this.uri = uri;
            createDocCount++;
            // System.out.println("START DOCUMENT"+uri);
        }

        public QuiXCharStream getURI() {
            return this.uri;
        }

        @Override
        public String toString() {
            return this.type + " " + this.uri;
        }
    }

    public static final class EndDocument extends AXMLQuiXEvent {
        private final QuiXCharStream uri;

        EndDocument(final QuiXCharStream uri) {
            super(QuiXToken.END_DOCUMENT);
            this.uri = uri;
            createDocCount++;
            // System.out.println("END DOCUMENT"+uri);
        }

        public QuiXCharStream getURI() {
            return this.uri;
        }

        @Override
        public String toString() {
            return this.type + " " + this.uri;
        }
    }

    static class StartJSON extends AJSONQuiXEvent {
        StartJSON() {
            super(QuiXToken.START_JSON);
        }
    }

    static class EndJSON extends AJSONQuiXEvent {
        EndJSON() {
            super(QuiXToken.END_JSON);
        }
    }

    static class StartObject extends AJSONQuiXEvent {
        StartObject() {
            super(QuiXToken.START_OBJECT);
        }
    }

    static class EndObject extends AJSONQuiXEvent {
        EndObject() {
            super(QuiXToken.END_OBJECT);
        }
    }

    // start array is in JSON/YAML but also in CSV/TSV
    static class StartArray extends AQuiXEvent {
        StartArray() {
            super(QuiXToken.START_ARRAY);
        }
    }

    // start array is in JSON/YAML but also in CSV/TSV
    static class EndArray extends AQuiXEvent {
        EndArray() {
            super(QuiXToken.END_ARRAY);
        }
    }

    // Table CSV / TSV

    static class StartTable extends ACSVQuiXEvent {
        StartTable() {
            super(QuiXToken.START_TABLE);
        }
    }

    static class EndTable extends ACSVQuiXEvent {
        EndTable() {
            super(QuiXToken.END_TABLE);
        }
    }

    // RDF Triple

    static class StartRDF extends ARDFQuiXEvent {
        StartRDF() {
            super(QuiXToken.START_RDF);
        }
    }

    static class EndRDF extends ARDFQuiXEvent {
        EndRDF() {
            super(QuiXToken.END_RDF);
        }
    }

    static class StartPredicate extends ARDFQuiXEvent {
        final QuiXCharStream name;

        StartPredicate(final QuiXCharStream name) {
            super(QuiXToken.START_PREDICATE);
            this.name = name;
        }
    }

    static class EndPredicate extends ARDFQuiXEvent {
        final QuiXCharStream name;

        EndPredicate(final QuiXCharStream name) {
            super(QuiXToken.END_PREDICATE);
            this.name = name;
        }
    }

    static class Subject extends ARDFQuiXEvent {
        final QuiXCharStream name;

        Subject(final QuiXCharStream name) {
            super(QuiXToken.SUBJECT);
            this.name = name;
        }
    }

    static class Object extends ARDFQuiXEvent {
        final QuiXCharStream name;

        Object(final QuiXCharStream name) {
            super(QuiXToken.OBJECT);
            this.name = name;
        }
    }

    static class Graph extends ARDFQuiXEvent {
        final QuiXCharStream name;

        Graph(final QuiXCharStream name) {
            super(QuiXToken.GRAPH);
            this.name = name;
        }
    }

    // JSON

    static class AJSONValue extends AJSONQuiXEvent {
        AJSONValue(final QuiXToken token) {
            super(token);
        }
    }

    static class ValueNull extends AJSONValue {
        ValueNull() {
            super(QuiXToken.VALUE_NULL);
        }
    }

    static class ValueTrue extends AJSONValue {
        ValueTrue() {
            super(QuiXToken.VALUE_TRUE);
        }
    }

    static class ValueFalse extends AJSONValue {
        ValueFalse() {
            super(QuiXToken.VALUE_FALSE);
        }
    }

    static class ValueNumber extends AJSONValue {
        final double value;

        ValueNumber(final double value) {
            super(QuiXToken.VALUE_NUMBER);
            this.value = value;
        }
    }

    static class ValueString extends AJSONValue {
        final QuiXCharStream value;

        ValueString(final QuiXCharStream value) {
            super(QuiXToken.VALUE_STRING);
            this.value = value;
        }
    }

    static class KeyName extends AJSONQuiXEvent {
        private final QuiXCharStream name;

        KeyName(final QuiXCharStream name) {
            super(QuiXToken.KEY_NAME);
            this.name = name;
        }
    }

    public static final class Namespace extends AXMLQuiXEvent {
        private final QuiXCharStream prefix;
        private final QuiXCharStream uri;

        Namespace(final QuiXCharStream prefix, final QuiXCharStream uri) {
            super(QuiXToken.NAMESPACE);
            this.prefix = prefix;
            this.uri = uri;
        }

        public QuiXCharStream getPrefix() {
            return this.prefix;
        }

        public QuiXCharStream getURI() {
            return this.uri;
        }

        @Override
        public String toString() {
            return this.type + " " + this.prefix + ":" + this.uri;
        }
    }

    public abstract static class NamedEvent extends AXMLQuiXEvent {
        private final QuiXQName qname;

        NamedEvent(final QuiXQName qname, final QuiXToken type) {
            super(type);
            this.qname = qname;
        }

        public QuiXCharStream getLocalName() {
            return this.qname.getLocalPart();
        }

        public QuiXCharStream getFullName() {
            return (this.qname.getPrefix().isEmpty() ? QuiXCharStream.EMPTY : this.qname.getPrefix().append(":"))
                    .append(this.qname.getLocalPart());
        }

        public QuiXCharStream getURI() {
            return this.qname.getNamespaceURI();
        }

        public QuiXCharStream getPrefix() {
            return this.qname.getPrefix();
        }

        public QuiXQName getQName() {
            return this.qname;
        }
    }

    public static final class StartElement extends NamedEvent {
        StartElement(final QuiXQName qname) {
            super(qname, QuiXToken.START_ELEMENT);
            // System.out.println("START ELEMENT"+localName);
        }

        @Override
        public String toString() {
            return this.type + " " + getLocalName();
        }
    }

    public static final class EndElement extends NamedEvent {
        EndElement(final QuiXQName qname) {
            super(qname, QuiXToken.END_ELEMENT);
            // System.out.println("END ELEMENT" + localName);
        }

        @Override
        public String toString() {
            return this.type + " " + getLocalName();
        }
    }

    public static final class Attribute extends NamedEvent {
        private final QuiXCharStream value;

        Attribute(final QuiXQName qname, final QuiXCharStream value) {
            super(qname, QuiXToken.ATTRIBUTE);
            this.value = value;
            createAttrCount++;
            // System.out.println("ATTRIBUTE");
        }

        public QuiXCharStream getValue() {
            return this.value;
        }

        @Override
        public String toString() {
            return this.type + " " + getLocalName();
        }

    }

    public static final class Text extends AXMLQuiXEvent {
        private final QuiXCharStream data;

        Text(final QuiXCharStream data) {
            super(QuiXToken.TEXT);
            this.data = data;
            // System.out.println("TEXT");
        }

        public QuiXCharStream getData() {
            return this.data;
        }

        @Override
        public String toString() {
            return this.type + " " + this.data;
        }
    }

    public static final class PI extends AXMLQuiXEvent {
        private final QuiXCharStream target;
        private final QuiXCharStream data;

        PI(final QuiXCharStream target, final QuiXCharStream data) {
            super(QuiXToken.PROCESSING_INSTRUCTION);
            this.target = target;
            this.data = data;
        }

        public QuiXCharStream getTarget() {
            return this.target;
        }

        public QuiXCharStream getData() {
            return this.data;
        }

        @Override
        public String toString() {
            return this.type + " " + this.target;
        }
    }

    public static final class Comment extends AXMLQuiXEvent {
        private final QuiXCharStream data;

        Comment(final QuiXCharStream data) {
            super(QuiXToken.COMMENT);
            this.data = data;
        }

        public QuiXCharStream getData() {
            return this.data;
        }

        @Override
        public String toString() {
            return this.type + " " + this.data;
        }
    }

    public NamedEvent asNamedEvent() {
        return (NamedEvent) this;
    }

    public StartSequence asStartSequence() {
        return (StartSequence) this;
    }

    public EndSequence asEndSequence() {
        return (EndSequence) this;
    }

    public Namespace asNamespace() {
        return (Namespace) this;
    }

    public StartElement asStartElement() {
        return (StartElement) this;
    }

    public EndElement asEndElement() {
        return (EndElement) this;
    }

    public StartDocument asStartDocument() {
        return (StartDocument) this;
    }

    public EndDocument asEndDocument() {
        return (EndDocument) this;
    }

    public Text asText() {
        return (Text) this;
    }

    public Comment asComment() {
        return (Comment) this;
    }

    public PI asPI() {
        return (PI) this;
    }

    public Attribute asAttribute() {
        return (Attribute) this;
    }

    @Override
    public QuiXToken getType() {
        return this.type;
    }

    /* get typed event */

    private static final StartSequence newStartSequence = SEQUENCE_CACHING_ENABLED ? new StartSequence() : null;

    public static AQuiXEvent getStartSequence() {
        createCallCount++;
        return SEQUENCE_CACHING_ENABLED ? newStartSequence : new StartSequence();
    }

    private static final EndSequence newEndSequence = SEQUENCE_CACHING_ENABLED ? new EndSequence() : null;

    public static AQuiXEvent getEndSequence() {
        createCallCount++;
        return SEQUENCE_CACHING_ENABLED ? newEndSequence : new EndSequence();
    }

    private static final Map<QuiXCharStream, StartDocument> startDocumentMap = DOCUMENT_CACHING_ENABLED
            ? new HashMap<QuiXCharStream, StartDocument>() : null;

    public static AXMLQuiXEvent getStartDocument(final QuiXCharStream uri) {
        createCallCount++;
        final StartDocument result;
        if (DOCUMENT_CACHING_ENABLED) {
            synchronized (startDocumentMap) {
                if (startDocumentMap.containsKey(uri)) {
                    result = startDocumentMap.get(uri);
                } else {
                    result = new StartDocument(uri);
                    startDocumentMap.put(uri, result);
                }
            }
        } else {
            return new StartDocument(uri);
        }
        return result;
    }

    private static final Map<QuiXCharStream, EndDocument> endDocumentMap = DOCUMENT_CACHING_ENABLED
            ? new HashMap<QuiXCharStream, EndDocument>() : null;

    public static AXMLQuiXEvent getEndDocument(final QuiXCharStream uri) {
        createCallCount++;
        final EndDocument result;
        if (DOCUMENT_CACHING_ENABLED) {
            synchronized (endDocumentMap) {
                if (endDocumentMap.containsKey(uri)) {
                    result = endDocumentMap.get(uri);
                } else {
                    result = new EndDocument(uri);
                    endDocumentMap.put(uri, result);
                }
            }
        } else {
            return new EndDocument(uri);
        }
        return result;
    }

    public static Namespace getNamespace(final QuiXCharStream prefix, final QuiXCharStream uri) {
        return new Namespace(prefix == null ? QuiXCharStream.EMPTY : prefix, uri);
    }

    private static final Map<QuiXCharStream, QuiXQName> qNameMap = NAME_CACHING_ENABLED
            ? new HashMap<QuiXCharStream, QuiXQName>() : null;

    private static QuiXQName getQName(final QuiXCharStream localName, final QuiXCharStream namespace, final QuiXCharStream pref) {
        final QuiXQName result;
        final QuiXCharStream uri = namespace == null ? QuiXCharStream.EMPTY : namespace;
        final QuiXCharStream prefix = pref == null ? QuiXCharStream.EMPTY : pref;
        if (NAME_CACHING_ENABLED) {
            QuiXCharStream key = localName;
            // here the prefix plays no role
            // if (prefix.length() > 0) key = prefix + ":" + localName;
            if (!uri.isEmpty())
                key = QuiXCharStream.fromSequence("{").append(uri).append("}").append(key);
            synchronized (qNameMap) {
                if (qNameMap.containsKey(key)) {
                    result = qNameMap.get(key);
                } else {
                    result = new QuiXQName(uri, localName, prefix);
                    qNameMap.put(key, result);
                }
            }
        } else {
            return new QuiXQName(uri, localName, prefix);
        }
        return result;
    }

    private static final Map<QuiXQName, StartElement> startElementMap = ELEMENT_CACHING_ENABLED
            ? new HashMap<QuiXQName, StartElement>() : null;

    public static AXMLQuiXEvent getStartElement(final QuiXCharStream qName, final QuiXCharStream namespace) {
        QuiXCharStream localName = qName;
        QuiXCharStream prefix = null;
        if (qName.contains(":")) {
            prefix = qName.substringBefore(":");
            localName = qName.substringAfter(":");
        }
        return getStartElement(localName, namespace, prefix);
    }

    public static AXMLQuiXEvent getStartElement(final QuiXCharStream localName, final QuiXCharStream namespace,
                                                final QuiXCharStream prefix) {
        createCallCount++;
        final StartElement result;
        final QuiXQName qname = getQName(localName, namespace, prefix);
        if (ELEMENT_CACHING_ENABLED) {
            synchronized (startElementMap) {
                if (startElementMap.containsKey(qname)) {
                    result = startElementMap.get(qname);
                } else {
                    result = new StartElement(qname);
                    startElementMap.put(qname, result);
                }
            }
        } else {
            return new StartElement(qname);
        }
        return result;
    }

    private static final Map<QuiXQName, EndElement> endElementMap = ELEMENT_CACHING_ENABLED
            ? new HashMap<QuiXQName, EndElement>() : null;

    public static AXMLQuiXEvent getEndElement(final QuiXCharStream qName, final QuiXCharStream namespace) {
        QuiXCharStream localName = qName;
        QuiXCharStream prefix = null;
        if (qName.contains(":")) {
            prefix = qName.substringBefore(":");
            localName = qName.substringAfter(":");
        }
        return getEndElement(localName, namespace, prefix);
    }

    public static AXMLQuiXEvent getEndElement(final QuiXCharStream localName, final QuiXCharStream namespace,
                                              final QuiXCharStream prefix) {
        createCallCount++;
        final EndElement result;
        final QuiXQName qname = getQName(localName, namespace, prefix);
        if (ELEMENT_CACHING_ENABLED) {
            synchronized (endElementMap) {
                if (endElementMap.containsKey(qname)) {
                    result = endElementMap.get(qname);
                } else {
                    result = new EndElement(qname);
                    endElementMap.put(qname, result);
                }
            }
        } else {
            return new EndElement(qname);
        }
        return result;
    }

    public static AXMLQuiXEvent getAttribute(final QuiXCharStream qName, final QuiXCharStream namespace, final QuiXCharStream value) {
        QuiXCharStream localName = qName;
        QuiXCharStream prefix = null;
        if (qName.contains(":")) {
            prefix = qName.substringBefore(":");
            localName = qName.substringAfter(":");
        }
        return getAttribute(localName, namespace, prefix, value);
    }

    public static AXMLQuiXEvent getAttribute(final QuiXCharStream localName, final QuiXCharStream namespace, final QuiXCharStream prefix,
                                             final QuiXCharStream value) {
        createCallCount++;
        return new Attribute(getQName(localName, namespace, prefix), value);
    }

    public static AXMLQuiXEvent getText(final QuiXCharStream text) {
        createCallCount++;
        return new Text(text);
    }

    public static AXMLQuiXEvent getPI(final QuiXCharStream target, final QuiXCharStream data) {
        createCallCount++;
        return new PI(target, data);
    }

    public static AXMLQuiXEvent getComment(final QuiXCharStream comment) {
        createCallCount++;
        return new Comment(comment);
    }

    // JSON

    public static AJSONQuiXEvent getStartJSON() {
        return new StartJSON();
    }

    public static AJSONQuiXEvent getEndJSON() {
        return new EndJSON();
    }

    public static AJSONQuiXEvent getStartObject() {
        return new StartObject();
    }

    public static AJSONQuiXEvent getEndObject() {
        return new EndObject();
    }

    public static AQuiXEvent getStartArray() {
        return new StartArray();
    }

    public static AQuiXEvent getEndArray() {
        return new EndArray();
    }

    public static AJSONQuiXEvent getKeyName(final QuiXCharStream name) {
        return new KeyName(name);
    }

    public static AJSONQuiXEvent getValueNull() {
        return new ValueNull();
    }

    public static AJSONQuiXEvent getValueTrue() {
        return new ValueTrue();
    }

    public static AJSONQuiXEvent getValueFalse() {
        return new ValueFalse();
    }

    public static AJSONQuiXEvent getValueNumber(final double number) {
        return new ValueNumber(number);
    }

    public static AJSONQuiXEvent getValueString(final QuiXCharStream str) {
        return new ValueString(str);
    }

    // CSV/TSV

    public static ACSVQuiXEvent getStartTable() {
        return new StartTable();
    }

    public static ACSVQuiXEvent getEndTable() {
        return new EndTable();
    }

    // RDF

    public static ARDFQuiXEvent getStartRDF() {
        return new StartRDF();
    }

    public static ARDFQuiXEvent getEndRDF() {
        return new EndRDF();
    }

    public static ARDFQuiXEvent getStartPredicate(final QuiXCharStream name) {
        return new StartPredicate(name);
    }

    public static ARDFQuiXEvent getEndPredicate(final QuiXCharStream name) {
        return new EndPredicate(name);
    }

    public static ARDFQuiXEvent getSubject(final QuiXCharStream name) {
        return new Subject(name);
    }

    public static ARDFQuiXEvent getObject(final QuiXCharStream name) {
        return new Object(name);
    }

    public static ARDFQuiXEvent getGraph(final QuiXCharStream name) {
        return new Graph(name);
    }

    /* utilities */

    public boolean isStartSequence() {
        return this.type == QuiXToken.START_SEQUENCE;
    }

    public boolean isEndSequence() {
        return this.type == QuiXToken.END_SEQUENCE;
    }

    public boolean isStartDocument() {
        return this.type == QuiXToken.START_DOCUMENT;
    }

    public boolean isEndDocument() {
        return this.type == QuiXToken.END_DOCUMENT;
    }

    public boolean isStartElement() {
        return this.type == QuiXToken.START_ELEMENT;
    }

    public boolean isEndElement() {
        return this.type == QuiXToken.END_ELEMENT;
    }

    public boolean isAttribute() {
        return this.type == QuiXToken.ATTRIBUTE;
    }

    public boolean isText() {
        return this.type == QuiXToken.TEXT;
    }

    public boolean isPI() {
        return this.type == QuiXToken.PROCESSING_INSTRUCTION;
    }

    public boolean isComment() {
        return this.type == QuiXToken.COMMENT;
    }

    public boolean isNamespace() {
        return this.type == QuiXToken.NAMESPACE;
    }

    @Override
    public AQuiXEvent getEvent() {
        return this;
    }

    /* debugging */

    public static long getCreateCount() {
        return createCount;
    }

    public static long getCreateDocCount() {
        return createDocCount;
    }

    public static long getCreateAttrCount() {
        return createAttrCount;
    }

    public static long getCreateCallCount() {
        return createCallCount;
    }

    public static void resetCreateCount() {
        createCount = 0;
        createDocCount = 0;
        createAttrCount = 0;
        createCallCount = 0;
    }

}