Code Block | ||
---|---|---|
| ||
package nl.wldelft.fews.pi; |
...
import nl.wldelft.util.Arguments; |
...
import nl.wldelft.util.BinaryUtils; |
...
import nl.wldelft.util.Clasz; |
...
import nl.wldelft.util.FastDateFormat; |
...
import nl.wldelft.util.FileUtils; |
...
import nl.wldelft.util.MathUtils; |
...
import nl.wldelft.util.NumberType; |
...
import nl.wldelft.util.ObjectUtils; |
...
import nl.wldelft.util.Period; |
...
import nl.wldelft.util.Properties; |
...
import nl.wldelft.util.TextUtils; |
...
import nl.wldelft.util.TimeZoneUtils; |
...
import nl.wldelft.util.function.Supplier; |
...
import nl.wldelft.util.io.VirtualOutputDir; |
...
import nl.wldelft.util.io.VirtualOutputDirConsumer; |
...
import nl.wldelft.util.io.XmlChunkedSerializer; |
...
import nl.wldelft.util.timeseries.Product; |
...
import nl.wldelft.util.timeseries.ProductInfo; |
...
import nl.wldelft.util.timeseries.Statistics; |
...
import nl.wldelft.util.timeseries.TimeSeriesContent; |
...
import nl.wldelft.util.timeseries.TimeSeriesHeader; |
...
import nl.wldelft.util.timeseries.TimeStep; |
...
import nl.wldelft.util.timeseries.TimesOfDayDaylightSavingTimeStep; |
...
import nl.wldelft.util.timeseries.TimesOfDayTimeStep; |
...
import nl.wldelft.util.timeseries.TimesOfHourTimeStep; |
...
import nl.wldelft.util.timeseries.ValueSource; |
...
import javax.xml.stream.XMLStreamException; |
...
import javax.xml.stream.XMLStreamWriter; |
...
import java.io.IOException; |
...
import java.io.OutputStream; |
...
import java.nio.ByteOrder; |
...
import java.util.Arrays; |
...
import java.util.Locale; |
...
import java.util.TimeZone; |
...
public class PiTimeSeriesSerializer implements |
...
XmlChunkedSerializer<TimeSeriesContent>, VirtualOutputDirConsumer { |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_2 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_2); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_3 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_3); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_4 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_4); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_5 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_5); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_6 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_6); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_7 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_7); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_8 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_8); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_9 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_9); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_10 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_10); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_11 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_11); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, Error> VERSION_1_12 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_12); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_13 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_13); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_14 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_14); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_15 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_15); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_16 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_16); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_17 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_17); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_18 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_18); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_19 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_19); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_20 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_20); |
...
...
|
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_21 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_21); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_22 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_22); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_23 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_23); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_24 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_24); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_25 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_25); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_26 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_26); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_27 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_27); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_28 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_28); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_29 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_29); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_30 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_30); |
...
public static final |
...
Supplier<PiTimeSeriesSerializer, |
...
Error> VERSION_1_31 = () -> new PiTimeSeriesSerializer(PiVersion.VERSION_1_31); |
...
private static final int BUFFER_SIZE = 2048; |
...
private TimeZone timeZone = null; |
...
private String missingValueText = "NaN"; |
...
private float missingValue = Float.NaN; |
...
private String virtualFileName = null; |
...
private boolean skipEmptyTimeSeries = false; |
...
public void setSkipEmptyTimeSeries(boolean skipEmptyTimeSeries) { |
...
this.skipEmptyTimeSeries = skipEmptyTimeSeries; |
...
} |
...
public void setUseMilliseconds (boolean useMilliseconds) {this.useMilliseconds = useMilliseconds; } |
...
public enum EventDestination { |
...
XML_EMBEDDED, SEPARATE_BINARY_FILE, ONLY_HEADERS |
...
} |
...
...
|
...
public enum EnsembleMemberFormat { |
...
INDEX, ID, HIDE |
...
} |
...
private EventDestination eventDestination = EventDestination.XML_EMBEDDED; |
...
private PiVersion version = PiVersion.VERSION_1_2; |
...
private EnsembleMemberFormat ensembleMemberFormat = EnsembleMemberFormat.INDEX; |
...
private boolean anyTimeSeriesWritten = false; |
...
private FastDateFormat dateFormat = null; |
...
private FastDateFormat timeFormat = null; |
...
private boolean useMilliseconds = false; |
...
private TimeSeriesContent timeSeriesContent = null; |
...
private XMLStreamWriter writer = null; |
...
private VirtualOutputDir virtualOutputDir = null; |
...
private OutputStream binaryOutputSteam = null; |
...
private byte[] byteBuffer = null; |
...
private char[] charBuffer = null; |
...
private float[] floatBuffer = null; |
...
private int bufferPos = 0; |
...
private long[] cachedTimes = new long[6]; |
...
private String[] cachedDateStrings = new String[6]; |
...
...
private String[] cachedTimeStrings = new String[6]; |
...
private int cachedSeconds = -1; |
...
private String cachedSecondsString = null; |
...
private float[][] domainAxesValues = null; |
...
private float[][] newDomainValues = null; |
...
public PiTimeSeriesSerializer() { |
...
} |
...
public PiTimeSeriesSerializer(PiVersion version) { |
...
this.version = version; |
...
} |
...
public void setEventDestination(EventDestination eventDestination) { |
...
this.eventDestination = eventDestination; |
...
} |
...
public PiVersion getVersion() { |
...
return version; |
...
} |
...
public void setVersion(PiVersion version) { |
...
Arguments.require.notNull(version); |
...
this.version = version; |
...
} |
...
public void setEnsembleMemberFormat(EnsembleMemberFormat ensembleMemberFormat) { |
...
Arguments.require.notNull(ensembleMemberFormat); |
...
this.ensembleMemberFormat = ensembleMemberFormat; |
...
} |
...
@Override |
...
public void setVirtualOutputDir(VirtualOutputDir virtualOutputDir) { |
...
this.virtualOutputDir = virtualOutputDir; |
...
} |
...
@Override |
...
public void serializeStartDocument(XMLStreamWriter streamWriter, String virtualFileName) throws Exception { |
...
anyTimeSeriesWritten = false; |
...
this.virtualFileName = virtualFileName; |
...
this.writer = streamWriter; |
...
if (ensembleMemberFormat == EnsembleMemberFormat.ID && version.getIntId() < PiVersion.VERSION_1_10.getIntId()) { |
...
throw new IOException("ensembleMemberId not supported for pi version " + version); |
...
} writeStartDocument(); |
...
String binFileName = FileUtils.getPathWithOtherExtension(virtualFileName, "bin"); |
...
if (virtualOutputDir != null) virtualOutputDir.delete(binFileName); |
...
if (eventDestination != EventDestination.SEPARATE_BINARY_FILE) return; |
...
if (virtualOutputDir == null) |
...
throw new IllegalStateException("virtualOutputDir == null"); |
...
binaryOutputSteam = virtualOutputDir.getOutputStream(binFileName); |
...
...
|
...
bufferPos = 0; if (byteBuffer != null) return; |
...
byteBuffer = new byte[BUFFER_SIZE * NumberType.FLOAT_SIZE]; |
...
floatBuffer = new float[BUFFER_SIZE]; |
...
} |
...
public void writeStartDocument() throws XMLStreamException { |
...
writer.writeStartDocument(); |
...
writer.writeStartElement("TimeSeries"); |
...
writer.setDefaultNamespace("http://www.wldelft.nl/fews/PI"); |
...
writer.writeNamespace("", "http://www.wldelft.nl/fews/PI"); |
...
writer.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); |
...
// writer.writeAttribute("xmlns", "http://www.wldelft.nl/fews/PI"); |
...
writer.writeAttribute("xsi:schemaLocation", PiSchemaLocations.get("pi_timeseries.xsd")); |
...
writer.writeAttribute("version", version.toString()); |
...
if (version.getIntId() >= PiVersion.VERSION_1_19.getIntId()) { |
...
writer.writeAttribute("xmlns:fs", "http://www.wldelft.nl/fews/fs"); |
...
} |
...
} |
...
@Override |
...
public void serializeContent(TimeSeriesContent timeSeriesContent) throws Exception { |
...
if (timeSeriesContent.getTimeSeriesCount() == 0) return; |
...
this.timeSeriesContent = timeSeriesContent; |
...
timeSeriesContent.setRequireEnsembleMemberIndices(ensembleMemberFormat == EnsembleMemberFormat.INDEX); |
...
if (!anyTimeSeriesWritten) { |
...
...
|
...
|
...
anyTimeSeriesWritten = true; initMissingValueText(); initTimeZone(); |
...
writeTimeZone(); |
...
} for (int i = 0, n = timeSeriesContent.getTimeSeriesCount(); i < n; i++) { |
...
timeSeriesContent.setTimeSeriesIndex(i); |
...
if (skipEmptyTimeSeries && timeSeriesContent.isTimeSeriesEmpty()) continue; |
...
...
if (!timeSeriesContent.isTimeSeriesEmpty()) timeSeriesContent.setContentTimeIndex(0); |
...
writer.writeStartElement("series"); |
...
writeHeader(); |
...
writeEvents(); |
...
writer.writeEndElement(); |
...
} |
...
} |
...
@Override |
...
public void serializeEndDocument() throws Exception { |
...
if (!anyTimeSeriesWritten) throw new PiTimeSeriesNotFoundException("No TimeSeries to be Written to " + virtualFileName); |
...
writer.writeEndElement(); |
...
writer.writeEndDocument(); |
...
if (eventDestination != EventDestination.SEPARATE_BINARY_FILE) return; |
...
flushBinEvents(); |
...
binaryOutputSteam.close(); |
...
binaryOutputSteam = null; |
...
} |
...
private void initMissingValueText() { |
...
missingValueText = timeSeriesContent.getDefaultMissingValue('.'); |
...
try { |
...
missingValue = Float.parseFloat(missingValueText); |
...
} catch (NumberFormatException e) { |
...
timeSeriesContent.setMissingValue(Float.NaN); |
...
missingValue = Float.NaN; |
...
missingValueText = "NaN"; |
...
} |
...
} |
...
private void initTimeZone() { |
...
if (!ObjectUtils.equals(timeZone, this.timeSeriesContent.getDefaultTimeZone())) { |
...
Arrays.fill(cachedTimes, Long.MIN_VALUE); |
...
timeZone = timeSeriesContent.getDefaultTimeZone(); |
...
} dateFormat = FastDateFormat.getInstance("yyyy-MM-dd", timeZone, Locale.US, dateFormat); |
...
...
|
...
timeFormat = useMilliseconds?FastDateFormat.getInstance("HH:mm:ss.SSS", timeZone, Locale.US, timeFormat) : FastDateFormat.getInstance("HH:mm:ss", timeZone, Locale.US, timeFormat); |
...
} |
...
private void writeTimeZone() throws XMLStreamException { |
...
if (timeZone.useDaylightTime()) { |
...
PiSerializerUtils.writeElement(writer, "daylightSavingObservingTimeZone", timeZone.getID()); |
...
} else { |
...
PiSerializerUtils.writeElement(writer, "timeZone", String.valueOf(TimeZoneUtils.getTimeZoneOffsetHours(timeZone))); |
...
} |
...
} |
...
private void writeHeader() throws Exception { |
...
TimeSeriesHeader header = timeSeriesContent.getTimeSeriesHeader(); |
...
PiTimeSeriesHeader piHeader = header instanceof PiTimeSeriesHeader ? (PiTimeSeriesHeader) header : new PiTimeSeriesHeader(); |
...
writer.writeStartElement("header"); |
...
PiSerializerUtils.writeElement(writer, "type", header.getParameterType() == null ? "instantaneous" : header.getParameterType().getName()); |
...
if (version.getIntId() >= PiVersion.VERSION_1_17.getIntId() && header.getModuleInstanceId() != null) PiSerializerUtils.writeElement(writer, "moduleInstanceId", header.getModuleInstanceId()); |
...
PiSerializerUtils.writeElement(writer, "locationId", header.getLocationId() == null ? "unknown" : header.getLocationId()); |
...
PiSerializerUtils.writeElement(writer, "parameterId", header.getParameterId() == null ? "unknown" : header.getParameterId()); |
...
if (version.getIntId() >= PiVersion.VERSION_1_4.getIntId()) { |
...
for (int i = 0, n = header.getQualifierCount(); i < n; i++) { |
...
PiSerializerUtils.writeElement(writer, "qualifierId", header.getQualifierId(i)); |
...
} } if (version.getIntId() >= PiVersion.VERSION_1_4.getIntId() && header.getEnsembleId() != null && !header.getEnsembleId().equals("main")) { |
...
if (ensembleMemberFormat != EnsembleMemberFormat.HIDE) { |
...
writeOptionalElement("ensembleId", header.getEnsembleId()); |
...
writeOptionalElement(ensembleMemberFormat == EnsembleMemberFormat.INDEX |
...
? "ensembleMemberIndex" : "ensembleMemberId", header.getEnsembleMemberId()); |
...
} } writeTimeStep(header); writePeriod(); if (version.getIntId() >= PiVersion.VERSION_1_5.getIntId()) writeTime("forecastDate", header.getForecastTime(), 2); |
...
if (version.getIntId() >= PiVersion.VERSION_1_20.getIntId()) writeTime("approvedDate", header.getApprovedTime(), 4); |
...
PiSerializerUtils.writeElement(writer, "missVal", timeSeriesContent.getDefaultMissingValue('.')); |
...
writeOptionalElement("longName", piHeader.getLongName()); |
...
writeOptionalElement("stationName", header.getLocationName()); |
...
...
if (version.getIntId() >= PiVersion.VERSION_1_7.getIntId()) PiSerializerUtils.writeCoordinates(writer, header, version); |
...
writeOptionalElement("units", header.getUnit()); |
...
for (int i = 0, n = header.getDomainParameterCount(); i < n; i++) { |
...
writeDomainAxis(header.getDomainParameterId(i), header.getDomainUnit(i)); |
...
} writeOptionalElement("sourceOrganisation", piHeader.getSourceOrganisation()); |
...
writeOptionalElement("sourceSystem", piHeader.getSourceSystem()); |
...
writeOptionalElement("fileDescription", piHeader.getFileDescription()); |
...
if (header.getCreationTime() != Long.MIN_VALUE) { |
...
updateDateTimeStringCache(header.getCreationTime(), 3); |
...
PiSerializerUtils.writeElement(writer, "creationDate", cachedDateStrings[3]); |
...
PiSerializerUtils.writeElement(writer, "creationTime", cachedTimeStrings[3]); |
...
} writeOptionalElement("region", piHeader.getRegion()); |
...
if (header.getHighLevelThresholdCount() > 0) writeHighThresholds(header); |
...
if (version.getIntId() >= PiVersion.VERSION_1_16.getIntId() && timeSeriesContent.hasStatistics()) writeTimeSeriesStatistics(); |
...
if (version.getIntId() >= PiVersion.VERSION_1_26.getIntId() && timeSeriesContent.getProduct() != null) writeProduct(); |
...
writer.writeEndElement(); |
...
} |
...
private void writeProduct() throws XMLStreamException { |
...
Product product = timeSeriesContent.getProduct(); |
...
writer.writeStartElement("product"); |
...
writer.writeAttribute("id", product.getId()); |
...
writer.writeAttribute("name", product.getName()); |
...
writeTime("productDate", product.getProductTime(), 5); |
...
writer.writeEmptyElement("category"); |
...
writer.writeAttribute("id", product.getCategory().getId()); |
...
writer.writeAttribute("name", product.getCategory().getName()); |
...
if (product.getProductInfos() != null && product.getProductInfos().length > 0) { |
...
for (int i = 0; i < product.getProductInfos().length; i++) { |
...
ProductInfo productInfo = product.getProductInfos()[i]; |
...
writer.writeStartElement("productInfo"); |
...
writer.writeStartElement("user"); |
...
writer.writeCharacters(productInfo.getUser()); |
...
writer.writeEndElement(); |
...
writer.writeStartElement("confidence"); |
...
writer.writeCharacters(productInfo.getConfidence()); |
...
writer.writeEndElement(); |
...
writer.writeStartElement("classification"); |
...
writer.writeCharacters(productInfo.getClassification()); |
...
writer.writeEndElement(); |
...
writer.writeStartElement("comment"); |
...
writer.writeCharacters(productInfo.getComment()); |
...
writer.writeEndElement(); |
...
writer.writeEndElement(); // productInfo |
...
} } writer.writeEndElement(); // product |
...
} |
...
private void writeTimeSeriesStatistics() throws XMLStreamException { |
...
Statistics timeSeriesInfoStatistics = timeSeriesContent.getStatistics(); |
...
if (timeSeriesInfoStatistics == null) return; |
...
if (timeSeriesInfoStatistics.hasFirstValueTime()) writeTime("firstValueTime", timeSeriesInfoStatistics.getFirstValueTime(), 0); |
...
...
if (timeSeriesInfoStatistics.hasLastValueTime()) writeTime("lastValueTime", timeSeriesInfoStatistics.getLastValueTime(), 1); |
...
if (timeSeriesInfoStatistics.hasMaxValue()) PiSerializerUtils.writeElement(writer, "maxValue", timeSeriesInfoStatistics.getMaxValue('.')); |
...
if (timeSeriesInfoStatistics.hasMinValue()) PiSerializerUtils.writeElement(writer, "minValue", timeSeriesInfoStatistics.getMinValue('.')); |
...
if (timeSeriesInfoStatistics.hasValueCount()) PiSerializerUtils.writeElement(writer,"valueCount", Integer.toString(timeSeriesInfoStatistics.getValueCount())); |
...
if (timeSeriesInfoStatistics.hasMaxWarningLevelName()) PiSerializerUtils.writeElement(writer, "maxWarningLevelName", timeSeriesInfoStatistics.getMaxWarningLevelName()); |
...
} |
...
private void writeHighThresholds(TimeSeriesHeader header) throws XMLStreamException { |
...
boolean thresholdsAvailable = false; |
...
boolean firstThreshold = true; |
...
for (int i = 0; i < header.getHighLevelThresholdCount(); i++) { |
...
TimeSeriesHeader.Threshold threshold = header.getHighLevelThreshold(i); |
...
...
|
...
|
...
String id = threshold.getId(); String name = threshold.getName(); |
...
//Note: here value can be NaN for LevelThresholdValues that have different values for different aggregationTimeSpans configured. |
...
float value = threshold.getValue(); |
...
if (Float.isNaN(value)) { |
...
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
continue; } thresholdsAvailable = true; if (firstThreshold) { writer.writeStartElement("thresholds"); firstThreshold = false; } if (version.getIntId() >= PiVersion.VERSION_1_14.getIntId()) { String label = null; String comment = null; String description = null; if (version.getIntId() >= PiVersion.VERSION_1_22.getIntId()){ label = threshold.getLabel(); } if (version.getIntId() >= PiVersion.VERSION_1_27.getIntId()){ comment = threshold.getComment(); description = threshold.getDescription(); } if (threshold.getGroupCount() > 0) { for (int j = 0, m = threshold.getGroupCount(); j < m; j++) { String groupId = threshold.getGroupId(j); String groupName = threshold.getGroupName(j); if (threshold.getGroupCount() == 1 && groupId != null && groupId.equalsIgnoreCase("DeprecatedThresholdsConfigured")) { groupId = null; groupName = null; } writeThreshold(id, name, value, groupId, groupName, label, description, comment); } } else { writeThreshold(id, name, value, null, null, label, description, comment); } } else { writeThreshold(id, name, value, null, null, null, null, null); } } if (thresholdsAvailable) { writer.writeEndElement(); } } private void writeThreshold(String id, String name, float value, String groupId, String groupName, String label, String description, String comment) throws XMLStreamException { writer.writeStartElement("highLevelThreshold"); writer.writeAttribute("id", id); writer.writeAttribute("name", name); if (label != null) writer.writeAttribute("label", label); if (description != null) writer.writeAttribute("description", description); if (comment != null) writer.writeAttribute("comment", comment); writer.writeAttribute("value", Float.toString(value)); if (groupId != null) writer.writeAttribute("groupId", groupId); if (groupName != null) writer.writeAttribute("groupName", groupName); writer.writeEndElement(); } private void writePeriod() throws XMLStreamException { TimeStep timeStep = timeSeriesContent.getTimeSeriesHeader().getTimeStep(); Period period = timeSeriesContent.getTimeSeriesPeriod(); Period headerPeriod; if (period == Period.NEVER) { // create a dummy period long now = timeStep.nearestTime(System.currentTimeMillis()); headerPeriod = new Period(now, now); } else { headerPeriod = period; } writeTime("startDate", headerPeriod.getStartTime(), 0); writeTime("endDate", headerPeriod.getEndTime(), 1); } private void updateDateTimeStringCache(long time, int cacheIndex) { if (cachedTimes[cacheIndex] == time) return; cachedTimes[cacheIndex] = time; cachedDateStrings[cacheIndex] = dateFormat.format(time); cachedTimeStrings[cacheIndex] = timeFormat.format(time); } private void writeTime(String name, long time, int cacheIndex) throws XMLStreamException { if (time == Long.MIN_VALUE) return; writer.writeEmptyElement(name); updateDateTimeStringCache(time, cacheIndex); writer.writeAttribute("date", cachedDateStrings[cacheIndex]); writer.writeAttribute("time", cachedTimeStrings[cacheIndex]); } private void writeTimeStep(TimeSeriesHeader header) throws XMLStreamException { writer.writeEmptyElement("timeStep"); TimeStep timeStep = header.getTimeStep(); // todo add support for month time step if (timeStep.isEquidistantMillis()) { writer.writeAttribute("unit", "second"); int seconds = (int) (timeStep.getStepMillis() / 1000); if (cachedSeconds != seconds) { cachedSecondsString = TextUtils.toString(seconds); cachedSeconds = seconds; } writer.writeAttribute("multiplier", cachedSecondsString); } else if (timeStep instanceof TimesOfDayDaylightSavingTimeStep && version.getIntId() >= PiVersion.VERSION_1_18.getIntId()) { writer.writeAttribute("times", PiCastorUtils.getTimesOfDayString((TimesOfDayDaylightSavingTimeStep) timeStep)); } else if (timeStep instanceof TimesOfDayTimeStep && version.getIntId() >= PiVersion.VERSION_1_18.getIntId()) { writer.writeAttribute("times", PiCastorUtils.getTimesOfDayString((TimesOfDayTimeStep) timeStep)); } else if (timeStep instanceof TimesOfHourTimeStep && version.getIntId() >= PiVersion.VERSION_1_24.getIntId()) { writer.writeAttribute("minutes", PiCastorUtils.getTimesOfHourString((TimesOfHourTimeStep) timeStep)); } else { writer.writeAttribute("unit", "nonequidistant"); } } private void writeEvents() throws Exception { switch (eventDestination) { case ONLY_HEADERS: return; case SEPARATE_BINARY_FILE: writeBinEvents(); return; case XML_EMBEDDED: writeXmlEvents(); } } private void writeBinEvents() throws Exception { for (int i = 0, n = timeSeriesContent.getContentTimeCount(); i < n; i++) { timeSeriesContent.setContentTimeIndex(i); if (!timeSeriesContent.isTimeAvailable()) continue; if (bufferPos == BUFFER_SIZE) flushBinEvents(); floatBuffer[bufferPos++] = timeSeriesContent.getValue(); } } private void flushBinEvents() throws IOException { if (bufferPos == 0) return; BinaryUtils.copy(floatBuffer, 0, bufferPos, byteBuffer, 0, bufferPos * NumberType.FLOAT_SIZE, ByteOrder.LITTLE_ENDIAN); binaryOutputSteam.write(byteBuffer, 0, bufferPos * NumberType.FLOAT_SIZE); bufferPos = 0; } private void writeXmlEvents() throws XMLStreamException { Properties properties = Properties.NONE; TimeSeriesHeader header = timeSeriesContent.getTimeSeriesHeader(); domainAxesValues = null; int domainParameterCount = header.getDomainParameterCount(); float[] floatBuffer = this.floatBuffer; for (int i = 0, n = timeSeriesContent.getContentTimeCount(); i < n; i++) { timeSeriesContent.setContentTimeIndex(i); if (!timeSeriesContent.isTimeAvailable()) continue; Properties newProperties = timeSeriesContent.getProperties(); if (!newProperties.equals(properties)) { properties = newProperties; PiSerializerUtils.writeProperties(properties, version, writer, dateFormat, timeFormat); } boolean valueMissing = timeSeriesContent.isValueMissing(); if (domainParameterCount > 0 && !valueMissing) { int valueCount = writeAxisValues(); if (floatBuffer == null || floatBuffer.length != valueCount) { floatBuffer = new float[valueCount]; this.floatBuffer = floatBuffer; } timeSeriesContent.readValues(floatBuffer); } if (domainParameterCount == 0 || valueMissing) { writer.writeEmptyElement("event"); } else { writer.writeStartElement("event"); } writeTime(); if (domainParameterCount == 0) writeValue(); PiSerializerUtils.writeFlagsUserComment(writer, timeSeriesContent, version); if (domainParameterCount == 0 || valueMissing) continue; int valuesPerRow = domainParameterCount == 1 ? 1 : domainAxesValues[1].length; writeValues(floatBuffer, valuesPerRow); writer.writeEndElement(); } } private void writeValue() throws XMLStreamException { String stringValue = timeSeriesContent.getValue('.'); writer.writeAttribute("value", stringValue); if (version.ordinal() >= PiVersion.VERSION_1_31.ordinal() && timeSeriesContent.getValueSource() == ValueSource.MANUAL) writer.writeAttribute("valueSource", "MAN"); if (version.ordinal() < PiVersion.VERSION_1_23.ordinal()) return; if (timeSeriesContent.isValueMissing()) return; float value = timeSeriesContent.getValue(); if (timeSeriesContent.getMinValue() != value) writer.writeAttribute("minValue", timeSeriesContent.getMinValue('.')); if (timeSeriesContent.getMaxValue() != value) writer.writeAttribute("maxValue", timeSeriesContent.getMaxValue('.')); if (version.ordinal() >= PiVersion.VERSION_1_29.ordinal() && !"".equals(timeSeriesContent.getDetectionSymbol())) writer.writeAttribute("detection", timeSeriesContent.getDetectionSymbol()); } private void writeTime() throws XMLStreamException { long time = timeSeriesContent.getTime(); String dateText = dateFormat.format(time); writer.writeAttribute("date", dateText); String timeText = timeFormat.format(time); writer.writeAttribute("time", timeText); if (version.ordinal() < PiVersion.VERSION_1_23.ordinal()) return; long startTime = timeSeriesContent.getRangeStartTime(); long endTime = timeSeriesContent.getRangeEndTime(); writeAttribute("startDate", dateFormat, startTime, time, dateText); writeAttribute("startTime", timeFormat, startTime, time, timeText); writeAttribute("endDate", dateFormat, endTime, time, dateText); writeAttribute("endTime" , timeFormat, endTime, time, timeText); } private void writeAttribute(String attributeName, FastDateFormat dateFormat, long time, long defaultTime, String defaultText) throws XMLStreamException { if (time == defaultTime) return; String text = dateFormat.format(time); if (TextUtils.equals(text, defaultText)) return; writer.writeAttribute(attributeName, text); } private int writeAxisValues() throws XMLStreamException { TimeSeriesHeader header = timeSeriesContent.getTimeSeriesHeader(); if (domainAxesValues == null) domainAxesValues = new float[header.getDomainParameterCount()][]; if (newDomainValues == null) newDomainValues = new float[header.getDomainParameterCount()][]; assert !timeSeriesContent.isValueMissing(); int res = 1; for (int i = 0, n = header.getDomainParameterCount(); i < n; i++) { float[] values = newDomainValues[i]; int valueCount = timeSeriesContent.getDomainAxisValueCount(i); res *= valueCount; if (values == null || values.length != valueCount) { values = new float[valueCount]; newDomainValues[i] = values; } timeSeriesContent.readDomainAxisValues(i, values); if (Arrays.equals(values, domainAxesValues[i])) continue; |
...
writer.writeStartElement("domainAxisValues"); |
...
writer.writeAttribute("parameterId", header.getDomainParameterId(i)); |
...
int valuePerRow = i = |
...
= 0 ? 1 : values.length; writeValues(values, valuePerRow); |
...
domainAxesValues[i] = Clasz.floats.copyOfArray(values); |
...
writer.writeEndElement(); |
...
} return res; |
...
} |
...
private void writeValues(float[] values, int valuesPerRow) throws XMLStreamException { |
...
assert !timeSeriesContent.isValueMissing(); |
...
char[] buffer = this.charBuffer; |
...
if (buffer == null |
...
) { buffer = new char[15]; |
...
this.charBuffer = buffer; |
...
} for (int i = 0; i < values.length; i++) { |
...
buffer[0] = i % valuesPerRow == 0 ? '\n' : '\t'; |
...
float value = values[i]; |
...
int endPos; |
...
if (MathUtils.equals(value, |
...
missingValue)) { missingValueText.getChars(0, missingValueText.length(), buffer, 1); |
...
endPos = missingValueText.length() + 1; |
...
} else { |
...
endPos = TextUtils.format(buffer, 1, value, '.', 0, 10); |
...
} writer.writeCharacters(buffer, |
...
0, endPos); // start with space } writer.writeCharacters("\n "); |
...
} |
...
private void writeOptionalElement(String elementName, String s) throws XMLStreamException { |
...
if (s == null) return; |
...
if (s.trim().isEmpty()) return; |
...
PiSerializerUtils.writeElement(writer, elementName, s); |
...
} |
...
private void writeDomainAxis(String parameterId, String unit) throws XMLStreamException { |
...
writer.writeEmptyElement("domainAxis"); |
...
writer.writeAttribute("parameterId", parameterId); |
...
if (unit != null) writer.writeAttribute("units", unit); |
...
} |
...
} |