Commit | Line | Data |
---|---|---|
2e1183f8 JCK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 Ecole Polytechnique de Montreal, Ericsson | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | ******************************************************************************/ | |
9 | package org.eclipse.tracecompass.tmf.analysis.xml.core.segment; | |
10 | ||
11 | import java.io.IOException; | |
12 | import java.io.ObjectInputStream; | |
13 | import java.io.ObjectOutputStream; | |
14 | import java.util.Collections; | |
2e1183f8 JCK |
15 | import java.util.HashMap; |
16 | import java.util.Map; | |
17 | ||
18 | import org.eclipse.jdt.annotation.NonNull; | |
2e1183f8 | 19 | import org.eclipse.tracecompass.segmentstore.core.ISegment; |
2e1183f8 JCK |
20 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; |
21 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
22 | import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; | |
23 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; | |
24 | ||
2e1183f8 JCK |
25 | /** |
26 | * This class implements an XML Pattern Segment. This type of segment has | |
27 | * content and a default timestamp, which is the start time of the segment. | |
28 | * | |
29 | * @author Jean-Christian Kouame | |
30 | * @since 2.0 | |
31 | * | |
32 | */ | |
33 | public class TmfXmlPatternSegment implements ISegment { | |
34 | ||
35 | /** | |
36 | * The serial version UID | |
37 | */ | |
38 | private static final long serialVersionUID = 3556323761465412078L; | |
39 | ||
40 | /* 'Byte' equivalent for state values types */ | |
41 | private static final byte TYPE_NULL = -1; | |
42 | private static final byte TYPE_INTEGER = 0; | |
43 | private static final byte TYPE_STRING = 1; | |
44 | private static final byte TYPE_LONG = 2; | |
45 | ||
2e1183f8 JCK |
46 | private final int fScale; |
47 | private final long fStart; | |
48 | private final long fEnd; | |
49 | private final String fSegmentName; | |
50 | private transient Map<@NonNull String, @NonNull ITmfStateValue> fContent; | |
51 | ||
52 | /** | |
53 | * Constructs an XML pattern segment | |
54 | * | |
55 | * @param start | |
56 | * Start time of the pattern segment | |
57 | * @param end | |
58 | * End time of the pattern segment | |
59 | * @param scale | |
60 | * Scale of the pattern segment | |
61 | * @param segmentName | |
62 | * Name of the pattern segment | |
63 | * @param fields | |
64 | * Fields of the pattern segment | |
65 | */ | |
66 | public TmfXmlPatternSegment(long start, long end, int scale, String segmentName, @NonNull Map<@NonNull String, @NonNull ITmfStateValue> fields) { | |
67 | fStart = start; | |
68 | fEnd = end; | |
69 | fScale = scale; | |
70 | fSegmentName = segmentName; | |
71 | fContent = Collections.unmodifiableMap(fields); | |
72 | } | |
73 | ||
74 | /** | |
75 | * Get the start timestamp of the segment | |
76 | * | |
77 | * @return The start timestamp | |
78 | */ | |
79 | public @NonNull ITmfTimestamp getTimestampStart() { | |
b2c971ec | 80 | return TmfTimestamp.create(fStart, fScale); |
2e1183f8 JCK |
81 | } |
82 | ||
83 | /** | |
84 | * Get the end timestamp of this segment | |
85 | * | |
86 | * @return The end timestamp | |
87 | */ | |
88 | public @NonNull ITmfTimestamp getTimestampEnd() { | |
b2c971ec | 89 | return TmfTimestamp.create(fEnd, fScale); |
2e1183f8 JCK |
90 | } |
91 | ||
92 | /** | |
93 | * Get the content of the pattern segment | |
94 | * @return The content | |
95 | */ | |
96 | public Map<@NonNull String, @NonNull ITmfStateValue> getContent() { | |
97 | return fContent; | |
98 | } | |
99 | ||
100 | /** | |
101 | * Get the name of pattern segment | |
102 | * @return The name | |
103 | */ | |
104 | public String getName() { | |
105 | return fSegmentName; | |
106 | } | |
107 | ||
108 | /** | |
109 | * Get the timestamp scale of the pattern segment | |
110 | * @return The timestamp scale | |
111 | */ | |
112 | public int getScale() { | |
113 | return fScale; | |
114 | } | |
115 | ||
116 | @Override | |
f1c52947 JCK |
117 | public int compareTo(@NonNull ISegment o) { |
118 | int ret = ISegment.super.compareTo(o); | |
119 | if (ret != 0) { | |
120 | return ret; | |
2e1183f8 | 121 | } |
f1c52947 | 122 | return toString().compareTo(o.toString()); |
2e1183f8 JCK |
123 | } |
124 | ||
125 | @Override | |
126 | public long getStart() { | |
127 | return fStart; | |
128 | } | |
129 | ||
130 | @Override | |
131 | public long getEnd() { | |
132 | return fEnd; | |
133 | } | |
134 | ||
135 | @Override | |
136 | public String toString() { | |
137 | return new StringBuilder(getClass().getSimpleName()) | |
138 | .append(", [fTimestampStart=").append(getTimestampStart()) //$NON-NLS-1$ | |
139 | .append(", fTimestampEnd=").append(getTimestampEnd()) //$NON-NLS-1$ | |
140 | .append(", duration= ").append(getLength()) //$NON-NLS-1$ | |
141 | .append(", fName=").append(getName()) //$NON-NLS-1$ | |
142 | .append(", fContent=").append(getContent()) //$NON-NLS-1$ | |
143 | .append("]").toString(); //$NON-NLS-1$ | |
144 | } | |
145 | ||
146 | private void writeObject(ObjectOutputStream out) throws IOException { | |
147 | out.defaultWriteObject(); | |
148 | ||
149 | // Write the number of fields | |
150 | out.writeInt(fContent.size()); | |
151 | ||
152 | // Write the fields | |
153 | for (Map.Entry<String, ITmfStateValue> entry : fContent.entrySet()) { | |
154 | out.writeInt(entry.getKey().length()); | |
155 | out.writeBytes(entry.getKey()); | |
156 | final ITmfStateValue value = entry.getValue(); | |
157 | final byte type = getByteFromType(value.getType()); | |
158 | out.writeByte(type); | |
159 | switch (type) { | |
160 | case TYPE_NULL: | |
161 | break; | |
162 | case TYPE_INTEGER: | |
163 | out.writeInt(value.unboxInt()); | |
164 | break; | |
165 | case TYPE_LONG: | |
166 | out.writeLong(value.unboxLong()); | |
167 | break; | |
168 | case TYPE_STRING: | |
169 | final @NonNull String string = value.unboxStr(); | |
170 | out.writeInt(string.length()); | |
171 | out.writeBytes(string); | |
172 | break; | |
173 | default: | |
174 | throw new IOException("Write object failed : Invalid data"); //$NON-NLS-1$ | |
175 | } | |
176 | } | |
177 | } | |
178 | ||
179 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { | |
180 | in.defaultReadObject(); | |
181 | int contentSize = in.readInt(); | |
182 | ||
183 | final Map<@NonNull String, @NonNull ITmfStateValue> content = new HashMap<>(); | |
184 | for (int i = 0; i < contentSize; i++) { | |
185 | int length = in.readInt(); | |
186 | byte[] bytes = new byte[length]; | |
187 | in.read(bytes, 0, length); | |
266dc922 | 188 | String name = new String(bytes).intern(); |
2e1183f8 JCK |
189 | |
190 | Byte type = in.readByte(); | |
191 | ITmfStateValue value; | |
192 | switch (type) { | |
193 | case TYPE_NULL: | |
194 | value = TmfStateValue.nullValue(); | |
195 | break; | |
196 | case TYPE_INTEGER: | |
197 | value = TmfStateValue.newValueInt(in.readInt()); | |
198 | break; | |
199 | case TYPE_LONG: | |
200 | value = TmfStateValue.newValueLong(in.readLong()); | |
201 | break; | |
202 | case TYPE_STRING: | |
203 | length = in.readInt(); | |
204 | bytes = new byte[length]; | |
205 | in.read(bytes, 0, length); | |
266dc922 | 206 | value = TmfStateValue.newValueString(new String(bytes).intern()); |
2e1183f8 JCK |
207 | break; |
208 | default: | |
209 | throw new IOException("Read object failed : Invalid data"); //$NON-NLS-1$ | |
210 | } | |
211 | content.put(name, value); | |
212 | } | |
213 | fContent = content; | |
214 | } | |
215 | ||
216 | /** | |
217 | * Here we determine how state values "types" are written in the 8-bit field | |
218 | * that indicates the value type in the file. | |
219 | */ | |
220 | private static byte getByteFromType(ITmfStateValue.Type type) { | |
221 | switch (type) { | |
222 | case NULL: | |
223 | return TYPE_NULL; | |
224 | case INTEGER: | |
225 | return TYPE_INTEGER; | |
226 | case STRING: | |
227 | return TYPE_STRING; | |
228 | case LONG: | |
229 | return TYPE_LONG; | |
230 | case DOUBLE: | |
231 | default: | |
232 | /* Should not happen if the switch is fully covered */ | |
233 | throw new IllegalStateException("Data type " + type + " not supported"); //$NON-NLS-1$ //$NON-NLS-2$ | |
234 | } | |
235 | } | |
236 | } |