gurux.dlms.objects.GXXmlWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gurux.dlms Show documentation
Show all versions of gurux.dlms Show documentation
gurux.dlms.java package is used to communicate with DLMS devices.
The newest version!
//
// --------------------------------------------------------------------------
// Gurux Ltd
//
//
//
// Filename: $HeadURL$
//
// Version: $Revision$,
// $Date$
// $Author$
//
// Copyright (c) Gurux Ltd
//
//---------------------------------------------------------------------------
//
// DESCRIPTION
//
// This file is a part of Gurux Device Framework.
//
// Gurux Device Framework is Open Source software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2 of the License.
// Gurux Device Framework is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// More information of Gurux products: https://www.gurux.org
//
// This code is licensed under the GNU General Public License v2.
// Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
//---------------------------------------------------------------------------
package gurux.dlms.objects;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import gurux.dlms.GXArray;
import gurux.dlms.GXDLMSConverter;
import gurux.dlms.GXDateOS;
import gurux.dlms.GXDateTime;
import gurux.dlms.GXDateTimeOS;
import gurux.dlms.GXSimpleEntry;
import gurux.dlms.GXStructure;
import gurux.dlms.GXTimeOS;
import gurux.dlms.enums.DataType;
import gurux.dlms.enums.ObjectType;
import gurux.dlms.internal.GXCommon;
/**
* Save COSEM object to the file.
*/
public class GXXmlWriter implements AutoCloseable {
private XMLStreamWriter writer = null;
private String newline = System.getProperty("line.separator");
private int indenting = 0;
char[] spaces = null;
private GXXmlWriterSettings settings;
public boolean isSkipDefaults() {
if (settings == null) {
return false;
}
return settings.isIgnoreDefaultValues();
}
/**
* @return GXDateTime values are serialised using meter time, not local
* time.
*/
public boolean isUseMeterTime() {
if (settings == null) {
return false;
}
return settings.isUseMeterTime();
}
/**
* Close writer.
*/
public final void close() throws XMLStreamException {
if (writer != null) {
writer.close();
writer = null;
}
}
/**
* Constructor.
*
* @param filename
* File name.
* @param wSettings
* Writer settings.
* @throws XMLStreamException
* Invalid XML stream.
* @throws FileNotFoundException
* File not found.
*/
public GXXmlWriter(final String filename, final GXXmlWriterSettings wSettings)
throws FileNotFoundException, XMLStreamException {
settings = wSettings;
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
writer = outputFactory.createXMLStreamWriter(new FileOutputStream(filename));
}
/**
* Constructor.
*
* @param s
* Stream.
* @param wSettings
* Writer settings.
* @throws XMLStreamException
* Invalid XML stream.
*/
public GXXmlWriter(final OutputStream s, final GXXmlWriterSettings wSettings)
throws XMLStreamException {
settings = wSettings;
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
writer = outputFactory.createXMLStreamWriter(s);
}
/**
* Append spaces to the buffer.
*
* @param count
* Amount of spaces.
* @throws XMLStreamException
*/
private void appendSpaces() throws XMLStreamException {
if (indenting > spaces.length / 2) {
writer.writeCharacters(spaces, 0, spaces.length);
} else {
writer.writeCharacters(spaces, 0, 2 * indenting);
}
}
public final void writeStartDocument() throws XMLStreamException {
if (spaces == null) {
spaces = new char[100];
for (int pos = 0; pos != spaces.length; ++pos) {
spaces[pos] = ' ';
}
}
writer.writeStartDocument();
writer.writeCharacters(newline);
indenting = 0;
}
public final void writeStartElement(final String name) throws XMLStreamException {
appendSpaces();
writer.writeStartElement(name);
writer.writeCharacters(newline);
++indenting;
}
public final void writeStartElement(final String elementName, final String attributeName,
final String value, final boolean newLine) throws XMLStreamException {
appendSpaces();
writer.writeStartElement(elementName);
writer.writeAttribute(attributeName, value);
if (newLine) {
writer.writeCharacters(newline);
}
++indenting;
}
public final void writeStartElement(final String elementName,
final List> attributes, final boolean newLine)
throws XMLStreamException {
appendSpaces();
writer.writeStartElement(elementName);
for (Map.Entry it : attributes) {
writer.writeAttribute(it.getKey(), it.getValue());
}
if (newLine) {
writer.writeCharacters(newline);
}
++indenting;
}
public final void writeElementString(final String name, final Date value)
throws XMLStreamException {
if (value != null && value.compareTo(new Date(0)) != 0) {
SimpleDateFormat sd = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.US);
writeElementString(name, sd.format(value));
}
}
public final void writeElementString(final String name, final long value)
throws XMLStreamException {
if (!isSkipDefaults() || value != 0) {
writeElementString(name, String.valueOf(value));
}
}
public final void writeElementString(final String name, final double value)
throws XMLStreamException {
writeElementString(name, value, 0);
}
public final void writeElementString(final String name, final double value,
final double defaultValue) throws XMLStreamException {
if (!isSkipDefaults() || value != defaultValue) {
writeElementString(name, String.format(Locale.US, "%f", value));
}
}
public final void writeElementString(final String name, final int value)
throws XMLStreamException {
if (!isSkipDefaults() || value != 0) {
writeElementString(name, String.valueOf(value));
}
}
public final void writeElementString(final String name, final String value)
throws XMLStreamException {
if (!isSkipDefaults() || (value != null && value.length() != 0)) {
appendSpaces();
writer.writeStartElement(name);
if (value != null) {
writer.writeCharacters(value.replaceAll("[\\x00]", ""));
}
writer.writeEndElement();
writer.writeCharacters(newline);
}
}
public final void writeElementString(final String name, final boolean value)
throws XMLStreamException {
if (!isSkipDefaults() || value) {
writeElementString(name, value ? "1" : "0");
}
}
public final void writeElementString(final String name, final GXDateTime value)
throws XMLStreamException {
if (value != null && value.getMeterCalendar().getTime() != new java.util.Date(0)) {
if (isUseMeterTime()) {
writeElementString(name, value.toFormatMeterString(Locale.ROOT));
} else {
writeElementString(name, value.toFormatString(Locale.ROOT));
}
}
}
private void writeArray(final Object data) throws XMLStreamException {
if (data instanceof List>) {
writer.writeCharacters(System.getProperty("line.separator"));
List> arr = (List>) data;
for (Object tmp : arr) {
if (tmp instanceof byte[]) {
writeElementObject("Item", tmp, false);
} else if (tmp instanceof GXArray) {
writeStartElement("Item", "Type", String.valueOf(DataType.ARRAY.getValue()),
true);
writeArray(tmp);
writeEndElement();
} else if (tmp instanceof GXStructure) {
writeStartElement("Item", "Type", String.valueOf(DataType.STRUCTURE.getValue()),
true);
writeArray(tmp);
writeEndElement();
} else {
writeElementObject("Item", tmp);
}
}
}
}
public final void writeElementObject(final String name, final Object value)
throws XMLStreamException {
writeElementObject(name, value, isSkipDefaults());
}
/**
* Write object value to file.
*
* @param name
* Object name.
* @param value
* Object value.
* @param dt
* Data type of serialized value.
* @param uiType
* UI data type of serialized value.
* @throws XMLStreamException
* Invalid XML stream.
*/
public final void writeElementObject(final String name, final Object value, final DataType dt,
final DataType uiType) throws XMLStreamException {
if (value != null) {
if (isSkipDefaults() && value instanceof java.util.Date
&& (((java.util.Date) value).compareTo(new java.util.Date(0))) == 0) {
return;
}
boolean addSpaces = false;
if (value instanceof GXDateTimeOS) {
List> list = new ArrayList>();
list.add(new GXSimpleEntry("Type",
String.valueOf(DataType.OCTET_STRING.getValue())));
if (value instanceof GXTimeOS) {
list.add(new GXSimpleEntry("UIType",
String.valueOf(DataType.TIME.getValue())));
} else if (value instanceof GXDateOS) {
list.add(new GXSimpleEntry("UIType",
String.valueOf(DataType.DATE.getValue())));
} else {
list.add(new GXSimpleEntry("UIType",
String.valueOf(DataType.DATETIME.getValue())));
}
writeStartElement(name, list, false);
} else if (uiType != DataType.NONE && uiType != dt
&& (uiType != DataType.STRING || dt == DataType.OCTET_STRING)) {
List> list = new ArrayList>();
list.add(new GXSimpleEntry("Type", String.valueOf(dt.getValue())));
list.add(new GXSimpleEntry("UIType",
String.valueOf(uiType.getValue())));
writeStartElement(name, list, false);
} else if (value instanceof Double || value instanceof Float) {
List> list = new ArrayList>();
list.add(new GXSimpleEntry("Type", String.valueOf(dt.getValue())));
if (value instanceof Double) {
list.add(new GXSimpleEntry("UIType",
String.valueOf(DataType.FLOAT64.getValue())));
} else {
list.add(new GXSimpleEntry("UIType",
String.valueOf(DataType.FLOAT32.getValue())));
}
writeStartElement(name, list, false);
} else {
if (dt == DataType.NONE) {
addSpaces = true;
writeStartElement(name);
} else {
writeStartElement(name, "Type", String.valueOf(dt.getValue()), false);
}
}
if (dt == DataType.ARRAY || dt == DataType.STRUCTURE) {
writeArray(value);
} else {
if (value instanceof GXDateTime) {
String str;
if (isUseMeterTime()) {
str = ((GXDateTime) value).toFormatMeterString(Locale.ROOT);
} else {
str = ((GXDateTime) value).toFormatString(Locale.ROOT);
}
writer.writeCharacters(str);
} else if (value instanceof Date) {
String str;
SimpleDateFormat sd = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss XXX");
str = sd.format(value);
writer.writeCharacters(str);
} else if (value instanceof byte[]) {
writer.writeCharacters(GXCommon.toHex((byte[]) value));
} else if (value != null) {
writer.writeCharacters(String.valueOf(value));
}
}
writeEndElement(addSpaces);
} else if (!isSkipDefaults()) {
if (dt != DataType.NONE || uiType != DataType.NONE) {
List> list = new ArrayList>();
list.add(new GXSimpleEntry("Type", String.valueOf(dt.getValue())));
list.add(new GXSimpleEntry("UIType",
String.valueOf(uiType.getValue())));
writeStartElement(name, list, false);
writeEndElement(false);
} else {
writeStartElement(name);
writeEndElement(false);
}
}
}
/**
* Write object value to file.
*
* @param name
* Object name.
* @param value
* Object value.
* @param skipDefaultValue
* Is default value serialized.
* @throws XMLStreamException
* Invalid XML stream.
*/
public final void writeElementObject(final String name, final Object value,
final boolean skipDefaultValue) throws XMLStreamException {
if (value != null || !skipDefaultValue) {
if (skipDefaultValue && value instanceof java.util.Date
&& (((java.util.Date) value).compareTo(new java.util.Date(0))) == 0) {
return;
}
if (value instanceof GXDateTimeOS) {
writeElementObject(name, value, DataType.OCTET_STRING, DataType.DATETIME);
} else if (value instanceof GXDateOS) {
writeElementObject(name, value, DataType.OCTET_STRING, DataType.DATE);
} else if (value instanceof GXTimeOS) {
writeElementObject(name, value, DataType.OCTET_STRING, DataType.TIME);
} else {
DataType dt = GXDLMSConverter.getDLMSDataType(value);
writeElementObject(name, value, dt, DataType.NONE);
}
}
}
private void writeEndElement(final boolean addSpaces) throws XMLStreamException {
--indenting;
if (addSpaces) {
appendSpaces();
}
writer.writeEndElement();
writer.writeCharacters(newline);
}
/**
* Write End Element tag.
*
* @throws XMLStreamException
* Invalid XML stream.
*/
public final void writeEndElement() throws XMLStreamException {
writeEndElement(true);
}
/**
* Write End document tag.
*
* @throws XMLStreamException
* Invalid XML stream.
*/
public final void writeEndDocument() throws XMLStreamException {
writer.writeEndDocument();
writer.flush();
}
/**
* Write any cached data to the stream.
*
* @throws XMLStreamException
* Invalid XML stream.
*/
public final void flush() throws XMLStreamException {
writer.flush();
}
/**
* Check if object attribute is serialized.
*
* @param objectType
* Object type
* @param index
* Attribute index.
* @return True, if object attribute is not serialized.
*/
boolean isSerialized(ObjectType objectType, int index) {
if (settings == null) {
return false;
}
for (GXIgnoreSerialize it : settings.getIgnored()) {
if (it.getObjectType() == objectType) {
for (int i : it.getAttributes()) {
if (i == index) {
return false;
}
}
}
}
return true;
}
}