Introduction
This article is written about efficient management for queueing and parsing packets. The first one is about the format of a string
based packet, the second is about queueing buffer, and the last thing that will be dealt in this article is about parsing the message.
Background
We need the protocol to communicate with each equipment in the automation system. In many cases, these protocols consist of a string
or structure based packet. Structure based packet is more easy to parse its contents than string based packet and that can consist of a packet with smaller size than a string packet, but as a string based packet has more compatibility among heterogeneous system, a string based packet is often used in communication system. So this article introduces string message packet manager having the function of parsing and queueing.
Message Format
I define the record as unit of packet and the record has a number of fields.
<RECORD_ID FIELD0=VALUE0 FIELD1=VALUE1 ... FIELDn=VALUEn/>
For example, we can paraphrase a structure based packet into a string based packet as below:
Structure based packet | String based packet |
struct EQP_Cleaner {
char ID[5];
RGB color;
int part_number;
int duration;
}
|
<EQP_CLEANER ID=EQP01 color=RED part_nubmer=80
duration=100/>
|
Using the Code
I think you can accomplish your purpose only by using the simple code and define the message format and use clear(..)
, setQsize(..)
for queue setting and handle data for pushMessage(..)
, popMessage(..)
.
Definition
A message packet describes the record that consists of record name and Field
set. The structure of record and field is shown as follows:
public class Field {
public String name;
public String value;
}
public class Record {
public String name;
ArrayList<Field> Fields= new ArrayList<Field>();
public int size() {
return Fields.size();
}
}
Function Description
void setQsize(int size)
Sets the maximum size to store message packets in buffer
int size()
Gets the number of current message packet stored in buffer
void clear()
Flushes buffer
void addField(Record t, Field f)
Adds a field to record
void addRecord(Record t)
Adds a record to buffer
Record getRecord(int index)
Gets a nth record in buffer (n: index)
Record getRecord(String name)
Gets a record by the name
keyword
Field getField(Record t, int index)
Gets a nth field in the specified record t
Field getField(Record t, String name)
Gets a field
by the name
keyword in the specified record t
Record deleteMessage(int index)
Deletes a nth record
Record deleteMessage(String name)
Deletes a record by the name
keyword
Record popMessage()
Gets and deletes the oldest record in buffer
void pushMessage(String strLine)
Inserts record in buffer, record here will be filled by parsing string
message. If current buffer size is bigger than maximum storage size, the oldest record will be deleted.
Implementation
pushMessage(..)
simultaneously fulfills function parsing and pushing a string
message in the buffer storage.
public void pushMessage(String strLine){
int bracket_start=0;
if(strLine.isEmpty() == false) {
if(size() >= mQsize) {
Record t = tags.get(0);
t.Fields.clear();
tags.remove(0);
}
String bracketName=null;
String bracketValue=null;
do {
int start = 0;
int end = 0;
start = strLine.indexOf("<", bracket_start);
if(start<0) break;
end = strLine.indexOf("/>", start);
if(end<0) break;
String tmp = strLine.substring(start+1, end);
bracket_start = end;
start = 0;
end = tmp.indexOf(" ", start);
if(end<0) continue;
bracketName = tmp.substring(start, end);
bracketValue = tmp.substring(end+1, bracket_start-1);
}while(bracket_start>=0);
if(bracketValue!=null)
{
String org = bracketValue;
Record t = new Record();
t.name = bracketName;
int index=0;
while(index < org.length()) {
Field f= new Field();
index = getField(org, index, f);
addField(t,f);
}
addRecord(t);
}
}
}
Usage
First, you have to create the object of MessageManager
:
MessageManager msgManager = new MessageManager();
and fill the buffer by pushMessage(..)
;
msgManager.pushMessage(strMsg);
According to the requirement, you can call popMessage(..)
.
record = msgManager.popMessage();
If you called popMessage
, finally you can get the field you want using the return record.
field = msgManager.getField(record,index);
When you would like to initialize the buffer, you can call clear()
;
msgManager.clear();
public static void main(String[] args) {
int buffsize = 6;
MessageManager.Record record=null;
MessageManager.Field field=null;
String strMsg1 = "<MsgId1 field0=192.168.0.1 field1=1001
field2=1002 field3=1003 field4=1004/>";
String strMsg2 = "<MsgId2 field0=192.168.0.2 field1=2001
field2=2002 field3=2003 field4=2004/>";
String strMsg3 = "<MsgId3 field0=192.168.0.3 field1=3001
field2=3002 field3=3003 field4=3004/>";
String strMsg4 = "<MsgId4 field0=192.168.0.4 field1=4001
field2=4002 field3=4003 field4=4004/>";
String strMsg5 = "<MsgId5 field0=192.168.0.5 field1=5001
field2=5002 field3=5003 field4=5004/>";
String strMsg6 = "<MsgId6 field0=192.168.0.6 field1=6001
field2=6002 field3=6003 field4=6004/>";
String strMsg7 = "<MsgId7 field0=192.168.0.7 field1=7001
field2=7002 field3=7003 field4=7004/>";
MessageManager msgManager = new MessageManager();
msgManager.clear();
System.out.println
("Add the buffer by strMsg1,strMsg2,...,strMsg5, buffer size:"+buffsize);
msgManager.setQsize(buffsize);
msgManager.pushMessage(strMsg1);
msgManager.pushMessage(strMsg2);
msgManager.pushMessage(strMsg3);
msgManager.pushMessage(strMsg4);
msgManager.pushMessage(strMsg5);
msgManager.pushMessage(strMsg6);
msgManager.pushMessage(strMsg7);
System.out.print("Print buffer--------------------------------------");
for(int i=0;i < msgManager.size();i++) {
record = msgManager.getRecord(i);
System.out.print("\n"+record.name+":");
for(int j=0;j < record.size();j++) {
field = msgManager.getField(record,j);
if(field!=null)
System.out.print(" ("+field.name+")"+field.value);
}
}
System.out.print("\nPop message-------------------------------------");
record = msgManager.popMessage();
System.out.print("\n"+record.name+":");
for(int k=0;k < record.size();k++) {
field = msgManager.getField(record,k);
if(field!=null)
System.out.print(" ("+field.name+")"+field.value);
}
System.out.print("\nbuffer after pop-------------------------------");
for(int i=0;i < msgManager.size();i++) {
record = msgManager.getRecord(i);
System.out.print("\n"+record.name+":");
for(int j=0;j < record.size();j++)
{
field = msgManager.getField(record,j);
if(field!=null)
System.out.print(" ("+field.name+")"+field.value);
}
}
System.out.print("\nFind MsgId5 and it's field3---------------------");
record = msgManager.getRecord("MsgId5");
if(record!=null) {
System.out.print("\n"+record.name+":");
field = msgManager.getField(record,"field3");
}else{
System.out.println("\ncannot find record..");
field = null;
}
if(field!=null)
System.out.print(" ("+field.name+")"+field.value);
else
System.out.println("\ncannot find field..");
msgManager.deleteMessage("MsgId6");
System.out.print("\nbuffer after Delete MsgId6 Message-------------");
for(int i=0;i < msgManager.size();i++) {
record = msgManager.getRecord(i);
System.out.print("\n"+record.name+":");
for(int j=0;j < record.size();j++) {
field = msgManager.getField(record,j);
if(field!=null)
System.out.print(" ("+field.name+")"+field.value);
}
}
}
[Result]
You can check the result as below:
I hope you try to compile and run as per the following instruction:
Points of Interest
I would like you to take note of parsing and queueing as soon as message is added.
History
- 12th September, 2016: Initial version