source: FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/AdvancedDataViewWriter.java @ 6884

Last change on this file since 6884 was 6884, checked in by Oliver Schonefeld, 8 years ago
  • Property svn:eol-style set to native
File size: 6.9 KB
Line 
1package eu.clarin.sru.server.fcs;
2
3import java.net.URI;
4import java.util.ArrayList;
5import java.util.HashMap;
6import java.util.List;
7import java.util.Map;
8
9import javax.xml.stream.XMLStreamException;
10import javax.xml.stream.XMLStreamWriter;
11
12
13public class AdvancedDataViewWriter {
14    public enum Unit {
15        ITEM,
16        TIMESTAMP
17    }
18    private static final long INITIAL_SEGMENT_ID = 1;
19    public static final int NO_HIGHLIGHT = -1;
20    private static final String ADV_PREFIX = "adv";
21    private static final String ADV_NS = "http://clarin.eu/fcs/dataview/advanced";
22    private static final String ADV_MIME_TYPE = "application/x-clarin-fcs-adv+xml";
23    private final Unit unit;
24    private final List<Segment> segments = new ArrayList<Segment>();
25    private final Map<URI, List<Span>> layers = new HashMap<URI, List<Span>>();
26    private long nextSegmentId = INITIAL_SEGMENT_ID;
27
28
29    public AdvancedDataViewWriter(Unit unit) {
30        if (unit == null) {
31            throw new NullPointerException("unit == null");
32        }
33        this.unit = unit;
34    }
35
36
37    public void reset() {
38        nextSegmentId = INITIAL_SEGMENT_ID;
39    }
40
41
42    private static final class Segment {
43        private final String id;
44        private final long start;
45        private final long end;
46        private final URI ref;
47
48        private Segment(long id, long start, long end) {
49            this.id = "s" + Long.toHexString(id);
50            this.start = start;
51            this.end = end;
52            this.ref = null;
53        }
54    }
55
56    private static final class Span {
57        private final Segment segment;
58        private final String value;
59        private final String altValue;
60        private final String highlight;
61
62
63        private Span(Segment segment, String value, String altValue,
64                int highlight) {
65            this.segment = segment;
66            this.value = value;
67            this.altValue = altValue;
68            if (highlight != NO_HIGHLIGHT) {
69                this.highlight = "h" + Integer.toHexString(highlight);
70            } else {
71                this.highlight = null;
72            }
73        }
74    }
75
76
77    public void addSpan(URI layerId, long start, long end, String value) {
78        addSpan(layerId, start, end, value, null, NO_HIGHLIGHT);
79    }
80
81
82    public void addSpan(URI layerId, long start, long end, String value,
83            int highlight) {
84        addSpan(layerId, start, end, value, null, highlight);
85    }
86
87
88    public void addSpan(URI layerId, long start, long end, String value,
89            String altValue) {
90        addSpan(layerId, start, end, value, altValue, NO_HIGHLIGHT);
91    }
92
93
94    public void addSpan(URI layerId, long start, long end, String value,
95            String altValue, int highlight) {
96        if (layerId == null) {
97            throw new NullPointerException("layerId == null");
98        }
99        if (start < 0) {
100            throw new IllegalArgumentException("start < 0");
101        }
102        if (end < start) {
103            throw new IllegalArgumentException("end < start");
104        }
105        if (highlight <= 0) {
106            highlight = NO_HIGHLIGHT;
107        }
108
109        // find segment or create a new one
110        Segment segment = null;
111        for (Segment seg : segments) {
112            if ((seg.start == start) && (seg.end == end)) {
113                segment = seg;
114                break;
115            }
116        }
117        if (segment == null) {
118            segment = new Segment(nextSegmentId++, start, end);
119            segments.add(segment);
120        }
121
122        // find layer or create a new one
123        List<Span> layer = layers.get(layerId);
124        if (layer == null) {
125            layer = new ArrayList<Span>();
126            layers.put(layerId, layer);
127        }
128
129        // sanity check (better overlap check?)
130        for (Span span : layer) {
131            if (segment.equals(span.segment)) {
132                // FIXME: better exception!
133                throw new IllegalArgumentException("segment already exists in layer");
134            }
135        }
136        layer.add(new Span(segment, value, altValue, highlight));
137    }
138
139
140    public void writeAdvancedDataView(XMLStreamWriter writer)
141            throws XMLStreamException {
142        if (writer == null) {
143            throw new NullPointerException("writer == null");
144        }
145
146        XMLStreamWriterHelper.writeStartDataView(writer, ADV_MIME_TYPE);
147        writer.setPrefix(ADV_PREFIX, ADV_NS);
148        writer.writeStartElement(ADV_NS, "Advanced");
149        writer.writeNamespace(ADV_PREFIX, ADV_NS);
150        if (unit == Unit.ITEM) {
151            writer.writeAttribute("unit", "item");
152        } else if (unit == Unit.TIMESTAMP) {
153            writer.writeAttribute("unit", "timestamp");
154        }
155
156        // segments
157        writer.writeStartElement(ADV_NS, "Segments");
158        for (Segment segment : segments) {
159            // FIXME: unit translation (long -> time)
160            writer.writeEmptyElement(ADV_NS, "Segment");
161            writer.writeAttribute("id", segment.id);
162            writer.writeAttribute("start", Long.toString(segment.start));
163            writer.writeAttribute("end", Long.toString(segment.end));
164            if (segment.ref != null) {
165                writer.writeAttribute("ref", segment.ref.toString());
166            }
167        }
168        writer.writeEndElement(); // "Segments" element
169
170        // layers
171        writer.writeStartElement(ADV_NS, "Layers");
172        for (Map.Entry<URI, List<Span>> layer : layers.entrySet()) {
173            writer.writeStartElement(ADV_NS, "Layer");
174            writer.writeAttribute("id", layer.getKey().toString());
175            for (Span span : layer.getValue()) {
176                if ((span.value != null) && !span.value.isEmpty()) {
177                    writer.writeStartElement(ADV_NS, "Span");
178                    writer.writeAttribute("ref", span.segment.id);
179                    if (span.highlight != null) {
180                        writer.writeAttribute("highlight", span.highlight);
181                    }
182                    if (span.altValue != null) {
183                        writer.writeAttribute("alt-value", span.altValue);
184                    }
185                    writer.writeCharacters(span.value);
186                    writer.writeEndElement(); // "Span" element
187                } else {
188                    writer.writeEmptyElement(ADV_NS, "Span");
189                    writer.writeAttribute("ref", span.segment.id);
190                    if (span.highlight != null) {
191                        writer.writeAttribute("highlight", span.highlight);
192                    }
193                    if (span.altValue != null) {
194                        writer.writeAttribute("alt-value", span.altValue);
195                    }
196                }
197            }
198            writer.writeEndElement(); // "Layer" element
199        }
200        writer.writeEndElement(); // "Layers" element
201
202        writer.writeEndElement(); // "Advanced" element
203        XMLStreamWriterHelper.writeEndDataView(writer);
204    }
205
206} // class AdvancedDataViewHelper
Note: See TracBrowser for help on using the repository browser.