1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sourceforge.jarduino.message;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.LinkedHashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25
26 import net.sourceforge.jarduino.ArduinoException;
27 import net.sourceforge.jarduino.message.ArduinoAttribute.ArduinoAttrObject;
28 import net.sourceforge.jarduino.message.ArduinoParser.ArduinoParserException;
29
30
31
32
33 public class ArduinoMessage
34 implements ArduinoNamedObject, ArduinoAttrObject {
35
36
37
38 static final String MARKER = "BO_";
39
40
41
42
43 private final String theId;
44
45
46
47
48 private final String theName;
49
50
51
52
53 private final int theLength;
54
55
56
57
58 private final ArduinoNode theSender;
59
60
61
62
63 private final List<ArduinoSignal> theSignals;
64
65
66
67
68 private boolean hasFloat;
69
70
71
72
73 private ArduinoSignal theMultiplexSignal;
74
75
76
77
78 private final Map<Long, List<ArduinoSignal>> theMultiplex;
79
80
81
82
83 private final Map<ArduinoAttribute, Object> theAttributes;
84
85
86
87
88
89
90
91
92 ArduinoMessage(final ArduinoNode pSender,
93 final String pMsgId,
94 final String pName,
95 final int pLength) {
96
97 theSender = pSender;
98 theId = pMsgId;
99 theName = pName;
100 theLength = pLength;
101
102
103 theSignals = new ArrayList<>();
104 theMultiplex = new LinkedHashMap<>();
105 theAttributes = new HashMap<>();
106 }
107
108
109
110
111
112 public void addSignal(final ArduinoSignal pSignal) {
113
114 hasFloat |= pSignal.isFloat() && !pSignal.getRange().unBounded();
115
116
117 final Long myMulti = pSignal.getMultiplexId();
118 if (myMulti.equals(ArduinoSignal.MULTI_NONE)) {
119
120 theSignals.add(pSignal);
121
122
123 if (pSignal.isMultiplex()) {
124 theMultiplexSignal = pSignal;
125 }
126
127
128 } else {
129 final List<ArduinoSignal> myList = theMultiplex.computeIfAbsent(myMulti, m -> new ArrayList<>());
130 myList.add(pSignal);
131 }
132 }
133
134
135
136
137
138 public String getId() {
139 return theId;
140 }
141
142 @Override
143 public String getName() {
144 return theName;
145 }
146
147
148
149
150
151 public int getLength() {
152 return theLength;
153 }
154
155
156
157
158
159 public ArduinoNode getSender() {
160 return theSender;
161 }
162
163
164
165
166
167 public ArduinoSystem getSystem() {
168 return theSender.getOwner();
169 }
170
171
172
173
174
175 public List<ArduinoSignal> getSignals() {
176 return theSignals;
177 }
178
179
180
181
182
183 public List<ArduinoSignal> getAllSignals() {
184
185 final List<ArduinoSignal> myResult = new ArrayList<>(theSignals);
186
187
188 for (List<ArduinoSignal> myList : theMultiplex.values()) {
189
190 myResult.addAll(myList);
191 }
192
193
194 return myResult;
195 }
196
197
198
199
200
201 public boolean hasFloat() {
202 return hasFloat;
203 }
204
205
206
207
208
209 public boolean hasMultiplex() {
210 return !theMultiplex.isEmpty();
211 }
212
213
214
215
216
217 public ArduinoSignal getMultiplexSignal() {
218 return theMultiplexSignal;
219 }
220
221
222
223
224
225 public Map<Long, List<ArduinoSignal>> getMultiplexMap() {
226 return theMultiplex;
227 }
228
229
230
231
232
233
234
235 void setAttrValue(final ArduinoAttribute pAttr,
236 final Object pValue) throws ArduinoParserException {
237
238 if (theAttributes.containsKey(pAttr)) {
239 throw new ArduinoParserException("Duplicate Attribute", pAttr.getName());
240 }
241
242
243 theAttributes.put(pAttr, pValue);
244 }
245
246 @Override
247 public Object getAttrValue(final ArduinoAttribute pAttr) {
248 final Object myValue = theAttributes.get(pAttr);
249 return myValue == null ? pAttr.getDefault() : myValue;
250 }
251
252
253
254
255
256
257
258 ArduinoSignal findSignalByName(final String pName) throws ArduinoParserException {
259
260 for (ArduinoSignal mySignal : theSignals) {
261 if (pName.equals(mySignal.getName())) {
262 return mySignal;
263 }
264 }
265
266
267 for (List<ArduinoSignal> myList : theMultiplex.values()) {
268
269 for (ArduinoSignal mySignal : myList) {
270 if (pName.equals(mySignal.getName())) {
271 return mySignal;
272 }
273 }
274 }
275
276
277 throw new ArduinoParserException("Unknown signal", pName);
278 }
279
280
281
282
283
284
285
286
287 static ArduinoMessage parseMessage(final ArduinoSystem pSystem,
288 final String pMessageDef) throws ArduinoException {
289
290 final int myIndex = pMessageDef.indexOf(ArduinoChar.COLON);
291 if (myIndex == -1) {
292 throw new ArduinoException("Missing " + ArduinoChar.COLON + " separator", pMessageDef);
293 }
294 String myHdr = pMessageDef.substring(0, myIndex);
295 final String myLine = pMessageDef.substring(myIndex + 1).trim();
296
297
298 final String myMarker = ArduinoParser.nextToken(myHdr);
299 myHdr = ArduinoParser.stripToken(myHdr, myMarker);
300 if (!myMarker.equals(MARKER)) {
301 throw new ArduinoException("Invalid marker", pMessageDef);
302 }
303
304
305 final String myId = ArduinoParser.nextToken(myHdr);
306 myHdr = ArduinoParser.stripToken(myHdr, myId);
307
308
309 final String myName = ArduinoParser.nextToken(myHdr);
310
311
312 try {
313
314 final String myLen = ArduinoParser.nextToken(myLine);
315 final String mySenderNode = ArduinoParser.stripToken(myLine, myLen);
316 final int myLength = ArduinoParser.parseNumber(myLen).intValue();
317 final ArduinoNode mySender = pSystem.findNodeByName(mySenderNode);
318
319
320 final ArduinoMessageoMessage.html#ArduinoMessage">ArduinoMessage myMessage = new ArduinoMessage(mySender, myId, myName, myLength);
321 mySender.addMessage(myMessage);
322
323
324 return myMessage;
325
326
327 } catch (ArduinoParserException e) {
328 throw new ArduinoException(e.getMessage() + ArduinoChar.COLON + e.getDetail(), pMessageDef);
329 }
330 }
331
332 @Override
333 public boolean equals(final Object pThat) {
334
335 if (pThat == this) {
336 return true;
337 } else if (!(pThat instanceof ArduinoMessage)) {
338 return false;
339 }
340
341
342 final ArduinoMessage/../net/sourceforge/jarduino/message/ArduinoMessage.html#ArduinoMessage">ArduinoMessage myThat = (ArduinoMessage) pThat;
343
344
345 return theId.equals(myThat.getId())
346 && theName.equals(myThat.getName())
347 && theSender.equals(myThat.getSender());
348 }
349
350 @Override
351 public int hashCode() {
352 return Objects.hash(theId, theName, theSender);
353 }
354
355 @Override
356 public String toString() {
357
358 final StringBuilder myBuilder = new StringBuilder();
359 myBuilder.append(MARKER);
360 myBuilder.append(ArduinoChar.BLANK);
361 myBuilder.append(theId);
362 myBuilder.append(ArduinoChar.BLANK);
363 myBuilder.append(theName);
364 myBuilder.append(ArduinoChar.COLON);
365 myBuilder.append(ArduinoChar.BLANK);
366 myBuilder.append(theLength);
367 myBuilder.append(ArduinoChar.BLANK);
368 myBuilder.append(theSender);
369 myBuilder.append(ArduinoChar.LF);
370
371
372 for (ArduinoSignal theSignal : theSignals) {
373 myBuilder.append(ArduinoChar.BLANK);
374 myBuilder.append(theSignal);
375 myBuilder.append(ArduinoChar.LF);
376 }
377
378
379 for (List<ArduinoSignal> myList : theMultiplex.values()) {
380
381 for (ArduinoSignal arduinoSignal : myList) {
382 myBuilder.append(ArduinoChar.BLANK);
383 myBuilder.append(arduinoSignal);
384 myBuilder.append(ArduinoChar.LF);
385 }
386 }
387
388
389 return myBuilder.toString();
390 }
391 }