Skip to content

Commit 6673965

Browse files
author
Open Lowcode SAS
committed
First committed version of the Messaging package of Open Lowcode tools.
1 parent 3e838cd commit 6673965

32 files changed

+3315
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/********************************************************************************
2+
* Copyright (c) 2019 [Open Lowcode SAS](https://openlowcode.com/)
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0 .
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
********************************************************************************/
10+
package org.openlowcode.tools.messages;
11+
12+
/**
13+
* @author Open Lowcode SAS
14+
* @param <E> the object to store in the circular buffer
15+
*/
16+
public class CircularBuffer<E extends Object> {
17+
private int buffersize;
18+
private E[] buffer;
19+
private int nextindex;
20+
private boolean bufferfull;
21+
22+
public void reset() {
23+
this.bufferfull = false;
24+
nextindex = 0;
25+
}
26+
27+
/**
28+
* Creates a circular buffer able to hold at maximum a set number of elements of
29+
* a given class.
30+
*
31+
* @param buffersize the number of elements to store
32+
*/
33+
@SuppressWarnings("unchecked")
34+
public CircularBuffer(int buffersize) {
35+
this.buffersize = buffersize;
36+
buffer = (E[]) new Object[buffersize];
37+
bufferfull = false;
38+
nextindex = 0;
39+
}
40+
41+
/**
42+
* Adds an element. If the buffer is full, will add the element given by
43+
* removing the older one.
44+
*
45+
* @param element the element to add
46+
*/
47+
public void addElement(E element) {
48+
buffer[nextindex] = element;
49+
nextindex++;
50+
if (nextindex == buffersize) {
51+
nextindex = 0;
52+
bufferfull = true;
53+
}
54+
}
55+
56+
/**
57+
* This is a specific method used to display the content of the buffer,
58+
* highlighting the last element, and replacing all carriage returns by space so
59+
* that it displays in a compact manner in the log.
60+
*
61+
* @return a String with the representation of the objects
62+
*/
63+
public String getCompactBufferTrace() {
64+
E[] answer = getBufferContent();
65+
StringBuffer compactanswer = new StringBuffer();
66+
for (int i = 0; i < answer.length; i++) {
67+
if (i == answer.length - 1)
68+
compactanswer.append(" ->");
69+
String element = answer[i].toString().replace('\n', ' ');
70+
compactanswer.append(element);
71+
if (i == answer.length - 1)
72+
compactanswer.append("<- ");
73+
}
74+
return compactanswer.toString();
75+
}
76+
77+
/**
78+
* This method drops the content of the circular buffer,
79+
* as an array of objects by order of creation
80+
* @return the content of the circular buffer, as an array of objects
81+
* of type E
82+
*/
83+
public E[] getBufferContent() {
84+
if (!bufferfull) {
85+
// simple case: just send the first elements of the array
86+
@SuppressWarnings("unchecked")
87+
E[] answer = (E[]) new Object[nextindex];
88+
System.arraycopy(buffer, 0, answer, 0, nextindex);
89+
return answer;
90+
} else {
91+
// complex case, buffer is full, there will be two portions to copy, before and
92+
// after the index.
93+
@SuppressWarnings("unchecked")
94+
E[] answer = (E[]) new Object[buffersize];
95+
System.arraycopy(buffer, nextindex, answer, 0, buffersize - nextindex);
96+
if (nextindex != 0)
97+
System.arraycopy(buffer, 0, answer, buffersize - nextindex, nextindex);
98+
return answer;
99+
}
100+
}
101+
102+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/********************************************************************************
2+
* Copyright (c) 2019 [Open Lowcode SAS](https://openlowcode.com/)
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0 .
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
********************************************************************************/
10+
package org.openlowcode.tools.messages;
11+
12+
/**
13+
* This message is used at the end of a compact array. Its graphical
14+
* representation is two closing brackets ')'
15+
*
16+
* @author Open Lowcode SAP
17+
*
18+
*/
19+
public class MessageArrayEnd extends MessageElement {
20+
private String name;
21+
22+
/**
23+
* @return the name of the compact array
24+
*/
25+
public String getName() {
26+
return name;
27+
}
28+
29+
/**
30+
* @param name sets or change the name of the compact array.
31+
*/
32+
public void setName(String name) {
33+
this.name = name;
34+
}
35+
36+
/**
37+
* creates a new message array end. The MessageWriter will automatically add the
38+
* message array name.
39+
*/
40+
public MessageArrayEnd() {
41+
42+
}
43+
44+
private static final String ARRAY_END_STRUCTURE = ")";
45+
46+
@Override
47+
public String serialize(String padding, boolean firstattribute) {
48+
return " " + ARRAY_END_STRUCTURE + ARRAY_END_STRUCTURE; // one more space due to path implementation
49+
}
50+
51+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/********************************************************************************
2+
* Copyright (c) 2019 [Open Lowcode SAS](https://openlowcode.com/)
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0 .
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
********************************************************************************/
10+
package org.openlowcode.tools.messages;
11+
12+
import java.math.BigDecimal;
13+
import java.util.ArrayList;
14+
import java.util.Arrays;
15+
import java.util.Date;
16+
17+
/**
18+
* A message array line is providing a payload (potentially null) for all the
19+
* columns declared in the MessageArrayStart
20+
*
21+
* @author Open Lowcode SAS
22+
* @see org.openlowcode.tools.messages.MessageArrayStart
23+
*/
24+
public class MessageArrayLine extends MessageElement {
25+
private ArrayList<Object> payload;
26+
private MessageArrayStart messagearraystart;
27+
private static final String LINE_STARTER = "(";
28+
private static final String LINE_ENDER = ")";
29+
private static final String OBJECT_SEPARATOR = ",";
30+
31+
/**
32+
* @param messagearraystart the fully configured MessageArrayStart
33+
* @param payload
34+
* @see org.openlowcode.tools.messages.MessageArrayStart
35+
*/
36+
public MessageArrayLine(MessageArrayStart messagearraystart, Object[] payload) {
37+
this.payload = new ArrayList<Object>(Arrays.asList(payload));
38+
messagearraystart.validateArrayLine(this);
39+
}
40+
41+
protected MessageArrayLine(Object[] payload) {
42+
this.payload = new ArrayList<Object>(Arrays.asList(payload));
43+
}
44+
45+
@Override
46+
public String serialize(String padding, boolean firstattribute) {
47+
StringBuffer string = new StringBuffer();
48+
string.append('\n');
49+
string.append(padding);
50+
string.append(LINE_STARTER);
51+
for (int i = 0; i < payload.size(); i++) {
52+
if (i > 0)
53+
string.append(OBJECT_SEPARATOR);
54+
string.append(printObject(messagearraystart.getFieldSpecAt(i), payload.get(i)));
55+
}
56+
string.append(LINE_ENDER);
57+
return string.toString();
58+
}
59+
60+
private String printObject(MessageFieldSpec fieldspec, Object object) {
61+
if (object == null)
62+
return fieldspec.generateNullContent();
63+
if (object instanceof String)
64+
return MessageStringField.serializeStringPayload((String) object, "");
65+
if (object instanceof Integer)
66+
return MessageIntegerField.serialize(((Integer) (object)).intValue());
67+
if (object instanceof BigDecimal)
68+
return MessageDecimalField.serializeDecimal((BigDecimal) object);
69+
if (object instanceof Boolean)
70+
return MessageBooleanField.serializeBoolean(((Boolean) (object)).booleanValue());
71+
if (object instanceof Date)
72+
return MessageDateField.serializeDate(((Date) (object)));
73+
74+
throw new RuntimeException("Object " + object.getClass() + " not supported in GML Compact Array");
75+
}
76+
77+
/**
78+
* @return the number of objects stored in the array line. It is guaranteed to
79+
* be always the same number of objects that defined in the
80+
* MessageArrayStart, though some elements may be null
81+
*/
82+
public int getObjectNumber() {
83+
return payload.size();
84+
}
85+
86+
/**
87+
* @param index
88+
* @return the object for column indicated by index
89+
*/
90+
public Object getPayloadAt(int index) {
91+
return payload.get(index);
92+
}
93+
94+
protected void setArrayStart(MessageArrayStart messagearraystart) {
95+
this.messagearraystart = messagearraystart;
96+
97+
}
98+
99+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/********************************************************************************
2+
* Copyright (c) 2019 [Open Lowcode SAS](https://openlowcode.com/)
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0 .
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
********************************************************************************/
10+
package org.openlowcode.tools.messages;
11+
12+
import java.util.ArrayList;
13+
import java.util.HashMap;
14+
15+
/**
16+
* This message element defines the format of a compact array. A compact array
17+
* allows sending of lines of data that share the same structure (columns).
18+
* Columns can be of any supported formats (described in subtypes of
19+
* MessageFieldType ):
20+
* <ul>
21+
* <li>Binary</li>
22+
* <li>Boolean</li>
23+
* <li>Date</li>
24+
* <li>Decimal</li>
25+
* <li>Boolean</li>
26+
* <li>Integer</li>
27+
* <li>String</li>
28+
* </ul>
29+
* Please note that binary is not yet supported.
30+
*
31+
* @author Open Lowcode SAS
32+
*
33+
*/
34+
public class MessageArrayStart extends MessageElement {
35+
private String arrayname;
36+
37+
private ArrayList<MessageFieldSpec> fieldlist;
38+
private HashMap<String, Integer> fieldlistperindex;
39+
private static String START_ARRAY = "(";
40+
private static String END_ARRAY = ")";
41+
42+
/**
43+
* @return the number of fields (columns) defined in the compact array format
44+
*/
45+
public int getFieldSpecNr() {
46+
return fieldlist.size();
47+
}
48+
49+
/**
50+
* @param index the index of field (columns), it should be between 0 and
51+
* strictly less than the number of Fields (see getFieldSpecNr)
52+
* @return the field at index. Throws an exception if index is invalid
53+
*/
54+
55+
public MessageFieldSpec getFieldSpecAt(int index) {
56+
return fieldlist.get(index);
57+
}
58+
59+
/**
60+
* @param arrayname name of the array structure
61+
* @param fieldlist the definition of fields
62+
*/
63+
64+
public MessageArrayStart(String arrayname, ArrayList<MessageFieldSpec> fieldlist) {
65+
this.arrayname = arrayname;
66+
this.fieldlist = fieldlist;
67+
if (fieldlist == null)
68+
throw new RuntimeException("field list is null for array " + arrayname);
69+
if (fieldlist.size() == 0)
70+
throw new RuntimeException("field list has zero element");
71+
fieldlistperindex = new HashMap<String, Integer>();
72+
for (int i = 0; i < fieldlist.size(); i++) {
73+
MessageFieldSpec spec = fieldlist.get(i);
74+
if (fieldlistperindex.get(spec.getName()) != null)
75+
throw new RuntimeException("Duplicate field for array with name" + spec.getName());
76+
fieldlistperindex.put(spec.getName(), new Integer(i));
77+
}
78+
}
79+
80+
/**
81+
* @return the name of the array
82+
*/
83+
public String getArrayName() {
84+
return this.arrayname;
85+
}
86+
87+
@Override
88+
public String serialize(String padding, boolean firstattribute) {
89+
StringBuffer arraystartbuffer = new StringBuffer();
90+
arraystartbuffer.append("\n");
91+
arraystartbuffer.append(padding);
92+
arraystartbuffer.append(START_ARRAY);
93+
arraystartbuffer.append(START_ARRAY);
94+
arraystartbuffer.append(arrayname);
95+
arraystartbuffer.append(START_ARRAY);
96+
for (int i = 0; i < fieldlist.size(); i++) {
97+
if (i > 0)
98+
arraystartbuffer.append(',');
99+
MessageFieldSpec thisfieldspec = fieldlist.get(i);
100+
arraystartbuffer.append(thisfieldspec.getName());
101+
arraystartbuffer.append('=');
102+
arraystartbuffer.append('"');
103+
arraystartbuffer.append(thisfieldspec.getType().getMessageFieldAcronym());
104+
arraystartbuffer.append('"');
105+
106+
}
107+
arraystartbuffer.append(END_ARRAY);
108+
return arraystartbuffer.toString();
109+
}
110+
111+
/**
112+
* Will analyze the given arrayline, and check that the number of columns of the
113+
* line is correct, and there is either a valid value or null as payload for
114+
* each column.
115+
*
116+
* @param arrayline the array line to check
117+
*/
118+
public void validateArrayLine(MessageArrayLine arrayline) {
119+
if (fieldlist.size() != arrayline.getObjectNumber())
120+
throw new RuntimeException("Array data line has incorrect " + arrayline.getObjectNumber()
121+
+ " number of elements, while " + this.fieldlist.size() + " are expected.");
122+
for (int i = 0; i < fieldlist.size(); i++) {
123+
fieldlist.get(i).validatePayload(i, arrayline.getPayloadAt(i));
124+
}
125+
arrayline.setArrayStart(this);
126+
}
127+
128+
}

0 commit comments

Comments
 (0)