From 4677471f6a30c85db17fbc3121737063d7351093 Mon Sep 17 00:00:00 2001 From: ashley Date: Fri, 5 Dec 2025 16:15:33 -0600 Subject: [PATCH 01/15] adding new and newly edited files --- .../java/org/vast/swe/fast/CotDataReader.java | 295 ++++++++++++++++++ .../java/org/vast/swe/fast/CotDataWriter.java | 275 ++++++++++++++++ .../service/consys/obs/ObsBindingCotXml.java | 280 +++++++++++++++++ .../consys/resource/ResourceBinding.java | 4 +- .../resource/ResourceBindingCotXml.java | 138 ++++++++ 5 files changed, 991 insertions(+), 1 deletion(-) create mode 100644 lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java create mode 100644 lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java create mode 100644 sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java create mode 100644 sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java new file mode 100644 index 0000000000..30493ecd5a --- /dev/null +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java @@ -0,0 +1,295 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + +The contents of this file are subject to the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +Copyright (C) 2012-2015 Sensia Software LLC. All Rights Reserved. + +******************************* END LICENSE BLOCK ***************************/ + +package org.vast.swe.fast; + +import com.ctc.wstx.api.WstxOutputProperties; +import com.google.gson.FormattingStyle; +import com.google.gson.Strictness; +import net.opengis.swe.v20.*; +import net.opengis.swe.v20.Boolean; +import org.vast.data.AbstractArrayImpl; +import org.vast.data.XMLEncodingImpl; +import org.vast.swe.SWEDataTypeUtils; +import org.vast.util.DateTimeFormat; +import org.vast.util.WriterException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.*; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Reader; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + + +/** + *

+ * New implementation of XML data writer with better efficiency since the + * write tree is pre-computed during init instead of being re-evaluated + * while iterating through the component tree. + *

+ * + * @author Ashley Poteau + * @since Dec 2, 2025 + */ +// xmlstreamreader +public class CotDataReader implements XMLStreamReader { + static final String COT_ERROR = "Error writing XML stream for "; + private final Reader in; + + protected XMLStreamWriter xmlWriter; + protected String namespace; + protected String prefix; + protected Map countWriters = new HashMap<>(); + private Strictness strictness = Strictness.LEGACY_STRICT; + private boolean serializeNulls = true; + private FormattingStyle formattingStyle; + // These fields cache data derived from the formatting style, to avoid having to + // re-evaluate it every time something is written + private String formattedColon; + private String formattedComma; + private boolean usesEmptyNewlineAndIndent; + + public CotDataReader(Reader in) { + this.in = Objects.requireNonNull(in, "in == null"); + } + + @Override + public Object getProperty(String s) throws IllegalArgumentException { + return null; + } + + @Override + public int next() throws XMLStreamException { + return 0; + } + + @Override + public void require(int i, String s, String s1) throws XMLStreamException { + + } + + @Override + public String getElementText() throws XMLStreamException { + return ""; + } + + @Override + public int nextTag() throws XMLStreamException { + return 0; + } + + @Override + public boolean hasNext() throws XMLStreamException { + return false; + } + + @Override + public void close() throws XMLStreamException { + + } + + @Override + public String getNamespaceURI(String s) { + return ""; + } + + @Override + public boolean isStartElement() { + return false; + } + + @Override + public boolean isEndElement() { + return false; + } + + @Override + public boolean isCharacters() { + return false; + } + + @Override + public boolean isWhiteSpace() { + return false; + } + + @Override + public String getAttributeValue(String s, String s1) { + return ""; + } + + @Override + public int getAttributeCount() { + return 0; + } + + @Override + public QName getAttributeName(int i) { + return null; + } + + @Override + public String getAttributeNamespace(int i) { + return ""; + } + + @Override + public String getAttributeLocalName(int i) { + return ""; + } + + @Override + public String getAttributePrefix(int i) { + return ""; + } + + @Override + public String getAttributeType(int i) { + return ""; + } + + @Override + public String getAttributeValue(int i) { + return ""; + } + + @Override + public boolean isAttributeSpecified(int i) { + return false; + } + + @Override + public int getNamespaceCount() { + return 0; + } + + @Override + public String getNamespacePrefix(int i) { + return ""; + } + + @Override + public String getNamespaceURI(int i) { + return ""; + } + + @Override + public NamespaceContext getNamespaceContext() { + return null; + } + + @Override + public int getEventType() { + return 0; + } + + @Override + public String getText() { + return ""; + } + + @Override + public char[] getTextCharacters() { + return new char[0]; + } + + @Override + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + return 0; + } + + @Override + public int getTextStart() { + return 0; + } + + @Override + public int getTextLength() { + return 0; + } + + @Override + public String getEncoding() { + return ""; + } + + @Override + public boolean hasText() { + return false; + } + + @Override + public Location getLocation() { + return null; + } + + @Override + public QName getName() { + return null; + } + + @Override + public String getLocalName() { + return ""; + } + + @Override + public boolean hasName() { + return false; + } + + @Override + public String getNamespaceURI() { + return ""; + } + + @Override + public String getPrefix() { + return ""; + } + + @Override + public String getVersion() { + return ""; + } + + @Override + public boolean isStandalone() { + return false; + } + + @Override + public boolean standaloneSet() { + return false; + } + + @Override + public String getCharacterEncodingScheme() { + return ""; + } + + @Override + public String getPITarget() { + return ""; + } + + @Override + public String getPIData() { + return ""; + } +} diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java new file mode 100644 index 0000000000..1735041ddd --- /dev/null +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java @@ -0,0 +1,275 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + +The contents of this file are subject to the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +Copyright (C) 2012-2015 Sensia Software LLC. All Rights Reserved. + +******************************* END LICENSE BLOCK ***************************/ + +package org.vast.swe.fast; + +import com.ctc.wstx.api.WstxOutputProperties; +import com.google.gson.FormattingStyle; +import com.google.gson.Strictness; +import net.opengis.swe.v20.*; +import net.opengis.swe.v20.Boolean; +import org.vast.data.AbstractArrayImpl; +import org.vast.data.XMLEncodingImpl; +import org.vast.swe.SWEDataTypeUtils; +import org.vast.util.DateTimeFormat; +import org.vast.util.WriterException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + + +/** + *

+ * New implementation of XML data writer with better efficiency since the + * write tree is pre-computed during init instead of being re-evaluated + * while iterating through the component tree. + *

+ * + * @author Ashley Poteau + * @since Oct 31, 2025 + */ +// xmlstreamwriter +public class CotDataWriter implements XMLStreamWriter { + static final String COT_ERROR = "Error writing XML stream for "; + + protected XMLStreamWriter xmlWriter; + protected String namespace; + protected String prefix; + protected Map countWriters = new HashMap<>(); + private Strictness strictness = Strictness.LEGACY_STRICT; + private boolean serializeNulls = true; + private FormattingStyle formattingStyle; + // These fields cache data derived from the formatting style, to avoid having to + // re-evaluate it every time something is written + private String formattedColon; + private String formattedComma; + private boolean usesEmptyNewlineAndIndent; + + public final void setStrictness(Strictness strictness) { + this.strictness = Objects.requireNonNull(strictness); + } + + public final Strictness getStrictness() { + return strictness; + } + + public final void setSerializeNulls(boolean serializeNulls) { + + this.serializeNulls = serializeNulls; + } + + /** + * Returns true if object members are serialized when their value is null. This has no impact on + * array elements. The default is true. + */ + public final boolean getSerializeNulls() { + return serializeNulls; + } + + public final void setFormattingStyle(FormattingStyle formattingStyle) { + this.formattingStyle = Objects.requireNonNull(formattingStyle); + + this.formattedComma = ","; + if (this.formattingStyle.usesSpaceAfterSeparators()) { + this.formattedColon = ": "; + + // Only add space if no newline is written + if (this.formattingStyle.getNewline().isEmpty()) { + this.formattedComma = ", "; + } + } else { + this.formattedColon = ":"; + } + + this.usesEmptyNewlineAndIndent = + this.formattingStyle.getNewline().isEmpty() && this.formattingStyle.getIndent().isEmpty(); + } + + public final void setIndent(String indent) { + if (indent.isEmpty()) { + setFormattingStyle(FormattingStyle.COMPACT); + } else { + setFormattingStyle(FormattingStyle.PRETTY.withIndent(indent)); + } + } + + @Override + public void writeStartElement(String s) throws XMLStreamException { + + } + + @Override + public void writeStartElement(String s, String s1) throws XMLStreamException { + + } + + @Override + public void writeStartElement(String s, String s1, String s2) throws XMLStreamException { + + } + + @Override + public void writeEmptyElement(String s, String s1) throws XMLStreamException { + + } + + @Override + public void writeEmptyElement(String s, String s1, String s2) throws XMLStreamException { + + } + + @Override + public void writeEmptyElement(String s) throws XMLStreamException { + + } + + @Override + public void writeEndElement() throws XMLStreamException { + + } + + @Override + public void writeEndDocument() throws XMLStreamException { + + } + + @Override + public void close() throws XMLStreamException { + + } + + @Override + public void flush() throws XMLStreamException { + + } + + @Override + public void writeAttribute(String s, String s1) throws XMLStreamException { + + } + + @Override + public void writeAttribute(String s, String s1, String s2, String s3) throws XMLStreamException { + + } + + @Override + public void writeAttribute(String s, String s1, String s2) throws XMLStreamException { + + } + + @Override + public void writeNamespace(String s, String s1) throws XMLStreamException { + + } + + @Override + public void writeDefaultNamespace(String s) throws XMLStreamException { + + } + + @Override + public void writeComment(String s) throws XMLStreamException { + + } + + @Override + public void writeProcessingInstruction(String s) throws XMLStreamException { + + } + + @Override + public void writeProcessingInstruction(String s, String s1) throws XMLStreamException { + + } + + @Override + public void writeCData(String s) throws XMLStreamException { + + } + + @Override + public void writeDTD(String s) throws XMLStreamException { + + } + + @Override + public void writeEntityRef(String s) throws XMLStreamException { + + } + + @Override + public void writeStartDocument() throws XMLStreamException { + + } + + @Override + public void writeStartDocument(String s) throws XMLStreamException { + + } + + @Override + public void writeStartDocument(String s, String s1) throws XMLStreamException { + + } + + @Override + public void writeCharacters(String s) throws XMLStreamException { + + } + + @Override + public void writeCharacters(char[] chars, int i, int i1) throws XMLStreamException { + + } + + @Override + public String getPrefix(String s) throws XMLStreamException { + return ""; + } + + @Override + public void setPrefix(String s, String s1) throws XMLStreamException { + + } + + @Override + public void setDefaultNamespace(String s) throws XMLStreamException { + + } + + @Override + public void setNamespaceContext(NamespaceContext namespaceContext) throws XMLStreamException { + + } + + @Override + public NamespaceContext getNamespaceContext() { + return null; + } + + @Override + public Object getProperty(String s) throws IllegalArgumentException { + return null; + } + +} diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java new file mode 100644 index 0000000000..99ac53b6e3 --- /dev/null +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -0,0 +1,280 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + +The contents of this file are subject to the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +Copyright (C) 2020 Sensia Software LLC. All Rights Reserved. + +******************************* END LICENSE BLOCK ***************************/ + +package org.sensorhub.impl.service.consys.obs; + +import com.google.common.collect.Sets; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import org.sensorhub.api.common.BigId; +import org.sensorhub.api.common.IdEncoders; +import org.sensorhub.api.data.IDataStreamInfo; +import org.sensorhub.api.data.IObsData; +import org.sensorhub.api.data.ObsData; +import org.sensorhub.api.datastore.feature.IFoiStore; +import org.sensorhub.api.datastore.obs.DataStreamKey; +import org.sensorhub.api.datastore.obs.IObsStore; +import org.sensorhub.impl.service.consys.ResourceParseException; +import org.sensorhub.impl.service.consys.SWECommonUtils; +import org.sensorhub.impl.service.consys.ServiceErrors; +import org.sensorhub.impl.service.consys.obs.ObsHandler.ObsHandlerContextData; +import org.sensorhub.impl.service.consys.resource.PropertyFilter; +import org.sensorhub.impl.service.consys.resource.RequestContext; +import org.sensorhub.impl.service.consys.resource.ResourceBindingJson; +import org.sensorhub.impl.service.consys.resource.ResourceLink; +import org.sensorhub.utils.SWEDataUtils; +import org.vast.cdm.common.DataStreamWriter; +import org.vast.swe.BinaryDataWriter; +import org.vast.swe.SWEConstants; +import org.vast.swe.ScalarIndexer; +import org.vast.swe.fast.AbstractDataWriter; +import org.vast.swe.fast.JsonDataParserGson; +import org.vast.swe.fast.JsonDataWriterGson; +import org.vast.swe.helper.GeoPosHelper; +import org.vast.util.ReaderException; +import org.vast.xml.DOMHelper; + +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import java.io.IOException; +import java.io.OutputStream; +import java.time.OffsetDateTime; +import java.time.format.DateTimeParseException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static org.sensorhub.impl.service.consys.SWECommonUtils.OM_COMPONENTS_FILTER; + + +public class ObsBindingCotXml extends ResourceBindingJson +{ + ObsHandlerContextData contextData; + IObsStore obsStore; + XMLStreamReader resultReader; + Map resultWriters; + DOMHelper dom; + ScalarIndexer timeStampIndexer; + XMLOutputFactory factory = XMLOutputFactory.newInstance(); + //CotDataWriter cotWriter; + OutputStream os; + + IFoiStore foiStore; + + private static final Set LOCATION_DEFINITIONS = Sets.newHashSet( + SWEConstants.DEF_SENSOR_LOC, + SWEConstants.DEF_PLATFORM_LOC, + SWEConstants.DEF_SAMPLING_LOC, + GeoPosHelper.DEF_LOCATION + ); + + public ObsBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boolean forReading, IObsStore obsStore) throws IOException + { + super(ctx, idEncoders, forReading); + this.contextData = (ObsHandlerContextData)ctx.getData(); + this.obsStore = obsStore; + + if (forReading) + { + resultReader = getSweCommonParser(contextData.dsInfo, reader); + resultReader.setRenewDataBlock(true); + timeStampIndexer = SWEDataUtils.getTimeStampIndexer(contextData.dsInfo.getRecordStructure()); + } + else + { + this.resultWriters = new HashMap<>(); + + // init result writer only in case of single datastream + // otherwise we'll do it later + if (contextData != null && contextData.dsInfo != null) + { + var resultWriter = getSweCommonWriter(contextData.dsInfo, writer, ctx.getPropertyFilter()); + resultWriters.put(ctx.getParentID(), resultWriter); + } + } + } + + + @Override + public IObsData deserialize(JsonReader reader) throws IOException + { + // if array, prepare to parse first element + if (reader.peek() == JsonToken.BEGIN_ARRAY) + reader.beginArray(); + + if (reader.peek() == JsonToken.END_DOCUMENT || !reader.hasNext()) + return null; + + var obs = new ObsData.Builder() + .withDataStream(contextData.dsID); + + try + { + reader.beginObject(); + + while (reader.hasNext()) + { + var propName = reader.nextName(); + + if ("phenomenonTime".equals(propName)) + obs.withPhenomenonTime(OffsetDateTime.parse(reader.nextString()).toInstant()); + else if ("resultTime".equals(propName)) + obs.withResultTime(OffsetDateTime.parse(reader.nextString()).toInstant()); + else if ("foi@id".equals(propName)) + { + try + { + var foiID = idEncoders.getFoiIdEncoder().decodeID(reader.nextString()); + obs.withFoi(foiID); + } + catch (IllegalArgumentException e) + { + throw ServiceErrors.badRequest("Invalid FOI ID"); + } + } + else if ("result".equals(propName)) + { + var result = resultReader.parseNextBlock(); + obs.withResult(result); + } + else + reader.skipValue(); + } + + reader.endObject(); + } + catch (DateTimeParseException e) + { + throw new ResourceParseException(INVALID_JSON_ERROR_MSG + "Invalid ISO8601 date/time at " + reader.getPath()); + } + catch (IllegalStateException | ReaderException e) + { + throw new ResourceParseException(INVALID_JSON_ERROR_MSG + e.getMessage()); + } + + if (contextData.foiId != null && contextData.foiId != BigId.NONE) + obs.withFoi(contextData.foiId); + + var newObs = obs.build(); + + // set timestamp in result data if present in schema + if (timeStampIndexer != null) + { + var phenomenonTimeIdx = timeStampIndexer.getDataIndex(newObs.getResult()); + newObs.getResult().setDoubleValue(phenomenonTimeIdx, newObs.getPhenomenonTime().toEpochMilli() / 1000.0); + } + + return newObs; + } + + + @Override + public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter writer) throws IOException + { + writer.beginObject(); + + if (key != null) + { + var obsId = idEncoders.getObsIdEncoder().encodeID(key); + writer.name("id").value(obsId); + } + + if (!ctx.isClientSide()) + { + var dsId = idEncoders.getDataStreamIdEncoder().encodeID(obs.getDataStreamID()); + writer.name("datastream@id").value(dsId); + } + + if (obs.hasFoi()) + { + var foiId = idEncoders.getFoiIdEncoder().encodeID(obs.getFoiID()); + writer.name("foi@id").value(foiId); + } + + writer.name("phenomenonTime").value(obs.getPhenomenonTime().toString()); + writer.name("resultTime").value(obs.getResultTime().toString()); + + // create or reuse existing result writer and write result data + writer.name("result"); + var resultWriter = resultWriters.computeIfAbsent(obs.getDataStreamID(), + k -> getSweCommonWriter(k, writer, ctx.getPropertyFilter()) ); + + // write if JSON is supported, otherwise print warning message + if (resultWriter instanceof JsonDataWriterGson) + resultWriter.write(obs.getResult()); + else + writer.value("Compressed binary result not shown in JSON"); + + writer.endObject(); + writer.flush(); + } + + + protected JsonWriter getJsonWriter(OutputStream os, PropertyFilter propFilter) throws IOException + { + var writer = super.getJsonWriter(os, propFilter); + writer.setSerializeNulls(true); + return writer; + } + + + protected DataStreamWriter getSweCommonWriter(BigId dsID, JsonWriter writer, PropertyFilter propFilter) + { + var dsInfo = obsStore.getDataStreams().get(new DataStreamKey(dsID)); + return getSweCommonWriter(dsInfo, writer, propFilter); + } + + + protected DataStreamWriter getSweCommonWriter(IDataStreamInfo dsInfo, JsonWriter writer, PropertyFilter propFilter) + { + if (!SWECommonUtils.allowNonBinaryFormat(dsInfo.getRecordStructure(), dsInfo.getRecordEncoding())) + return new BinaryDataWriter(); + + // create JSON SWE writer + var sweWriter = new JsonDataWriterGson(writer); + sweWriter.setDataComponents(dsInfo.getRecordStructure()); + + // filter out components that are already included in O&M + sweWriter.setDataComponentFilter(OM_COMPONENTS_FILTER); + return sweWriter; + } + + + protected JsonDataParserGson getSweCommonParser(IDataStreamInfo dsInfo, JsonReader reader) + { + // create JSON SWE parser + var sweParser = new JsonDataParserGson(reader); + sweParser.setDataComponents(dsInfo.getRecordStructure()); + + // filter out components that are already included in O&M + sweParser.setDataComponentFilter(OM_COMPONENTS_FILTER); + return sweParser; + } + + + @Override + public void startCollection() throws IOException + { + startJsonCollection(writer); + } + + + @Override + public void endCollection(Collection links) throws IOException + { + endJsonCollection(writer, links); + } +} diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java index 66213aacc5..5e2ff81771 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java @@ -19,6 +19,8 @@ import org.sensorhub.api.common.IdEncoders; import org.vast.util.Asserts; +import javax.xml.stream.XMLStreamException; + /** *

@@ -49,7 +51,7 @@ protected ResourceBinding(RequestContext ctx, IdEncoders idEncoders) public abstract V deserialize() throws IOException; public abstract void serialize(K key, V res, boolean showLinks) throws IOException; - public abstract void startCollection() throws IOException; + public abstract void startCollection() throws IOException, XMLStreamException; public abstract void endCollection(Collection links) throws IOException; diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java new file mode 100644 index 0000000000..349170cfae --- /dev/null +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java @@ -0,0 +1,138 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + +The contents of this file are subject to the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +Copyright (C) 2020 Sensia Software LLC. All Rights Reserved. + +******************************* END LICENSE BLOCK ***************************/ + +package org.sensorhub.impl.service.consys.resource; + +import com.google.gson.Strictness; +import com.google.gson.stream.JsonReader; +import org.sensorhub.api.common.IdEncoders; +import org.vast.swe.fast.CotDataReader; +import org.vast.swe.fast.CotDataWriter; +import org.vast.xml.XMLImplFinder; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.Set; + + +/** + *

+ * Base class for all XML resource formatters + *

+ * + * @param Resource Key + * @param Resource Object + * + * @author Ashley Poteau + * @since Dec 3, 2025 + */ +public abstract class ResourceBindingCotXml extends ResourceBinding +{ + public static final String INVALID_XML_ERROR_MSG = "Invalid XML: "; + public static final String MISSING_PROP_ERROR_MSG = "Missing property: "; + + protected final XMLStreamReader xmlReader; + protected final XMLStreamWriter xmlWriter; + + protected boolean isCollection; + + Set excludedProps; + Set includedProps; + + protected ResourceBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boolean forReading) throws IOException + { + super(ctx, idEncoders); + + try + { + if (forReading) + { + var factory = XMLImplFinder.getStaxInputFactory(); + var is = new BufferedInputStream(ctx.getInputStream()); + xmlReader = factory.createXMLStreamReader(is, StandardCharsets.UTF_8.name()); + xmlWriter = null; + } + else + { + var factory = XMLImplFinder.getStaxOutputFactory(); + var os = ctx.getOutputStream();//new BufferedOutputStream(ctx.getOutputStream()); + xmlWriter = factory.createXMLStreamWriter(os, StandardCharsets.UTF_8.name()); + xmlReader = null; + } + } + catch (XMLStreamException e) + { + throw new IOException("Error initializing XML bindings", e); + } + } + + public abstract V deserialize(XMLStreamReader xmlReader) throws IOException; + public abstract void serialize(K key, V res, boolean showLinks, XMLStreamWriter xmlWriter) throws IOException; + + + protected CotDataReader getCotReader(InputStream is) throws IOException + { + var osr = new InputStreamReader(is, StandardCharsets.UTF_8); + return new CotDataReader(osr); + } + + protected CotDataWriter getCotWriter(OutputStream os, PropertyFilter propFilter) throws IOException + { + CotDataWriter writer = new CotDataWriter(); + var osw = new OutputStreamWriter(os, StandardCharsets.UTF_8); + if (propFilter != null) { + this.excludedProps = propFilter.getExcludedProps(); + this.includedProps = propFilter.getIncludedProps(); + } +// else +// writer = new JsonInliningWriter(osw); + + writer.setStrictness(Strictness.LENIENT); + writer.setSerializeNulls(false); + writer.setIndent(INDENT); + return writer; + } + + + @Override + public V deserialize() throws IOException + { + return deserialize(this.xmlReader); + } + + @Override + public void serialize(K key, V res, boolean showLinks) throws IOException { + serialize(key, res, showLinks, this.xmlWriter); + } + + @Override + public void startCollection() throws IOException, XMLStreamException { + isCollection = true; + startXMLCollection(xmlWriter); + } + + protected void startXMLCollection(XMLStreamWriter xmlWriter) throws XMLStreamException { + xmlWriter.writeStartElement(getItemsPropertyName()); + // xmlWriter.beginArray(); + } + + protected String getItemsPropertyName() + { + return "items"; + } + +} \ No newline at end of file From e9ace213a88c1b4452ae49e6437cf2e8e5ad0424 Mon Sep 17 00:00:00 2001 From: ashley Date: Tue, 16 Dec 2025 12:30:57 -0600 Subject: [PATCH 02/15] creating datarec, cothelper --- .../java/org/vast/swe/helper/CoTHelper.java | 735 ++++++++++++++++++ .../service/consys/obs/ObsBindingCotXml.java | 326 ++++---- .../resource/ResourceBindingCotXml.java | 15 +- 3 files changed, 927 insertions(+), 149 deletions(-) create mode 100644 lib-ogc/swe-common-core/src/main/java/org/vast/swe/helper/CoTHelper.java diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/helper/CoTHelper.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/helper/CoTHelper.java new file mode 100644 index 0000000000..ac8b746437 --- /dev/null +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/helper/CoTHelper.java @@ -0,0 +1,735 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + +The contents of this file are subject to the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer is Botts Innovative Research Inc. Portions created by the Initial +Developer are Copyright (C) 2016 the Initial Developer. All Rights Reserved. + +******************************* END LICENSE BLOCK ***************************/ + +package org.vast.swe.helper; + +import net.opengis.swe.v20.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.vast.swe.SWEBuilders.QuantityBuilder; +import org.vast.swe.SWEBuilders.VectorBuilder; +import org.vast.swe.SWEConstants; +import org.vast.swe.SWEHelper; + + +/** + *

+ * Helper class to create SWE structures used for geo-positioning
+ * This includes location and attitude but also linear velocity, angular rate, + * and linear acceleration + *

+ * + * @author Ashley Poteau + * @since December 11, 2025 + */ +public class CoTHelper extends VectorHelper +{ + + private static final Logger logger = LoggerFactory.getLogger(CoTHelper.class); + + public static final String DEF_LATITUDE_GEODETIC = SWEHelper.getPropertyUri("GeodeticLatitude"); + public static final String DEF_LONGITUDE = SWEHelper.getPropertyUri("Longitude"); + public static final String DEF_ALTITUDE_ELLIPSOID = SWEHelper.getPropertyUri("HeightAboveEllipsoid"); + public static final String DEF_ALTITUDE_MSL = SWEHelper.getPropertyUri("HeightAboveMSL"); + public static final String DEF_ALTITUDE_GROUND = SWEHelper.getPropertyUri("HeightAboveGround"); + public static final String DEF_ALTITUDE_BAROMETRIC = SWEHelper.getPropertyUri("BarometricAltitude"); + public static final String DEF_HEADING_TRUE = SWEHelper.getPropertyUri("TrueHeading"); + public static final String DEF_HEADING_MAGNETIC = SWEHelper.getPropertyUri("MagneticHeading"); + public static final String DEF_YAW_ANGLE = SWEHelper.getPropertyUri("YawAngle"); + public static final String DEF_PITCH_ANGLE = SWEHelper.getPropertyUri("PitchAngle"); + public static final String DEF_ROLL_ANGLE = SWEHelper.getPropertyUri("RollAngle"); + public static final String DEF_AZIMUTH_ANGLE = SWEHelper.getPropertyUri("AzimuthAngle"); + public static final String DEF_ELEVATION_ANGLE = SWEHelper.getPropertyUri("ElevationAngle"); + + public Time createPrecisionTimeStamp(){ + return createTime() + .asSamplingTimeIsoUTC() + .name("time") + .description("time stamp: when the event was generated") + .build(); + } + + public Quantity createCoTVersion(){ + return createQuantity() + .name("version") + .label("Version") + .definition(SWEHelper.getPropertyUri("cot-version")) + .description("Schema version of this event instance (e.g. 2.0)") + .build(); + } + public Category createUID(){ + return createCategory() + .name("uid") + .label("UID") + .definition(SWEHelper.getPropertyUri("id")) + .description("Globally unique name for this information on this event") + .build(); + } + + public Category createType(){ + return createCategory() + .name("type") + .label("Type") + .definition(SWEHelper.getPropertyUri("cot-type")) + .description("Hierarchically organized hint about event type") + .build(); + } + + public Time createStartTime(){ + return createTime() + .asSamplingTimeIsoUTC() + .name("start-time") + .label("Start Time") + .definition(SWEHelper.getPropertyUri("start-time")) + .description("starting time when an event should be considered valid") + .build(); + } + + public Time createStaleTime(){ + return createTime() + .asSamplingTimeIsoUTC() + .name("stale-time") + .label("Stale Time") + .definition(SWEHelper.getPropertyUri("stale-time")) + .description("ending time when an event should no longer be considered valid") + .build(); + } + public Text createHow(){ + return createText() + .name("how") + .label("How") + .definition(SWEHelper.getPropertyUri("cot-how")) + .description("Gives a hint about how the coordinates were generated") + .build(); + } + + public Quantity createCE(){ + return createQuantity() + .name("ce") + .label("Radius") + .definition(SWEHelper.getPropertyUri("cot-ce")) + .description("Circular 1-sigma or a circular area about the point in meters") + .uomCode("m") + .build(); + } + public Quantity createLE(){ + return createQuantity() + .name("le") + .label("Height") + .definition(SWEHelper.getPropertyUri("cot-le")) + .description("Linear 1-sigma error or an altitude range about the point in meters") + .uomCode("m") + .build(); + } + + public Text createRmkSrc(){ + return createText() + .name("source") + .label("Source") + .definition(SWEHelper.getPropertyUri("Remarks Source")) + .description("OpenSensorHub") + .build(); + } + + /** + * Creates a geodetic latitude field (WGS84 datum, degrees) + * @return A builder to set other options and build the final quantity + */ + public QuantityBuilder createLatitude() + { + return createQuantity() + .definition(DEF_LATITUDE_GEODETIC) + .refFrame(SWEConstants.REF_FRAME_4326) + .label("Geodetic Latitude") + .axisId("Lat") + .uomCode("deg"); + } + + + /** + * Creates a longitude field (WGS84 datum, degrees) + * @return A builder to set other options and build the final quantity + */ + public QuantityBuilder createLongitude() + { + return createQuantity() + .definition(DEF_LONGITUDE) + .refFrame(SWEConstants.REF_FRAME_4326) + .label("Longitude") + .axisId("Lon") + .uomCode("deg"); + } + + + /** + * Creates an ellipsoidal height field, also called altitude above ellipsoid (WGS84 datum, meters) + * @return A builder to set other options and build the final quantity + */ + public QuantityBuilder createAltitudeWGS84() + { + return createQuantity() + .definition(DEF_ALTITUDE_ELLIPSOID) + .refFrame(SWEConstants.REF_FRAME_WGS84_HAE) + .label("Ellipsoidal Height") + .description("Altitude above WGS84 ellipsoid") + .uom("m"); + } + + + /** + * Creates an MSL altitude field (approximate MSL datum, meters) + * @return A builder to set other options and build the final quantity + */ + public QuantityBuilder createAltitudeMSL() + { + return createQuantity() + .definition(DEF_ALTITUDE_MSL) + .refFrame(SWEConstants.VERTICAL_CRS_MSL_HEIGHT) + .label("MSL Height") + .description("Altitude above mean sea level (approximate datum)") + .uom("m"); + } + + + /** + * Creates a 3D location vector with latitude/longitude/altitude axes and WGS84 datum (EPSG 4979) + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createLocationVectorLLA() + { + return createVector() + .definition(DEF_LOCATION) + .refFrame(SWEConstants.REF_FRAME_WGS84_HAE) + .addCoordinate("lat", createLatitude() + .refFrame(null)) + .addCoordinate("lon", createLongitude() + .refFrame(null)) + .addCoordinate("alt", createAltitudeWGS84() + .refFrame(null) + .axisId("h")); + } + + + /** + * Creates a 3D location vector with latitude/longitude/altitude axes and WGS84 datum (EPSG 4979) + * @param def semantic definition of location vector (if null, {@link #DEF_LOCATION} is used) + * @return the new Vector component object + */ + public Vector newLocationVectorLLA(String def) + { + return createLocationVectorLLA() + .definition(def != null ? def : DEF_LOCATION) + .build(); + } + + + /** + * Creates a 3D location vector with latitude/longitude on WGS84 datum (EPSG 4326) + * and MSL altitude (EPSG 5714) + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createLocationVectorLLA_MSL() + { + return createVector() + .definition(DEF_LOCATION) + .refFrame(SWEConstants.REF_FRAME_WGS84_MSL) + .addCoordinate("lat", createLatitude() + .refFrame(null)) + .addCoordinate("lon", createLongitude() + .refFrame(null)) + .addCoordinate("alt", createAltitudeMSL() + .refFrame(null) + .axisId("h")); + } + + + /** + * Creates a 3D location vector with latitude/longitude on WGS84 datum (EPSG 4326) + * and MSL altitude (EPSG 5714) + * @param def semantic definition of location vector (if null, {@link #DEF_LOCATION} is used) + * @return the new Vector component object + */ + public Vector newLocationVectorLLA_MSL(String def) + { + return createLocationVectorLLA_MSL() + .definition(def != null ? def : DEF_LOCATION) + .build(); + } + + + /** + * Creates a 2D location vector with latitude/longitude axes (EPSG 4326) + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createLocationVectorLatLon() + { + return createVector() + .definition(DEF_LOCATION) + .refFrame(SWEConstants.REF_FRAME_4326) + .addCoordinate("lat", createLatitude() + .refFrame(null)) + .addCoordinate("lon", createLongitude() + .refFrame(null)); + } + + + /** + * @see #createLocationVectorLatLon(String) + * @param def semantic definition of location vector (if null, {@link #DEF_LOCATION} is used) + * @return the new Vector component object + */ + public Vector newLocationVectorLatLon(String def) + { + return createLocationVectorLatLon() + .definition(def != null ? def : DEF_LOCATION) + .build(); + } + + + /** + * Creates a 3D location vector with ECEF X/Y/Z axes (EPSG 4978) + * @param uomCode unit of distance to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createLocationVectorECEF(String uomCode) + { + return createLocationVectorXYZ(uomCode) + .refFrame(SWEConstants.REF_FRAME_WGS84_ECEF); + } + + + /** + * Creates a 3D location vector with ECEF X/Y/Z axes (EPSG 4978) + * @param def semantic definition of location vector (if null, {@link #DEF_LOCATION} is used) + * @param uomCode unit of distance to use on all 3 axes + * @return the new Vector component object + */ + public Vector newLocationVectorECEF(String def, String uomCode) + { + return newLocationVectorXYZ(def, SWEConstants.REF_FRAME_WGS84_ECEF, "m"); + } + + + /** + * Creates a 3D location vector with ECEF X/Y/Z axes (EPSG 4978), measured in meters + * @param def semantic definition of location vector (if null, {@link #DEF_LOCATION} is used) + * @return the new Vector component object + */ + public Vector newLocationVectorECEF(String def) + { + return newLocationVectorECEF(def, "m"); + } + + + /** + * Creates a 3D velocity vector with ECEF X/Y/Z axes (EPSG 4978) + * @param uomCode unit of velocity to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createVelocityVectorECEF(String uomCode) + { + return createVelocityVector(uomCode) + .refFrame(SWEConstants.REF_FRAME_WGS84_ECEF); + } + + + /** + * Creates a 3D velocity with ECEF X/Y/Z axes (EPSG 4978) + * @param def semantic definition of velocity vector (if null, {@link #DEF_VELOCITY} is used) + * @param uomCode unit of velocity to use on all 3 axes + * @return the new Vector component object + */ + public Vector newVelocityVectorECEF(String def, String uomCode) + { + return newVelocityVector(def, SWEConstants.REF_FRAME_WGS84_ECEF, uomCode); + } + + + /** + * Creates a 3D velocity vector with ENU X/Y/Z axes + * @param uomCode unit of velocity to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createVelocityVectorENU(String uomCode) + { + return createVelocityVector(uomCode) + .refFrame(SWEConstants.REF_FRAME_ENU); + } + + + /** + * Creates a 3D velocity with ENU X/Y/Z axes + * @param def semantic definition of velocity vector (if null, {@link #DEF_VELOCITY} is used) + * @param uomCode unit of velocity to use on all 3 axes + * @return the new Vector component object + */ + public Vector newVelocityVectorENU(String def, String uomCode) + { + return newVelocityVector(def, SWEConstants.REF_FRAME_ENU, uomCode); + } + + + /** + * Creates a 3D velocity vector with NED X/Y/Z axes + * @param uomCode unit of velocity to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createVelocityVectorNED(String uomCode) + { + return createVelocityVector(uomCode) + .refFrame(SWEConstants.REF_FRAME_NED); + } + + + /** + * Creates a 3D velocity with NED X/Y/Z axes + * @param def semantic definition of velocity vector (if null, {@link #DEF_VELOCITY} is used) + * @param uomCode unit of velocity to use on all 3 axes + * @return the new Vector component object + */ + public Vector newVelocityVectorNED(String def, String uomCode) + { + return newVelocityVector(def, SWEConstants.REF_FRAME_NED, uomCode); + } + + + /** + * Creates a 3D orientation vector composed of 3 Euler angles expressed in a local + * frame (order of rotations is yaw/Z, pitch/X, roll/Y in rotating frame) + * @param uomCode angular unit to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createEulerOrientationYPR(String uomCode) + { + if (uomCode == null) + uomCode = "deg"; + + return createVector() + .definition(DEF_ORIENTATION_EULER) + .description("Euler angles with order of rotation yaw/pitch/roll in rotating frame") + .dataType(DataType.FLOAT) + .addCoordinate("yaw", createQuantity() + .definition(DEF_YAW_ANGLE) + .label("Yaw Angle") + .uomCode(uomCode) + .axisId("Z") + .build()) + .addCoordinate("pitch", createQuantity() + .definition(DEF_PITCH_ANGLE) + .label("Pitch Angle") + .uomCode(uomCode) + .axisId("X") + .build()) + .addCoordinate("roll", createQuantity() + .definition(DEF_ROLL_ANGLE) + .label("Roll Angle") + .uomCode(uomCode) + .axisId("Y") + .build()); + } + + + /** + * Creates a 3D orientation vector composed of 3 Euler angles expressed in local + * East-North-Up (ENU) frame (order of rotations is heading/Z, pitch/X, roll/Y in rotating frame) + * @param uomCode angular unit to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createEulerOrientationENU(String uomCode) + { + if (uomCode == null) + uomCode = "deg"; + + return createVector() + .definition(DEF_ORIENTATION_EULER) + .description("Euler angles with order of rotation heading/pitch/roll in rotating frame") + .refFrame(SWEConstants.REF_FRAME_ENU) + .dataType(DataType.FLOAT) + .addCoordinate("heading", createQuantity() + .definition(DEF_HEADING_TRUE) + .label("Heading Angle") + .description("Heading angle from east direction, measured counter clockwise") + .uomCode(uomCode) + .axisId("Z") + .build()) + .addCoordinate("pitch", createQuantity() + .definition(DEF_PITCH_ANGLE) + .label("Pitch Angle") + .description("Rotation around the lateral axis, up/down from the local horizontal plane (positive when pointing up)") + .uomCode(uomCode) + .axisId("X") + .build()) + .addCoordinate("roll", createQuantity() + .definition(DEF_ROLL_ANGLE) + .label("Roll Angle") + .description("Rotation around the longitudinal axis") + .uomCode(uomCode) + .axisId("Y") + .build()); + } + + + /** + * Creates a 3D orientation vector composed of 3 Euler angles expressed in local + * East-North-Up (ENU) frame (order of rotations is heading/Z, pitch/X, roll/Y in rotating frame) + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_EULER} is used) + * @param uomCode angular unit to use on all 3 axes + * @return the new Vector component object + */ + public Vector newEulerOrientationENU(String def, String uomCode) + { + return createEulerOrientationENU(uomCode) + .definition(def != null ? def : DEF_ORIENTATION_EULER) + .build(); + } + + + /** + * Creates a 3D orientation vector composed of 3 Euler angles expressed in local + * North-East-Down (NED) frame (order of rotations is heading/Z, pitch/Y, roll/X in rotating frame) + * @param uomCode angular unit to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createEulerOrientationNED(String uomCode) + { + if (uomCode == null) + uomCode = "deg"; + + return createVector() + .definition(DEF_ORIENTATION_EULER) + .description("Euler angles with order of rotation heading/pitch/roll in rotating frame") + .refFrame(SWEConstants.REF_FRAME_NED) + .dataType(DataType.FLOAT) + .addCoordinate("heading", createQuantity() + .definition(DEF_HEADING_TRUE) + .label("Heading Angle") + .description("Heading angle from true north, measured clockwise") + .uomCode(uomCode) + .axisId("Z") + .build()) + .addCoordinate("pitch", createQuantity() + .definition(DEF_PITCH_ANGLE) + .label("Pitch Angle") + .description("Rotation around the lateral axis, up/down from the local horizontal plane (positive when pointing up)") + .uomCode(uomCode) + .axisId("Y") + .build()) + .addCoordinate("roll", createQuantity() + .definition(DEF_ROLL_ANGLE) + .label("Roll Angle") + .description("Rotation around the longitudinal axis") + .uomCode(uomCode) + .axisId("X") + .build()); + } + + + /** + * Creates a 3D orientation vector composed of 3 Euler angles expressed in local + * North-East-Down (NED) frame (order of rotations is heading/Z, pitch/Y, roll/X in rotating frame) + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_EULER} is used) + * @param uomCode angular unit to use on all 3 axes + * @return the new Vector component object + */ + public Vector newEulerOrientationNED(String def, String uomCode) + { + return createEulerOrientationNED(uomCode) + .definition(def != null ? def : DEF_ORIENTATION_EULER) + .build(); + } + + + /** + * Default version of {@link #newEulerOrientationNED(String, String)} with + * units set to degrees + * @param def + * @return the new Vector component object + */ + public Vector newEulerOrientationNED(String def) + { + return newEulerOrientationNED(def, "deg"); + } + + + /** + * Creates an orientation vector component composed of 3 Euler angles expressed in + * Earth-Centered-Earth-Fixed (ECEF) frame (order of rotations is X, Y, Z) + * @param uomCode angular unit to use on all 3 axes + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createEulerOrientationECEF(String uomCode) + { + if (uomCode == null) + uomCode = "deg"; + + return createVector() + .definition(DEF_ORIENTATION_EULER) + .description("Euler angles with order of rotation Z/Y/X in rotating frame") + .refFrame(SWEConstants.REF_FRAME_NED) + .dataType(DataType.FLOAT) + .addCoordinate("rz", createQuantity() + .definition(DEF_ANGLE) + .label("Z Rotation") + .uomCode(uomCode) + .axisId("Z") + .build()) + .addCoordinate("ry", createQuantity() + .definition(DEF_ANGLE) + .label("Y Rotation") + .uomCode(uomCode) + .axisId("Y") + .build()) + .addCoordinate("rx", createQuantity() + .definition(DEF_ANGLE) + .label("X Rotation") + .uomCode(uomCode) + .axisId("X") + .build()); + } + + + /** + * Creates an orientation vector component composed of 3 Euler angles expressed in + * Earth-Centered-Earth-Fixed (ECEF) frame (order of rotations is X, Y, Z) + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_EULER} is used) + * @param uomCode angular unit to use on all 3 axes + * @return the new Vector component object + */ + public Vector newEulerOrientationECEF(String def, String uomCode) + { + return createEulerOrientationECEF(uomCode) + .definition(def != null ? def : DEF_ORIENTATION_EULER) + .build(); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in the given frame (scalar comes last). + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_QUAT} is used) + * @param refFrame reference frame with respect to which the coordinates of this quaternion are expressed + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createQuatOrientation() + { + return createVector() + .definition(DEF_ORIENTATION_QUAT) + .description("Orientation quaternion, usually normalized") + .dataType(DataType.FLOAT) + .addCoordinate("qx", createQuantity() + .definition(SWEConstants.DEF_COEF) + .label("X Component") + .uomCode("1") + .axisId("X") + .build()) + .addCoordinate("qy", createQuantity() + .definition(SWEConstants.DEF_COEF) + .label("Y Component") + .uomCode("1") + .axisId("Y") + .build()) + .addCoordinate("qz", createQuantity() + .definition(SWEConstants.DEF_COEF) + .label("Z Component") + .uomCode("1") + .axisId("Z") + .build()) + .addCoordinate("q0", createQuantity() + .definition(SWEConstants.DEF_COEF) + .label("Scalar Component") + .uomCode("1") + .build()); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in the given frame (scalar comes last). + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_QUAT} is used) + * @param refFrame reference frame with respect to which the coordinates of this quaternion are expressed + * @return the new Vector component object + */ + public Vector newQuatOrientation(String def, String refFrame) + { + return createQuatOrientation() + .definition(def != null ? def : DEF_ORIENTATION_QUAT) + .refFrame(refFrame) + .build(); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in ENU frame. + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createQuatOrientationENU() + { + return createQuatOrientation() + .refFrame(SWEConstants.REF_FRAME_ENU); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in ENU frame. + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_QUAT} is used) + * @return the new Vector component object + */ + public Vector newQuatOrientationENU(String def) + { + return newQuatOrientation(def, SWEConstants.REF_FRAME_ENU); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in NED frame. + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createQuatOrientationNED() + { + return createQuatOrientation() + .refFrame(SWEConstants.REF_FRAME_NED); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in NED frame. + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_QUAT} is used) + * @return the new Vector component object + */ + public Vector newQuatOrientationNED(String def) + { + return newQuatOrientation(def, SWEConstants.REF_FRAME_NED); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in ECEF frame. + * @return A builder to set other options and build the final vector + */ + public VectorBuilder createQuatOrientationECEF() + { + return createQuatOrientation() + .refFrame(SWEConstants.REF_FRAME_WGS84_ECEF); + } + + + /** + * Creates a 4d vector representing an orientation quaternion expressed in ECEF frame. + * @param def semantic definition of orientation vector (if null, {@link #DEF_ORIENTATION_QUAT} is used) + * @return the new Vector component object + */ + public Vector newQuatOrientationECEF(String def) + { + return newQuatOrientation(def, SWEConstants.REF_FRAME_WGS84_ECEF); + } +} diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java index 99ac53b6e3..f0e260b623 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -14,6 +14,7 @@ package org.sensorhub.impl.service.consys.obs; +import com.ctc.wstx.api.WstxOutputProperties; import com.google.common.collect.Sets; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; @@ -30,49 +31,50 @@ import org.sensorhub.impl.service.consys.SWECommonUtils; import org.sensorhub.impl.service.consys.ServiceErrors; import org.sensorhub.impl.service.consys.obs.ObsHandler.ObsHandlerContextData; -import org.sensorhub.impl.service.consys.resource.PropertyFilter; -import org.sensorhub.impl.service.consys.resource.RequestContext; -import org.sensorhub.impl.service.consys.resource.ResourceBindingJson; -import org.sensorhub.impl.service.consys.resource.ResourceLink; +import org.sensorhub.impl.service.consys.resource.*; import org.sensorhub.utils.SWEDataUtils; import org.vast.cdm.common.DataStreamWriter; +import org.vast.data.DataBlockMixed; +import org.vast.data.XMLEncodingImpl; import org.vast.swe.BinaryDataWriter; import org.vast.swe.SWEConstants; import org.vast.swe.ScalarIndexer; -import org.vast.swe.fast.AbstractDataWriter; -import org.vast.swe.fast.JsonDataParserGson; -import org.vast.swe.fast.JsonDataWriterGson; +import org.vast.swe.fast.*; import org.vast.swe.helper.GeoPosHelper; +import net.opengis.swe.v20.DataBlock; +import org.sensorhub.api.data.DataEvent; import org.vast.util.ReaderException; import org.vast.xml.DOMHelper; - +import net.opengis.swe.v20.DataRecord; import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import org.vast.swe.helper.CoTHelper; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.time.OffsetDateTime; import java.time.format.DateTimeParseException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; import static org.sensorhub.impl.service.consys.SWECommonUtils.OM_COMPONENTS_FILTER; -public class ObsBindingCotXml extends ResourceBindingJson +public class ObsBindingCotXml extends ResourceBindingCotXml { ObsHandlerContextData contextData; IObsStore obsStore; - XMLStreamReader resultReader; + XmlDataParser resultReader; + CotDataReader cotReader; // unused... + CotDataWriter cotWriter; Map resultWriters; DOMHelper dom; ScalarIndexer timeStampIndexer; XMLOutputFactory factory = XMLOutputFactory.newInstance(); - //CotDataWriter cotWriter; OutputStream os; - IFoiStore foiStore; + protected DataRecord dataRec; private static final Set LOCATION_DEFINITIONS = Sets.newHashSet( SWEConstants.DEF_SENSOR_LOC, @@ -81,200 +83,238 @@ public class ObsBindingCotXml extends ResourceBindingJson GeoPosHelper.DEF_LOCATION ); - public ObsBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boolean forReading, IObsStore obsStore) throws IOException - { + protected ObsBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boolean forReading, IObsStore obsStore) throws IOException, XMLStreamException { super(ctx, idEncoders, forReading); this.contextData = (ObsHandlerContextData)ctx.getData(); this.obsStore = obsStore; - + + dom = new DOMHelper(); + if (forReading) { - resultReader = getSweCommonParser(contextData.dsInfo, reader); + var inputStream = ctx.getInputStream(); + resultReader = getSweCommonParser(contextData.dsInfo, inputStream); resultReader.setRenewDataBlock(true); timeStampIndexer = SWEDataUtils.getTimeStampIndexer(contextData.dsInfo.getRecordStructure()); + } else { this.resultWriters = new HashMap<>(); - + // init result writer only in case of single datastream // otherwise we'll do it later if (contextData != null && contextData.dsInfo != null) { - var resultWriter = getSweCommonWriter(contextData.dsInfo, writer, ctx.getPropertyFilter()); + var resultWriter = getSweCommonWriter(contextData.dsInfo, os); resultWriters.put(ctx.getParentID(), resultWriter); } } } - - + @Override - public IObsData deserialize(JsonReader reader) throws IOException - { - // if array, prepare to parse first element - if (reader.peek() == JsonToken.BEGIN_ARRAY) - reader.beginArray(); - - if (reader.peek() == JsonToken.END_DOCUMENT || !reader.hasNext()) - return null; - + public IObsData deserialize(CotDataReader xmlReader) throws IOException { var obs = new ObsData.Builder() - .withDataStream(contextData.dsID); - - try - { - reader.beginObject(); - - while (reader.hasNext()) - { - var propName = reader.nextName(); - - if ("phenomenonTime".equals(propName)) - obs.withPhenomenonTime(OffsetDateTime.parse(reader.nextString()).toInstant()); - else if ("resultTime".equals(propName)) - obs.withResultTime(OffsetDateTime.parse(reader.nextString()).toInstant()); - else if ("foi@id".equals(propName)) - { - try - { - var foiID = idEncoders.getFoiIdEncoder().decodeID(reader.nextString()); - obs.withFoi(foiID); - } - catch (IllegalArgumentException e) - { - throw ServiceErrors.badRequest("Invalid FOI ID"); + .withDataStream(contextData.dsID); + + CoTHelper fac = new CoTHelper(); + + String vers = "2.0"; + + dataRec = (DataRecord) fac.createRecord() // come back to this casting............ + .label("") + .addField("version", fac.createCoTVersion()) + .addField("type", fac.createType()) + .addField("uid", fac.createUID()) + .addField("time", fac.createPrecisionTimeStamp()) + .addField("start-time", fac.createStartTime()) + .addField("stale-time", fac.createStaleTime()) + .addField("how", fac.createHow()) + .label("") + .label("") + .addField("lat", fac.createLatitude()) + .addField("lon", fac.createLongitude()) + .addField("ce", fac.createCE()) + // hae here?..... + .addField("le", fac.createLE()) + .label("") + .label("") + // + .label("") + .addField("source", fac.createRmkSrc()) + .addField("time", fac.createPrecisionTimeStamp()) + .label("") + .label(""); + + try { + while (xmlReader.hasNext()) { + xmlReader.next(); + + //var propName = reader.nextName(); + + if (xmlReader.isStartElement()) { + String propName = xmlReader.getLocalName(); + + if ("phenomenonTime".equals(propName)) + obs.withPhenomenonTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); + else if ("resultTime".equals(propName)) + obs.withResultTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); + else if ("foi@id".equals(propName)) { + try { + var foiID = idEncoders.getFoiIdEncoder().decodeID(xmlReader.getElementText()); + obs.withFoi(foiID); + } catch (IllegalArgumentException e) { + throw ServiceErrors.badRequest("Invalid FOI ID"); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } else if ("result".equals(propName)) { + var result = xmlReader.next(); + obs.withResult((DataBlock) dataRec); // what is this } } - else if ("result".equals(propName)) - { - var result = resultReader.parseNextBlock(); - obs.withResult(result); - } - else - reader.skipValue(); + } - - reader.endObject(); } catch (DateTimeParseException e) { - throw new ResourceParseException(INVALID_JSON_ERROR_MSG + "Invalid ISO8601 date/time at " + reader.getPath()); + throw new ResourceParseException(INVALID_XML_ERROR_MSG + "Invalid ISO8601 date/time at " + xmlReader.getLocalName()); } - catch (IllegalStateException | ReaderException e) + catch (IllegalStateException e) { - throw new ResourceParseException(INVALID_JSON_ERROR_MSG + e.getMessage()); + throw new ResourceParseException(INVALID_XML_ERROR_MSG + e.getMessage()); + } catch (XMLStreamException e) { + throw new RuntimeException(e); } - + if (contextData.foiId != null && contextData.foiId != BigId.NONE) obs.withFoi(contextData.foiId); - + var newObs = obs.build(); - + // set timestamp in result data if present in schema if (timeStampIndexer != null) { var phenomenonTimeIdx = timeStampIndexer.getDataIndex(newObs.getResult()); newObs.getResult().setDoubleValue(phenomenonTimeIdx, newObs.getPhenomenonTime().toEpochMilli() / 1000.0); } - + return newObs; } - @Override - public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter writer) throws IOException - { - writer.beginObject(); - - if (key != null) - { - var obsId = idEncoders.getObsIdEncoder().encodeID(key); - writer.name("id").value(obsId); + public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter xmlWriter) throws IOException, XMLStreamException { + Set locationComponents = new HashSet<>(); + + var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); + for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { + var component = dataStream.getRecordStructure().getComponent(i); + if (LOCATION_DEFINITIONS.contains(component.getDefinition())) { + // This is how we know we have location components in the data structure + // So we can save this and parse specifically the location components into GeoJSON + locationComponents.add(i); + } } - - if (!ctx.isClientSide()) - { - var dsId = idEncoders.getDataStreamIdEncoder().encodeID(obs.getDataStreamID()); - writer.name("datastream@id").value(dsId); + + double longitude = 0; + double latitude = 0; + + for (int index : locationComponents) { + var locationDataBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject()[index]; + // You'll still need to check if these are real values and not null + latitude = locationDataBlock.getDoubleValue(0); + longitude = locationDataBlock.getDoubleValue(1); } - - if (obs.hasFoi()) - { - var foiId = idEncoders.getFoiIdEncoder().encodeID(obs.getFoiID()); - writer.name("foi@id").value(foiId); + + var obsId = idEncoders.getObsIdEncoder().encodeID(key); + + var obsName = dataStream.getOutputName(); + + if (!(longitude == 0.0 && latitude == 0.0)) { + factory.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, false); + XMLOutputFactory factory = XMLOutputFactory.newInstance(); + xmlWriter = (CotDataWriter) factory.createXMLStreamWriter(System.out); + xmlWriter.writeStartElement(""); + + cotWriter.flush(); } - - writer.name("phenomenonTime").value(obs.getPhenomenonTime().toString()); - writer.name("resultTime").value(obs.getResultTime().toString()); - - // create or reuse existing result writer and write result data - writer.name("result"); - var resultWriter = resultWriters.computeIfAbsent(obs.getDataStreamID(), - k -> getSweCommonWriter(k, writer, ctx.getPropertyFilter()) ); - - // write if JSON is supported, otherwise print warning message - if (resultWriter instanceof JsonDataWriterGson) - resultWriter.write(obs.getResult()); - else - writer.value("Compressed binary result not shown in JSON"); - - writer.endObject(); - writer.flush(); } - - - protected JsonWriter getJsonWriter(OutputStream os, PropertyFilter propFilter) throws IOException - { - var writer = super.getJsonWriter(os, propFilter); + + + protected CotDataWriter getCotWriter(OutputStream os, PropertyFilter propFilter) throws IOException { + var writer = super.getCotWriter(os, propFilter); writer.setSerializeNulls(true); return writer; } - - - protected DataStreamWriter getSweCommonWriter(BigId dsID, JsonWriter writer, PropertyFilter propFilter) - { + + protected AbstractDataWriter getSweCommonWriter(BigId dsID, OutputStream os) throws IOException { var dsInfo = obsStore.getDataStreams().get(new DataStreamKey(dsID)); - return getSweCommonWriter(dsInfo, writer, propFilter); + + return getSweCommonWriter(dsInfo, os); } - - - protected DataStreamWriter getSweCommonWriter(IDataStreamInfo dsInfo, JsonWriter writer, PropertyFilter propFilter) - { - if (!SWECommonUtils.allowNonBinaryFormat(dsInfo.getRecordStructure(), dsInfo.getRecordEncoding())) - return new BinaryDataWriter(); - - // create JSON SWE writer - var sweWriter = new JsonDataWriterGson(writer); - sweWriter.setDataComponents(dsInfo.getRecordStructure()); - + + protected AbstractDataWriter getSweCommonWriter(IDataStreamInfo dsInfo, OutputStream os) throws IOException { +// if (!SWECommonUtils.allowNonBinaryFormat(dsInfo.getRecordStructure(), dsInfo.getRecordEncoding())) +// return new BinaryDataWriter(); // i see i cant return BinaryDataWriter because this method and the one before are now + // AbstractDataWriter instead of DataStreamWriter, but idk what else to return... + // the auto fix just creates more errors and issues. i dont wanna meddle too much in other files + // not too sure what this does at all tbh + +//// if (dsInfo.getRecordEncoding() instanceof TextEncodingImpl) { +//// throw new IOException("Text encoding not supported for application/cot+xml"); +//// } + + // create cot/xml writer + XmlDataWriter dataWriter = new XmlDataWriter(); //wraps writer. when you return writer, + // youre passing in a writer that knows how to write the specific xml data it needs. + //CotWriter responsible for writing cot spec compliant info + + //xmlcotwriter extends xmldatawriter. new class. same with xmlcotparser and reader. convert it back into a swecommondata record that can be put in osh + + dataWriter.setDataEncoding(new XMLEncodingImpl()); + dataWriter.setOutput(os); + dataWriter.setDataComponents(dsInfo.getRecordStructure()); + //cotWriter.setDataEncoding(dsInfo.getRecordEncoding()); + // filter out components that are already included in O&M - sweWriter.setDataComponentFilter(OM_COMPONENTS_FILTER); - return sweWriter; + dataWriter.setDataComponentFilter(OM_COMPONENTS_FILTER); + return dataWriter; } - - - protected JsonDataParserGson getSweCommonParser(IDataStreamInfo dsInfo, JsonReader reader) - { - // create JSON SWE parser - var sweParser = new JsonDataParserGson(reader); + + protected XmlDataParser getSweCommonParser(IDataStreamInfo dsInfo, InputStream is) throws IOException { + //should be cotxmlparser... soon + // do i have to make a parser actually.....? + + // create XML SWE parser + var sweParser = new XmlDataParser(); sweParser.setDataComponents(dsInfo.getRecordStructure()); - + // filter out components that are already included in O&M sweParser.setDataComponentFilter(OM_COMPONENTS_FILTER); + sweParser.setInput(is); return sweParser; } @Override - public void startCollection() throws IOException - { - startJsonCollection(writer); + public void startCollection() throws XMLStreamException { + + // if we're reading, just skip to the items array + // calls to deserialize() will take it from there + //xmlReader.beginObject(); // idk what to replace this with......... + while (xmlReader.hasNext()) { + var propName = xmlReader.getLocalName(); + if (propName.equals(getItemsPropertyName())) + return; + else + xmlReader.next(); + } } @Override public void endCollection(Collection links) throws IOException { - endJsonCollection(writer, links); + xmlReader.isEndElement(); // reader... or writer...?? } } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java index 349170cfae..30be58249e 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java @@ -45,8 +45,11 @@ public abstract class ResourceBindingCotXml extends ResourceBinding public static final String INVALID_XML_ERROR_MSG = "Invalid XML: "; public static final String MISSING_PROP_ERROR_MSG = "Missing property: "; - protected final XMLStreamReader xmlReader; - protected final XMLStreamWriter xmlWriter; +// protected final XMLStreamReader xmlReader; +// protected final XMLStreamWriter xmlWriter; + + protected final CotDataReader xmlReader; + protected final CotDataWriter xmlWriter; protected boolean isCollection; @@ -63,14 +66,14 @@ protected ResourceBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boole { var factory = XMLImplFinder.getStaxInputFactory(); var is = new BufferedInputStream(ctx.getInputStream()); - xmlReader = factory.createXMLStreamReader(is, StandardCharsets.UTF_8.name()); + xmlReader = (CotDataReader) factory.createXMLStreamReader(is, StandardCharsets.UTF_8.name()); xmlWriter = null; } else { var factory = XMLImplFinder.getStaxOutputFactory(); var os = ctx.getOutputStream();//new BufferedOutputStream(ctx.getOutputStream()); - xmlWriter = factory.createXMLStreamWriter(os, StandardCharsets.UTF_8.name()); + xmlWriter = (CotDataWriter) factory.createXMLStreamWriter(os, StandardCharsets.UTF_8.name()); xmlReader = null; } } @@ -80,8 +83,8 @@ protected ResourceBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boole } } - public abstract V deserialize(XMLStreamReader xmlReader) throws IOException; - public abstract void serialize(K key, V res, boolean showLinks, XMLStreamWriter xmlWriter) throws IOException; + public abstract V deserialize(CotDataReader xmlReader) throws IOException; + public abstract void serialize(K key, V res, boolean showLinks, CotDataWriter xmlWriter) throws IOException, XMLStreamException; protected CotDataReader getCotReader(InputStream is) throws IOException From 68d30d240f5f1b5260a4619285b88666c9e6ecea Mon Sep 17 00:00:00 2001 From: ashley Date: Tue, 16 Dec 2025 13:42:20 -0600 Subject: [PATCH 03/15] fixing comments, endCollection --- .../impl/service/consys/obs/ObsBindingCotXml.java | 11 +++++------ .../impl/service/consys/resource/ResourceBinding.java | 4 ++-- .../consys/resource/ResourceBindingCotXml.java | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java index f0e260b623..97a9e8d475 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -121,7 +121,7 @@ public IObsData deserialize(CotDataReader xmlReader) throws IOException { String vers = "2.0"; - dataRec = (DataRecord) fac.createRecord() // come back to this casting............ + dataRec = (DataRecord) fac.createRecord() .label("") .addField("version", fac.createCoTVersion()) .addField("type", fac.createType()) @@ -170,7 +170,7 @@ else if ("foi@id".equals(propName)) { } } else if ("result".equals(propName)) { var result = xmlReader.next(); - obs.withResult((DataBlock) dataRec); // what is this + obs.withResult((DataBlock) dataRec); } } @@ -301,7 +301,6 @@ public void startCollection() throws XMLStreamException { // if we're reading, just skip to the items array // calls to deserialize() will take it from there - //xmlReader.beginObject(); // idk what to replace this with......... while (xmlReader.hasNext()) { var propName = xmlReader.getLocalName(); if (propName.equals(getItemsPropertyName())) @@ -313,8 +312,8 @@ public void startCollection() throws XMLStreamException { @Override - public void endCollection(Collection links) throws IOException - { - xmlReader.isEndElement(); // reader... or writer...?? + public void endCollection(Collection links) throws IOException, XMLStreamException { + xmlWriter.close(); + xmlWriter.flush(); } } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java index 5e2ff81771..b9d794bea4 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBinding.java @@ -50,9 +50,9 @@ protected ResourceBinding(RequestContext ctx, IdEncoders idEncoders) public abstract V deserialize() throws IOException; - public abstract void serialize(K key, V res, boolean showLinks) throws IOException; + public abstract void serialize(K key, V res, boolean showLinks) throws IOException, XMLStreamException; public abstract void startCollection() throws IOException, XMLStreamException; - public abstract void endCollection(Collection links) throws IOException; + public abstract void endCollection(Collection links) throws IOException, XMLStreamException; protected String getAbsoluteHref(String href) diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java index 30be58249e..24d86efd4f 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java @@ -118,7 +118,7 @@ public V deserialize() throws IOException } @Override - public void serialize(K key, V res, boolean showLinks) throws IOException { + public void serialize(K key, V res, boolean showLinks) throws IOException, XMLStreamException { serialize(key, res, showLinks, this.xmlWriter); } From 011e2db04b09620565c43c3521ca5a06c5bcef3b Mon Sep 17 00:00:00 2001 From: ashley Date: Tue, 6 Jan 2026 11:12:04 -0600 Subject: [PATCH 04/15] pushing --- .../impl/service/consys/RootHandler.java | 5 +- .../impl/service/consys/SWECommonUtils.java | 4 + .../AbstractFeatureHistoryHandler.java | 5 +- .../consys/home/CollectionHandler.java | 11 +- .../consys/obs/DataStreamSchemaHandler.java | 8 +- .../service/consys/obs/ObsBindingCotXml.java | 1 - .../service/consys/obs/ObsBindingGeoJson.java | 322 ++++++++++++++++++ .../impl/service/consys/obs/ObsHandler.java | 17 +- .../service/consys/obs/ObsStatsHandler.java | 5 +- .../consys/resource/BaseResourceHandler.java | 22 +- .../consys/resource/IResourceHandler.java | 4 +- .../consys/resource/ResourceFormat.java | 14 +- .../service/consys/task/CommandHandler.java | 4 + .../consys/task/CommandStatusHandler.java | 4 + .../task/CommandStreamSchemaHandler.java | 8 +- 15 files changed, 395 insertions(+), 39 deletions(-) create mode 100644 sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingGeoJson.java diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/RootHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/RootHandler.java index eaccc5636a..28156cd249 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/RootHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/RootHandler.java @@ -19,6 +19,8 @@ import org.sensorhub.impl.service.consys.resource.IResourceHandler; import org.sensorhub.impl.service.consys.resource.RequestContext; +import javax.xml.stream.XMLStreamException; + public class RootHandler extends BaseHandler { @@ -36,8 +38,7 @@ public RootHandler(HomePageHandler homePage, boolean readOnly) @Override - public void doGet(RequestContext ctx) throws IOException - { + public void doGet(RequestContext ctx) throws IOException, XMLStreamException { IResourceHandler resource = ctx.isEndOfPath() ? homePage : getSubResource(ctx); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java index e5d2f4c8ff..860ff1ead7 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java @@ -217,6 +217,10 @@ public static Collection getAvailableFormats(IDataStreamInfo dsInfo, Map formatList.add(ResourceFormat.SWE_TEXT.getMimeType()); formatList.add(ResourceFormat.SWE_XML.getMimeType()); } + + formatList.add(ResourceFormat.COT_XML.getMimeType()); + + formatList.add(ResourceFormat.GEO_JSON.getMimeType()); formatList.add(ResourceFormat.SWE_BINARY.getMimeType()); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/feature/AbstractFeatureHistoryHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/feature/AbstractFeatureHistoryHandler.java index 98e13cbeb2..dc30681bf8 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/feature/AbstractFeatureHistoryHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/feature/AbstractFeatureHistoryHandler.java @@ -36,6 +36,8 @@ import org.slf4j.LoggerFactory; import org.vast.ogc.gml.IFeature; +import javax.xml.stream.XMLStreamException; + public abstract class AbstractFeatureHistoryHandler< V extends IFeature, @@ -70,8 +72,7 @@ public void doPut(RequestContext ctx) throws IOException @Override - protected void getById(final RequestContext ctx, final String id) throws IOException - { + protected void getById(final RequestContext ctx, final String id) throws IOException, XMLStreamException { // check permissions var parentId = ctx.getParentRef().id; ctx.getSecurityHandler().checkParentPermission(permissions.get, parentId); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/home/CollectionHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/home/CollectionHandler.java index e2c6499434..52d67bcf1e 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/home/CollectionHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/home/CollectionHandler.java @@ -34,6 +34,8 @@ import org.sensorhub.impl.service.consys.system.SystemHandler; import org.vast.swe.SWEConstants; +import javax.xml.stream.XMLStreamException; + public class CollectionHandler extends BaseHandler { @@ -117,8 +119,7 @@ public String[] getNames() @Override - public void doGet(RequestContext ctx) throws InvalidRequestException, IOException, SecurityException - { + public void doGet(RequestContext ctx) throws InvalidRequestException, IOException, SecurityException, XMLStreamException { // check permissions //ctx.getSecurityHandler().checkPermission(permissions.read); @@ -183,8 +184,7 @@ protected void addItemsLink(String title, String path, Set links) } - void list(RequestContext ctx) throws IOException - { + void list(RequestContext ctx) throws IOException, XMLStreamException { var binding = getBinding(ctx, false); binding.startCollection(); @@ -222,8 +222,7 @@ void list(RequestContext ctx) throws IOException } - void getById(RequestContext ctx, String id) throws IOException - { + void getById(RequestContext ctx, String id) throws IOException, XMLStreamException { var binding = getBinding(ctx, false); var col = allCollections.get(id); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/DataStreamSchemaHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/DataStreamSchemaHandler.java index 9a228a1ace..5c1d6a93ef 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/DataStreamSchemaHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/DataStreamSchemaHandler.java @@ -33,6 +33,8 @@ import org.sensorhub.impl.service.consys.resource.RequestContext.ResourceRef; import org.vast.util.Asserts; +import javax.xml.stream.XMLStreamException; + public class DataStreamSchemaHandler extends ResourceHandler { @@ -99,8 +101,7 @@ public void doDelete(final RequestContext ctx) throws IOException @Override - public void doGet(RequestContext ctx) throws IOException - { + public void doGet(RequestContext ctx) throws IOException, XMLStreamException { if (ctx.isEndOfPath()) getById(ctx, ""); else @@ -109,8 +110,7 @@ public void doGet(RequestContext ctx) throws IOException @Override - protected void getById(final RequestContext ctx, final String id) throws IOException - { + protected void getById(final RequestContext ctx, final String id) throws IOException, XMLStreamException { // check permissions var parentId = ctx.getParentRef().id; ctx.getSecurityHandler().checkParentPermission(permissions.get, parentId); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java index 97a9e8d475..ff902c17d0 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -173,7 +173,6 @@ else if ("foi@id".equals(propName)) { obs.withResult((DataBlock) dataRec); } } - } } catch (DateTimeParseException e) diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingGeoJson.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingGeoJson.java new file mode 100644 index 0000000000..4e132d2451 --- /dev/null +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingGeoJson.java @@ -0,0 +1,322 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + +The contents of this file are subject to the Mozilla Public License, v. 2.0. +If a copy of the MPL was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +Copyright (C) 2020 Sensia Software LLC. All Rights Reserved. + +******************************* END LICENSE BLOCK ***************************/ + +package org.sensorhub.impl.service.consys.obs; + +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import org.sensorhub.api.common.BigId; +import org.sensorhub.api.common.IdEncoders; +import org.sensorhub.api.data.IDataStreamInfo; +import org.sensorhub.api.data.IObsData; +import org.sensorhub.api.data.ObsData; +import org.sensorhub.api.datastore.obs.DataStreamKey; +import org.sensorhub.api.datastore.obs.IObsStore; +import org.sensorhub.impl.service.consys.ResourceParseException; +import org.sensorhub.impl.service.consys.SWECommonUtils; +import org.sensorhub.impl.service.consys.ServiceErrors; +import org.sensorhub.impl.service.consys.obs.ObsHandler.ObsHandlerContextData; +import org.sensorhub.impl.service.consys.resource.PropertyFilter; +import org.sensorhub.impl.service.consys.resource.RequestContext; +import org.sensorhub.impl.service.consys.resource.ResourceBindingJson; +import org.sensorhub.impl.service.consys.resource.ResourceLink; +import org.sensorhub.utils.SWEDataUtils; +import org.sensorhub.api.datastore.feature.IFoiStore; +import org.vast.data.DataBlockMixed; +import org.vast.ogc.gml.IFeature; + +import org.vast.cdm.common.DataStreamWriter; +import org.vast.swe.BinaryDataWriter; +import org.vast.swe.SWEConstants; +import org.vast.swe.ScalarIndexer; +import org.vast.swe.fast.JsonDataParserGson; +import org.vast.swe.fast.JsonDataWriterGson; +import org.vast.swe.helper.GeoPosHelper; +import org.vast.util.ReaderException; + +import java.io.IOException; +import java.io.OutputStream; +import java.time.OffsetDateTime; +import java.time.format.DateTimeParseException; +import java.util.*; + +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.Point; +import org.locationtech.jts.geom.Coordinate; + +import org.sensorhub.api.datastore.EmptyFilterIntersection; +import com.google.common.collect.Sets; + + +import static org.sensorhub.impl.service.consys.SWECommonUtils.OM_COMPONENTS_FILTER; + + +public class ObsBindingGeoJson extends ResourceBindingJson +{ + ObsHandlerContextData contextData; + IObsStore obsStore; + JsonDataParserGson resultReader; + Map resultWriters; + ScalarIndexer timeStampIndexer; + + IFoiStore foiStore; + + private static final Set LOCATION_DEFINITIONS = Sets.newHashSet( + SWEConstants.DEF_SENSOR_LOC, + SWEConstants.DEF_PLATFORM_LOC, + SWEConstants.DEF_SAMPLING_LOC, + GeoPosHelper.DEF_LOCATION + ); + + + public ObsBindingGeoJson(RequestContext ctx, IdEncoders idEncoders, boolean forReading, IObsStore obsStore) throws IOException + { + super(ctx, idEncoders, forReading); + this.contextData = (ObsHandlerContextData)ctx.getData(); + this.obsStore = obsStore; + + if (forReading) + { + resultReader = getSweCommonParser(contextData.dsInfo, reader); + resultReader.setRenewDataBlock(true); + timeStampIndexer = SWEDataUtils.getTimeStampIndexer(contextData.dsInfo.getRecordStructure()); + } + else + { + this.resultWriters = new HashMap<>(); + + // init result writer only in case of single datastream + // otherwise we'll do it later + if (contextData != null && contextData.dsInfo != null) + { + var resultWriter = getSweCommonWriter(contextData.dsInfo, writer, ctx.getPropertyFilter()); + resultWriters.put(ctx.getParentID(), resultWriter); + } + } + } + + + @Override + public IObsData deserialize(JsonReader reader) throws IOException + { + // if array, prepare to parse first element + if (reader.peek() == JsonToken.BEGIN_ARRAY) + reader.beginArray(); + + if (reader.peek() == JsonToken.END_DOCUMENT || !reader.hasNext()) + return null; + + var obs = new ObsData.Builder() + .withDataStream(contextData.dsID); + + try + { + reader.beginObject(); + + while (reader.hasNext()) + { + var propName = reader.nextName(); + + if ("phenomenonTime".equals(propName)) + obs.withPhenomenonTime(OffsetDateTime.parse(reader.nextString()).toInstant()); + else if ("resultTime".equals(propName)) + obs.withResultTime(OffsetDateTime.parse(reader.nextString()).toInstant()); + else if ("foi@id".equals(propName)) + { + try + { + var foiID = idEncoders.getFoiIdEncoder().decodeID(reader.nextString()); + obs.withFoi(foiID); + } + catch (IllegalArgumentException e) + { + throw ServiceErrors.badRequest("Invalid FOI ID"); + } + } + else if ("result".equals(propName)) + { + var result = resultReader.parseNextBlock(); + obs.withResult(result); + } + else + reader.skipValue(); + } + + reader.endObject(); + } + catch (DateTimeParseException e) + { + throw new ResourceParseException(INVALID_JSON_ERROR_MSG + "Invalid ISO8601 date/time at " + reader.getPath()); + } + catch (IllegalStateException | ReaderException e) + { + throw new ResourceParseException(INVALID_JSON_ERROR_MSG + e.getMessage()); + } + + if (contextData.foiId != null && contextData.foiId != BigId.NONE) + obs.withFoi(contextData.foiId); + + var newObs = obs.build(); + + // set timestamp in result data if present in schema + if (timeStampIndexer != null) + { + var phenomenonTimeIdx = timeStampIndexer.getDataIndex(newObs.getResult()); + newObs.getResult().setDoubleValue(phenomenonTimeIdx, newObs.getPhenomenonTime().toEpochMilli() / 1000.0); + } + + return newObs; + } + + // only shows anything if theres any lon/lat data + @Override + public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter writer) throws IOException { + + Set locationComponents = new HashSet<>(); + + var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); + for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { + var component = dataStream.getRecordStructure().getComponent(i); + if (LOCATION_DEFINITIONS.contains(component.getDefinition())) { + // This is how we know we have location components in the data structure + // So we can save this and parse specifically the location components into GeoJSON + locationComponents.add(i); + } + } + + double altitude = 0; + double longitude = 0; + double latitude = 0; + + for (int index : locationComponents) { + var locationDataBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject()[index]; + // You'll still need to check if these are real values and not null + latitude = locationDataBlock.getDoubleValue(0); + longitude = locationDataBlock.getDoubleValue(1); + altitude = locationDataBlock.getDoubleValue(2); //geojson format doesnt seem to have alt :? + } + + var obsId = idEncoders.getObsIdEncoder().encodeID(key); + + var resultWriter = resultWriters.computeIfAbsent(obs.getDataStreamID(), + k -> getSweCommonWriter(k, writer, ctx.getPropertyFilter()) ); + + var obsRes = obs.getResult().toString(); + + var obsName = dataStream.getOutputName(); + + if (!(longitude == 0.0 && latitude == 0.0)) { + writer.beginObject(); + writer.name("type").value("Feature"); + + writer.name("geometry"); + writer.beginObject(); + writer.name("type").value("Point"); + + writer.name("coordinates").value("[" + longitude + ", " + latitude + "]"); + + + writer.name("properties"); + // name, id, timestamp, whatever else + + writer.beginObject(); + writer.name("name").value(obsName); + writer.name("id").value(obsId); + writer.name("phenomenonTime").value(obs.getPhenomenonTime().toString()); + writer.name("resultTime").value(obs.getResultTime().toString()); + + // write if JSON is supported, otherwise print warning message +// if (resultWriter instanceof JsonDataWriterGson) +// resultWriter.write(obs.getResult()); +// else +// writer.value("Compressed binary result not shown in JSON"); + + writer.endObject(); + writer.endObject(); + writer.endObject(); + writer.flush(); + } + } + + + protected JsonWriter getJsonWriter(OutputStream os, PropertyFilter propFilter) throws IOException + { + var writer = super.getJsonWriter(os, propFilter); + writer.setSerializeNulls(true); + return writer; + } + + + protected DataStreamWriter getSweCommonWriter(BigId dsID, JsonWriter writer, PropertyFilter propFilter) + { + var dsInfo = obsStore.getDataStreams().get(new DataStreamKey(dsID)); + return getSweCommonWriter(dsInfo, writer, propFilter); + } + + + protected DataStreamWriter getSweCommonWriter(IDataStreamInfo dsInfo, JsonWriter writer, PropertyFilter propFilter) + { + if (!SWECommonUtils.allowNonBinaryFormat(dsInfo.getRecordStructure(), dsInfo.getRecordEncoding())) + return new BinaryDataWriter(); + + // create JSON SWE writer + var sweWriter = new JsonDataWriterGson(writer); + sweWriter.setDataComponents(dsInfo.getRecordStructure()); + + // filter out components that are already included in O&M + sweWriter.setDataComponentFilter(OM_COMPONENTS_FILTER); + return sweWriter; + } + + + protected JsonDataParserGson getSweCommonParser(IDataStreamInfo dsInfo, JsonReader reader) + { + // create JSON SWE parser + var sweParser = new JsonDataParserGson(reader); + sweParser.setDataComponents(dsInfo.getRecordStructure()); + + // filter out components that are already included in O&M + sweParser.setDataComponentFilter(OM_COMPONENTS_FILTER); + return sweParser; + } + + + @Override + public void startCollection() throws IOException + { + if (reader != null) { + // if we're reading, just skip to the items array + // calls to deserialize() will take it from there + // TODO generalize this to all bindings + reader.beginObject(); + while (reader.hasNext()) { + var propName = reader.nextName(); + if (propName.equals(getItemsPropertyName())) + return; + else + reader.skipValue(); + } + } + else + startJsonCollection(writer); + } + + + @Override + public void endCollection(Collection links) throws IOException + { + endJsonCollection(writer, links); + } +} diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java index f9963930c2..801ef2890c 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java @@ -54,6 +54,8 @@ import com.google.common.base.Objects; import net.opengis.swe.v20.BinaryEncoding; +import javax.xml.stream.XMLStreamException; + public class ObsHandler extends BaseResourceHandler { @@ -89,8 +91,7 @@ public ObsHandler(IEventBus eventBus, ObsSystemDbWrapper db, ScheduledExecutorSe @Override - protected ResourceBinding getBinding(RequestContext ctx, boolean forReading) throws IOException - { + protected ResourceBinding getBinding(RequestContext ctx, boolean forReading) throws IOException, XMLStreamException { var contextData = new ObsHandlerContextData(); ctx.setData(contextData); @@ -144,9 +145,13 @@ protected ResourceBinding getBinding(RequestContext ctx, boolea format = ResourceFormat.JSON; ctx.setFormat(format); } - + if (format.isOneOf(ResourceFormat.JSON, ResourceFormat.OM_JSON)) return new ObsBindingOmJson(ctx, idEncoders, forReading, dataStore); + else if (format.equals(ResourceFormat.GEO_JSON)) + return new ObsBindingGeoJson(ctx, idEncoders, forReading, dataStore); + else if (format.equals(ResourceFormat.COT_XML)) + return new ObsBindingCotXml(ctx, idEncoders, forReading, dataStore); else return new ObsBindingSweCommon(ctx, idEncoders, forReading, dataStore); } @@ -253,7 +258,7 @@ protected void subscribe(final RequestContext ctx) throws InvalidRequestExceptio else startReplayStream(ctx, dsID, filter, replaySpeed, binding); } - catch (IOException e) + catch (IOException | XMLStreamException e) { throw new IllegalStateException("Error initializing binding", e); } @@ -329,6 +334,8 @@ protected void sendObs(IObsData obs) { subscription.cancel(); throw new CallbackException(e); + } catch (XMLStreamException e) { + throw new RuntimeException(e); } } @@ -435,7 +442,7 @@ protected void startReplayStream(final RequestContext ctx, final BigId dsID, fin ctx.getLogger().debug("Ending obs replay stream #{}", System.identityHashCode(streamHandler)); } } - catch (IOException e) + catch (IOException | XMLStreamException e) { throw new CompletionException(e); } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsStatsHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsStatsHandler.java index e5620fed5d..aa49f65903 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsStatsHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsStatsHandler.java @@ -37,6 +37,8 @@ import org.sensorhub.impl.service.consys.resource.RequestContext.ResourceRef; import org.sensorhub.impl.system.DataStreamTransactionHandler; +import javax.xml.stream.XMLStreamException; + public class ObsStatsHandler extends BaseHandler { @@ -76,8 +78,7 @@ protected ResourceBinding getBinding(RequestContext ctx) throws @Override - public void doGet(final RequestContext ctx) throws IOException - { + public void doGet(final RequestContext ctx) throws IOException, XMLStreamException { // check permissions var parentId = ctx.getParentRef().id; ctx.getSecurityHandler().checkParentPermission(permissions.get, parentId); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java index 93fa8048d3..928c4b479e 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java @@ -39,6 +39,8 @@ import org.sensorhub.impl.service.consys.resource.RequestContext.ResourceRef; import org.vast.util.Asserts; +import javax.xml.stream.XMLStreamException; + /** *

@@ -77,7 +79,7 @@ protected BaseResourceHandler(S dataStore, IdEncoder idEncoder, IdEncoders allId } - protected abstract ResourceBinding getBinding(RequestContext ctx, boolean forReading) throws IOException; + protected abstract ResourceBinding getBinding(RequestContext ctx, boolean forReading) throws IOException, XMLStreamException; protected abstract K getKey(final RequestContext ctx, final String id) throws InvalidRequestException; protected abstract String encodeKey(final RequestContext ctx, K key); protected abstract F getFilter(final ResourceRef parent, final Map queryParams, long offset, long limit) throws InvalidRequestException; @@ -86,8 +88,7 @@ protected BaseResourceHandler(S dataStore, IdEncoder idEncoder, IdEncoders allId @Override - public void doGet(final RequestContext ctx) throws IOException - { + public void doGet(final RequestContext ctx) throws IOException, XMLStreamException { // if requesting from this resource collection if (ctx.isEndOfPath()) { @@ -201,8 +202,7 @@ protected void subscribeToEvents(final RequestContext ctx) throws IOException } - protected void getById(final RequestContext ctx, final String id) throws IOException - { + protected void getById(final RequestContext ctx, final String id) throws IOException, XMLStreamException { // check permissions ctx.getSecurityHandler().checkResourcePermission(permissions.get, id); @@ -215,8 +215,7 @@ protected void getById(final RequestContext ctx, final String id) throws IOExcep } - protected void getByKey(final RequestContext ctx, K key) throws IOException - { + protected void getByKey(final RequestContext ctx, K key) throws IOException, XMLStreamException { // fetch from data store final V res = dataStore.get(key); if (res != null) @@ -237,8 +236,7 @@ protected void getByKey(final RequestContext ctx, K key) throws IOException } - protected void list(final RequestContext ctx) throws IOException - { + protected void list(final RequestContext ctx) throws IOException, XMLStreamException { // check permissions var parentId = ctx.getParentRef().id; ctx.getSecurityHandler().checkParentPermission(permissions.list, parentId); @@ -348,8 +346,10 @@ protected void create(final RequestContext ctx) throws IOException catch (DataStoreException e) { throw ServiceErrors.requestRejected("Ingest Error: " + e.getMessage()); + } catch (XMLStreamException e) { + throw new RuntimeException(e); } - + if (count == 0) throw ServiceErrors.invalidPayload("No data provided"); } @@ -397,7 +397,7 @@ protected void update(final RequestContext ctx, final String id) throws IOExcept validate(res); } - catch (ResourceParseException e) + catch (ResourceParseException | XMLStreamException e) { throw ServiceErrors.invalidPayload("Invalid payload: " + e.getMessage()); } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/IResourceHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/IResourceHandler.java index 3d481fd633..674d4086c2 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/IResourceHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/IResourceHandler.java @@ -17,6 +17,8 @@ import java.io.IOException; import org.sensorhub.impl.service.consys.InvalidRequestException; +import javax.xml.stream.XMLStreamException; + public interface IResourceHandler { @@ -24,7 +26,7 @@ public interface IResourceHandler String[] getNames(); - void doGet(RequestContext ctx) throws InvalidRequestException, IOException, SecurityException; + void doGet(RequestContext ctx) throws InvalidRequestException, IOException, SecurityException, XMLStreamException; void doPost(RequestContext ctx) throws InvalidRequestException, IOException, SecurityException; diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java index 352e6424f4..eafc071924 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java @@ -28,6 +28,8 @@ public class ResourceFormat public static String SHORT_SMLJSON = "sml3"; public static String SHORT_SMLXML = "sml2"; public static String SHORT_HTML = "html"; + private static String SHORT_GEO_JSON = "geo_json"; + public static String SHORT_COTXML = "cot"; public static ResourceFormat HTML = new ResourceFormat("text/html", SHORT_HTML); public static ResourceFormat JSON = new ResourceFormat("application/json", SHORT_JSON); @@ -35,7 +37,13 @@ public class ResourceFormat public static ResourceFormat SML_JSON = new ResourceFormat("application/sml+json", SHORT_SMLJSON); public static ResourceFormat SML_XML = new ResourceFormat("application/sml+xml", SHORT_SMLXML); - + + //BOW + public static ResourceFormat GEO_JSON = new ResourceFormat("application/geo+json", SHORT_GEO_JSON); + + //BOW (again) + public static ResourceFormat COT_XML = new ResourceFormat("application/cot+xml", SHORT_COTXML); + public static ResourceFormat OM_JSON = new ResourceFormat("application/om+json", SHORT_JSON); public static ResourceFormat OM_XML = new ResourceFormat("application/om+xml"); @@ -72,10 +80,14 @@ public static ResourceFormat fromShortName(String format) return ResourceFormat.JSON; else if (SHORT_GEOJSON.equals(format)) return ResourceFormat.GEOJSON; + else if (SHORT_GEO_JSON.equals(format)) + return ResourceFormat.GEO_JSON; else if (SHORT_SMLJSON.equals(format)) return ResourceFormat.SML_JSON; else if (SHORT_SMLXML.equals(format)) return ResourceFormat.SML_XML; + else if (SHORT_COTXML.equals(format)) + return ResourceFormat.COT_XML; else if (SHORT_HTML.equals(format)) return ResourceFormat.HTML; else diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandHandler.java index 43d1443617..0455aa913b 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandHandler.java @@ -57,6 +57,8 @@ import org.sensorhub.utils.CallbackException; import org.vast.util.Asserts; +import javax.xml.stream.XMLStreamException; + public class CommandHandler extends BaseResourceHandler { @@ -249,6 +251,8 @@ public void onNext(CommandEvent event) { subscription.cancel(); throw new CallbackException(e); + } catch (XMLStreamException e) { + throw new RuntimeException(e); } } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStatusHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStatusHandler.java index 97a3917ffc..bd19419490 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStatusHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStatusHandler.java @@ -48,6 +48,8 @@ import org.sensorhub.utils.CallbackException; import org.vast.util.Asserts; +import javax.xml.stream.XMLStreamException; + public class CommandStatusHandler extends BaseResourceHandler { @@ -195,6 +197,8 @@ public void onNext(CommandStatusEvent event) { subscription.cancel(); throw new CallbackException(e); + } catch (XMLStreamException e) { + throw new RuntimeException(e); } } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamSchemaHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamSchemaHandler.java index 0ac1383f6d..fce75e9a51 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamSchemaHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamSchemaHandler.java @@ -33,6 +33,8 @@ import org.sensorhub.impl.service.consys.resource.RequestContext.ResourceRef; import org.vast.util.Asserts; +import javax.xml.stream.XMLStreamException; + public class CommandStreamSchemaHandler extends ResourceHandler { @@ -97,8 +99,7 @@ public void doDelete(final RequestContext ctx) throws IOException @Override - public void doGet(RequestContext ctx) throws IOException - { + public void doGet(RequestContext ctx) throws IOException, XMLStreamException { if (ctx.isEndOfPath()) getById(ctx, ""); else @@ -107,8 +108,7 @@ public void doGet(RequestContext ctx) throws IOException @Override - protected void getById(final RequestContext ctx, final String id) throws IOException - { + protected void getById(final RequestContext ctx, final String id) throws IOException, XMLStreamException { // check permissions var parentId = ctx.getParentRef().id; ctx.getSecurityHandler().checkParentPermission(permissions.get, parentId); From 0903ec08b7e8fa9811d18a0a16e3ae2837266e52 Mon Sep 17 00:00:00 2001 From: ashley Date: Wed, 14 Jan 2026 11:12:54 -0600 Subject: [PATCH 05/15] updating cot serializer --- .../java/org/vast/swe/fast/CotDataReader.java | 229 +-------------- .../java/org/vast/swe/fast/CotDataWriter.java | 190 ++---------- .../java/org/vast/swe/fast/XmlDataWriter.java | 2 +- .../service/consys/obs/ObsBindingCotXml.java | 276 +++++++++++------- .../resource/ResourceBindingCotXml.java | 60 ++-- 5 files changed, 228 insertions(+), 529 deletions(-) diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java index 30493ecd5a..c0f6f8a1c1 100644 --- a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java @@ -35,7 +35,6 @@ import java.util.Map; import java.util.Objects; - /** *

* New implementation of XML data writer with better efficiency since the @@ -46,11 +45,14 @@ * @author Ashley Poteau * @since Dec 2, 2025 */ + // xmlstreamreader -public class CotDataReader implements XMLStreamReader { +// or xmldataparser? +public class CotDataReader extends XmlDataParser { static final String COT_ERROR = "Error writing XML stream for "; private final Reader in; + protected XMLStreamReader xmlReader; protected XMLStreamWriter xmlWriter; protected String namespace; protected String prefix; @@ -67,229 +69,6 @@ public class CotDataReader implements XMLStreamReader { public CotDataReader(Reader in) { this.in = Objects.requireNonNull(in, "in == null"); } - - @Override - public Object getProperty(String s) throws IllegalArgumentException { - return null; - } - - @Override - public int next() throws XMLStreamException { - return 0; - } - - @Override - public void require(int i, String s, String s1) throws XMLStreamException { - - } - - @Override - public String getElementText() throws XMLStreamException { - return ""; - } - - @Override - public int nextTag() throws XMLStreamException { - return 0; - } - - @Override - public boolean hasNext() throws XMLStreamException { - return false; - } - - @Override - public void close() throws XMLStreamException { - - } - - @Override - public String getNamespaceURI(String s) { - return ""; - } - - @Override - public boolean isStartElement() { - return false; - } - - @Override - public boolean isEndElement() { - return false; - } - @Override - public boolean isCharacters() { - return false; - } - - @Override - public boolean isWhiteSpace() { - return false; - } - - @Override - public String getAttributeValue(String s, String s1) { - return ""; - } - - @Override - public int getAttributeCount() { - return 0; - } - - @Override - public QName getAttributeName(int i) { - return null; - } - - @Override - public String getAttributeNamespace(int i) { - return ""; - } - - @Override - public String getAttributeLocalName(int i) { - return ""; - } - - @Override - public String getAttributePrefix(int i) { - return ""; - } - - @Override - public String getAttributeType(int i) { - return ""; - } - - @Override - public String getAttributeValue(int i) { - return ""; - } - - @Override - public boolean isAttributeSpecified(int i) { - return false; - } - - @Override - public int getNamespaceCount() { - return 0; - } - @Override - public String getNamespacePrefix(int i) { - return ""; - } - - @Override - public String getNamespaceURI(int i) { - return ""; - } - - @Override - public NamespaceContext getNamespaceContext() { - return null; - } - - @Override - public int getEventType() { - return 0; - } - - @Override - public String getText() { - return ""; - } - - @Override - public char[] getTextCharacters() { - return new char[0]; - } - - @Override - public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { - return 0; - } - - @Override - public int getTextStart() { - return 0; - } - - @Override - public int getTextLength() { - return 0; - } - - @Override - public String getEncoding() { - return ""; - } - - @Override - public boolean hasText() { - return false; - } - - @Override - public Location getLocation() { - return null; - } - - @Override - public QName getName() { - return null; - } - - @Override - public String getLocalName() { - return ""; - } - - @Override - public boolean hasName() { - return false; - } - - @Override - public String getNamespaceURI() { - return ""; - } - - @Override - public String getPrefix() { - return ""; - } - - @Override - public String getVersion() { - return ""; - } - - @Override - public boolean isStandalone() { - return false; - } - - @Override - public boolean standaloneSet() { - return false; - } - - @Override - public String getCharacterEncodingScheme() { - return ""; - } - - @Override - public String getPITarget() { - return ""; - } - - @Override - public String getPIData() { - return ""; - } } diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java index 1735041ddd..2b63401628 100644 --- a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java @@ -48,7 +48,8 @@ * @since Oct 31, 2025 */ // xmlstreamwriter -public class CotDataWriter implements XMLStreamWriter { +// xmldatawriter? +public class CotDataWriter extends XmlDataWriter { static final String COT_ERROR = "Error writing XML stream for "; protected XMLStreamWriter xmlWriter; @@ -64,6 +65,32 @@ public class CotDataWriter implements XMLStreamWriter { private String formattedComma; private boolean usesEmptyNewlineAndIndent; + + public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException { + xmlWriter.writeStartElement(namespaceURI, localName); + } + + public void writeCotCharacters(String text) throws XMLStreamException { + if (xmlWriter == null) { + throw new IllegalStateException("XMLStreamWriter not initialized. Call setOutput() first."); + } + xmlWriter.writeCharacters(text); + } + + public void writeCotStartElement(String text) throws XMLStreamException { + if (xmlWriter == null) { + throw new IllegalStateException("XMLStreamWriter not initialized. Call setOutput() first."); + } + xmlWriter.writeStartElement(text); + } + + public void writeCotAttribute(String var1, String var2) throws XMLStreamException { + if (xmlWriter == null) { + throw new IllegalStateException("XMLStreamWriter not initialized. Call setOutput() first."); + } + xmlWriter.writeAttribute(var1, var2); + } + public final void setStrictness(Strictness strictness) { this.strictness = Objects.requireNonNull(strictness); } @@ -104,6 +131,7 @@ public final void setFormattingStyle(FormattingStyle formattingStyle) { this.formattingStyle.getNewline().isEmpty() && this.formattingStyle.getIndent().isEmpty(); } + public final void setIndent(String indent) { if (indent.isEmpty()) { setFormattingStyle(FormattingStyle.COMPACT); @@ -112,164 +140,4 @@ public final void setIndent(String indent) { } } - @Override - public void writeStartElement(String s) throws XMLStreamException { - - } - - @Override - public void writeStartElement(String s, String s1) throws XMLStreamException { - - } - - @Override - public void writeStartElement(String s, String s1, String s2) throws XMLStreamException { - - } - - @Override - public void writeEmptyElement(String s, String s1) throws XMLStreamException { - - } - - @Override - public void writeEmptyElement(String s, String s1, String s2) throws XMLStreamException { - - } - - @Override - public void writeEmptyElement(String s) throws XMLStreamException { - - } - - @Override - public void writeEndElement() throws XMLStreamException { - - } - - @Override - public void writeEndDocument() throws XMLStreamException { - - } - - @Override - public void close() throws XMLStreamException { - - } - - @Override - public void flush() throws XMLStreamException { - - } - - @Override - public void writeAttribute(String s, String s1) throws XMLStreamException { - - } - - @Override - public void writeAttribute(String s, String s1, String s2, String s3) throws XMLStreamException { - - } - - @Override - public void writeAttribute(String s, String s1, String s2) throws XMLStreamException { - - } - - @Override - public void writeNamespace(String s, String s1) throws XMLStreamException { - - } - - @Override - public void writeDefaultNamespace(String s) throws XMLStreamException { - - } - - @Override - public void writeComment(String s) throws XMLStreamException { - - } - - @Override - public void writeProcessingInstruction(String s) throws XMLStreamException { - - } - - @Override - public void writeProcessingInstruction(String s, String s1) throws XMLStreamException { - - } - - @Override - public void writeCData(String s) throws XMLStreamException { - - } - - @Override - public void writeDTD(String s) throws XMLStreamException { - - } - - @Override - public void writeEntityRef(String s) throws XMLStreamException { - - } - - @Override - public void writeStartDocument() throws XMLStreamException { - - } - - @Override - public void writeStartDocument(String s) throws XMLStreamException { - - } - - @Override - public void writeStartDocument(String s, String s1) throws XMLStreamException { - - } - - @Override - public void writeCharacters(String s) throws XMLStreamException { - - } - - @Override - public void writeCharacters(char[] chars, int i, int i1) throws XMLStreamException { - - } - - @Override - public String getPrefix(String s) throws XMLStreamException { - return ""; - } - - @Override - public void setPrefix(String s, String s1) throws XMLStreamException { - - } - - @Override - public void setDefaultNamespace(String s) throws XMLStreamException { - - } - - @Override - public void setNamespaceContext(NamespaceContext namespaceContext) throws XMLStreamException { - - } - - @Override - public NamespaceContext getNamespaceContext() { - return null; - } - - @Override - public Object getProperty(String s) throws IllegalArgumentException { - return null; - } - } diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/XmlDataWriter.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/XmlDataWriter.java index bb58502b7e..18171b9fb8 100644 --- a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/XmlDataWriter.java +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/XmlDataWriter.java @@ -322,7 +322,7 @@ public int process(DataBlock data, int index) throws IOException } - protected void writeStartElement(String eltName) throws XMLStreamException + public void writeStartElement(String eltName) throws XMLStreamException { if (namespace != null) { diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java index ff902c17d0..aa57277c5c 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -34,7 +34,9 @@ import org.sensorhub.impl.service.consys.resource.*; import org.sensorhub.utils.SWEDataUtils; import org.vast.cdm.common.DataStreamWriter; +import org.vast.data.AbstractDataBlock; import org.vast.data.DataBlockMixed; +import org.vast.data.DataRecordImpl; import org.vast.data.XMLEncodingImpl; import org.vast.swe.BinaryDataWriter; import org.vast.swe.SWEConstants; @@ -72,7 +74,7 @@ public class ObsBindingCotXml extends ResourceBindingCotXml DOMHelper dom; ScalarIndexer timeStampIndexer; XMLOutputFactory factory = XMLOutputFactory.newInstance(); - OutputStream os; + OutputStream os = ctx.getOutputStream(); IFoiStore foiStore; protected DataRecord dataRec; @@ -116,96 +118,104 @@ protected ObsBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boolean fo public IObsData deserialize(CotDataReader xmlReader) throws IOException { var obs = new ObsData.Builder() .withDataStream(contextData.dsID); - - CoTHelper fac = new CoTHelper(); - - String vers = "2.0"; - - dataRec = (DataRecord) fac.createRecord() - .label("") - .addField("version", fac.createCoTVersion()) - .addField("type", fac.createType()) - .addField("uid", fac.createUID()) - .addField("time", fac.createPrecisionTimeStamp()) - .addField("start-time", fac.createStartTime()) - .addField("stale-time", fac.createStaleTime()) - .addField("how", fac.createHow()) - .label("") - .label("") - .addField("lat", fac.createLatitude()) - .addField("lon", fac.createLongitude()) - .addField("ce", fac.createCE()) - // hae here?..... - .addField("le", fac.createLE()) - .label("") - .label("") - // - .label("") - .addField("source", fac.createRmkSrc()) - .addField("time", fac.createPrecisionTimeStamp()) - .label("") - .label(""); - - try { - while (xmlReader.hasNext()) { - xmlReader.next(); - - //var propName = reader.nextName(); - - if (xmlReader.isStartElement()) { - String propName = xmlReader.getLocalName(); - - if ("phenomenonTime".equals(propName)) - obs.withPhenomenonTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); - else if ("resultTime".equals(propName)) - obs.withResultTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); - else if ("foi@id".equals(propName)) { - try { - var foiID = idEncoders.getFoiIdEncoder().decodeID(xmlReader.getElementText()); - obs.withFoi(foiID); - } catch (IllegalArgumentException e) { - throw ServiceErrors.badRequest("Invalid FOI ID"); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - } else if ("result".equals(propName)) { - var result = xmlReader.next(); - obs.withResult((DataBlock) dataRec); - } - } - } - } - catch (DateTimeParseException e) - { - throw new ResourceParseException(INVALID_XML_ERROR_MSG + "Invalid ISO8601 date/time at " + xmlReader.getLocalName()); - } - catch (IllegalStateException e) - { - throw new ResourceParseException(INVALID_XML_ERROR_MSG + e.getMessage()); - } catch (XMLStreamException e) { - throw new RuntimeException(e); - } - - if (contextData.foiId != null && contextData.foiId != BigId.NONE) - obs.withFoi(contextData.foiId); - var newObs = obs.build(); - - // set timestamp in result data if present in schema - if (timeStampIndexer != null) - { - var phenomenonTimeIdx = timeStampIndexer.getDataIndex(newObs.getResult()); - newObs.getResult().setDoubleValue(phenomenonTimeIdx, newObs.getPhenomenonTime().toEpochMilli() / 1000.0); - } - return newObs; } +// @Override +// public IObsData deserialize(CotDataReader xmlReader) throws IOException { +// var obs = new ObsData.Builder() +// .withDataStream(contextData.dsID); +// +// CoTHelper fac = new CoTHelper(); +// +// String vers = "2.0"; +// +// dataRec = (DataRecord) fac.createRecord() +// .label("") +// .addField("version", fac.createCoTVersion()) +// .addField("type", fac.createType()) +// .addField("uid", fac.createUID()) +// .addField("time", fac.createPrecisionTimeStamp()) +// .addField("start-time", fac.createStartTime()) +// .addField("stale-time", fac.createStaleTime()) +// .addField("how", fac.createHow()) +// .label("") +// .label("") +// .addField("lat", fac.createLatitude()) +// .addField("lon", fac.createLongitude()) +// .addField("ce", fac.createCE()) +// // hae here?..... +// .addField("le", fac.createLE()) +// .label("") +// .label("") +// // +// .label("") +// .addField("source", fac.createRmkSrc()) +// .addField("time", fac.createPrecisionTimeStamp()) +// .label("") +// .label(""); +// +//// try { +//// while (xmlReader.hasNext()) { +//// xmlReader.next(); +//// +//// //var propName = reader.nextName(); +//// +//// if (xmlReader.isStartElement()) { +//// String propName = xmlReader.getLocalName(); +//// +//// if ("phenomenonTime".equals(propName)) +//// obs.withPhenomenonTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); +//// else if ("resultTime".equals(propName)) +//// obs.withResultTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); +//// else if ("foi@id".equals(propName)) { +//// try { +//// var foiID = idEncoders.getFoiIdEncoder().decodeID(xmlReader.getElementText()); +//// obs.withFoi(foiID); +//// } catch (IllegalArgumentException e) { +//// throw ServiceErrors.badRequest("Invalid FOI ID"); +//// } catch (XMLStreamException e) { +//// throw new RuntimeException(e); +//// } +//// } else if ("result".equals(propName)) { +//// //var result = xmlReader.next(); +//// obs.withResult((DataBlock) dataRec); +//// } +//// } +//// } +//// } +//// catch (DateTimeParseException e) +//// { +//// throw new ResourceParseException(INVALID_XML_ERROR_MSG + "Invalid ISO8601 date/time at " + xmlReader.getLocalName()); +//// } +//// catch (IllegalStateException e) +//// { +//// throw new ResourceParseException(INVALID_XML_ERROR_MSG + e.getMessage()); +//// } catch (XMLStreamException e) { +//// throw new RuntimeException(e); +//// } +// +// if (contextData.foiId != null && contextData.foiId != BigId.NONE) +// obs.withFoi(contextData.foiId); +// +// var newObs = obs.build(); +// +// // set timestamp in result data if present in schema +// if (timeStampIndexer != null) +// { +// var phenomenonTimeIdx = timeStampIndexer.getDataIndex(newObs.getResult()); +// newObs.getResult().setDoubleValue(phenomenonTimeIdx, newObs.getPhenomenonTime().toEpochMilli() / 1000.0); +// } +// +// return newObs; +// } + @Override public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter xmlWriter) throws IOException, XMLStreamException { Set locationComponents = new HashSet<>(); - var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); + for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { var component = dataStream.getRecordStructure().getComponent(i); if (LOCATION_DEFINITIONS.contains(component.getDefinition())) { @@ -215,6 +225,14 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter } } + var obsId = idEncoders.getObsIdEncoder().encodeID(key); + + xmlWriter.setOutput(os); + + xmlWriter.writeStartElement("event"); + xmlWriter.writeCotAttribute("version", "2.0"); + xmlWriter.writeCotAttribute("uid", obsId); + double longitude = 0; double latitude = 0; @@ -225,23 +243,69 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter longitude = locationDataBlock.getDoubleValue(1); } - var obsId = idEncoders.getObsIdEncoder().encodeID(key); - - var obsName = dataStream.getOutputName(); + var recordStruct = ((DataRecordImpl) dataStream.getRecordStructure()).getFieldList(); + + var resultBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject(); + + cotWriter.writeCotStartElement("event"); + + int i = 0; + + for (AbstractDataBlock abstractResultBlock : resultBlock) { + String value = abstractResultBlock.getStringValue(); + String fieldName = recordStruct.get(i).getName(); + + OffsetDateTime timeResult = null; + + switch (fieldName) { + case "version": + cotWriter.writeCotAttribute("version", value); + break; + case "type": + cotWriter.writeCotAttribute("type", value); + break; + case "uid": + cotWriter.writeCotAttribute("uid", value); + break; + case "time": + timeResult = abstractResultBlock.getDateTime(); + cotWriter.writeCotAttribute("time", timeResult.toString()); + break; + case "start": + timeResult = abstractResultBlock.getDateTime(); + cotWriter.writeCotAttribute("start time", timeResult.toString()); + break; + case "stale": // how would i do the plus 1 year here + timeResult = abstractResultBlock.getDateTime(); + cotWriter.writeCotAttribute("stale time", timeResult.toString()); + break; + case "how": + cotWriter.writeCotAttribute("how", value); + break; + case "lat": + cotWriter.writeCotAttribute("lon", value); + break; + case "ce": + cotWriter.writeCotAttribute("ce", value); + break; + case "le": + cotWriter.writeCotAttribute("le", value); + break; + case "source": + cotWriter.writeCotAttribute("source", value); + break; + } + } - if (!(longitude == 0.0 && latitude == 0.0)) { - factory.setProperty(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE, false); - XMLOutputFactory factory = XMLOutputFactory.newInstance(); - xmlWriter = (CotDataWriter) factory.createXMLStreamWriter(System.out); - xmlWriter.writeStartElement(""); +// if (!(longitude == 0.0 && latitude == 0.0)) { +// +// } - cotWriter.flush(); - } } - protected CotDataWriter getCotWriter(OutputStream os, PropertyFilter propFilter) throws IOException { - var writer = super.getCotWriter(os, propFilter); + protected CotDataWriter getCotWriter(OutputStream os) throws IOException { + var writer = super.getCotWriter(os); writer.setSerializeNulls(true); return writer; } @@ -264,10 +328,11 @@ protected AbstractDataWriter getSweCommonWriter(IDataStreamInfo dsInfo, OutputSt //// } // create cot/xml writer - XmlDataWriter dataWriter = new XmlDataWriter(); //wraps writer. when you return writer, + //XmlDataWriter dataWriter = new XmlDataWriter(); //wraps writer. when you return writer, // youre passing in a writer that knows how to write the specific xml data it needs. //CotWriter responsible for writing cot spec compliant info + CotDataWriter dataWriter = new CotDataWriter(); //xmlcotwriter extends xmldatawriter. new class. same with xmlcotparser and reader. convert it back into a swecommondata record that can be put in osh dataWriter.setDataEncoding(new XMLEncodingImpl()); @@ -294,25 +359,14 @@ protected XmlDataParser getSweCommonParser(IDataStreamInfo dsInfo, InputStream i return sweParser; } - @Override - public void startCollection() throws XMLStreamException { - - // if we're reading, just skip to the items array - // calls to deserialize() will take it from there - while (xmlReader.hasNext()) { - var propName = xmlReader.getLocalName(); - if (propName.equals(getItemsPropertyName())) - return; - else - xmlReader.next(); - } + public void startCollection() throws XMLStreamException, IOException { + super.startCollection(); } - @Override public void endCollection(Collection links) throws IOException, XMLStreamException { - xmlWriter.close(); - xmlWriter.flush(); + cotWriter.close(); + cotWriter.flush(); } } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java index 24d86efd4f..4b6dbe2483 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java @@ -26,6 +26,7 @@ import javax.xml.stream.XMLStreamWriter; import java.io.*; import java.nio.charset.StandardCharsets; +import java.util.Collection; import java.util.Set; @@ -48,8 +49,8 @@ public abstract class ResourceBindingCotXml extends ResourceBinding // protected final XMLStreamReader xmlReader; // protected final XMLStreamWriter xmlWriter; - protected final CotDataReader xmlReader; - protected final CotDataWriter xmlWriter; + protected final CotDataReader cotReader; + protected final CotDataWriter cotWriter; protected boolean isCollection; @@ -59,27 +60,25 @@ public abstract class ResourceBindingCotXml extends ResourceBinding protected ResourceBindingCotXml(RequestContext ctx, IdEncoders idEncoders, boolean forReading) throws IOException { super(ctx, idEncoders); - + try { if (forReading) { - var factory = XMLImplFinder.getStaxInputFactory(); var is = new BufferedInputStream(ctx.getInputStream()); - xmlReader = (CotDataReader) factory.createXMLStreamReader(is, StandardCharsets.UTF_8.name()); - xmlWriter = null; + cotReader = getCotReader(is); + cotWriter = null; } else { - var factory = XMLImplFinder.getStaxOutputFactory(); - var os = ctx.getOutputStream();//new BufferedOutputStream(ctx.getOutputStream()); - xmlWriter = (CotDataWriter) factory.createXMLStreamWriter(os, StandardCharsets.UTF_8.name()); - xmlReader = null; + var os = ctx.getOutputStream(); + cotWriter = getCotWriter(os); + cotReader = null; } } - catch (XMLStreamException e) + catch (Exception e) { - throw new IOException("Error initializing XML bindings", e); + throw new IOException("Error initializing COT XML bindings", e); } } @@ -93,44 +92,43 @@ protected CotDataReader getCotReader(InputStream is) throws IOException return new CotDataReader(osr); } - protected CotDataWriter getCotWriter(OutputStream os, PropertyFilter propFilter) throws IOException + protected CotDataWriter getCotWriter(OutputStream os) throws IOException { - CotDataWriter writer = new CotDataWriter(); - var osw = new OutputStreamWriter(os, StandardCharsets.UTF_8); - if (propFilter != null) { - this.excludedProps = propFilter.getExcludedProps(); - this.includedProps = propFilter.getIncludedProps(); + try { + CotDataWriter writer = new CotDataWriter(); + writer.setOutput(os); + return writer; + } catch (Exception e) { + throw new IOException("Error creating COT writer", e); } -// else -// writer = new JsonInliningWriter(osw); - - writer.setStrictness(Strictness.LENIENT); - writer.setSerializeNulls(false); - writer.setIndent(INDENT); - return writer; } @Override public V deserialize() throws IOException { - return deserialize(this.xmlReader); + return deserialize(this.cotReader); } @Override public void serialize(K key, V res, boolean showLinks) throws IOException, XMLStreamException { - serialize(key, res, showLinks, this.xmlWriter); + serialize(key, res, showLinks, this.cotWriter); } @Override public void startCollection() throws IOException, XMLStreamException { isCollection = true; - startXMLCollection(xmlWriter); + if (cotWriter != null) { + cotWriter.startStream(true); + } } - protected void startXMLCollection(XMLStreamWriter xmlWriter) throws XMLStreamException { - xmlWriter.writeStartElement(getItemsPropertyName()); - // xmlWriter.beginArray(); + @Override + public void endCollection(Collection links) throws IOException, XMLStreamException { + if (cotWriter != null) { + cotWriter.endStream(); + cotWriter.flush(); + } } protected String getItemsPropertyName() From c1606f8c4448dc1b1efdfdff2f2cca8c2cdb8cc3 Mon Sep 17 00:00:00 2001 From: ashley Date: Wed, 21 Jan 2026 16:55:33 -0600 Subject: [PATCH 06/15] trying to fix null variable errors --- .../impl/service/consys/obs/ObsBindingCotXml.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java index aa57277c5c..34d807b3f4 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -69,7 +69,7 @@ public class ObsBindingCotXml extends ResourceBindingCotXml IObsStore obsStore; XmlDataParser resultReader; CotDataReader cotReader; // unused... - CotDataWriter cotWriter; + CotDataWriter cotWriter = new CotDataWriter(); Map resultWriters; DOMHelper dom; ScalarIndexer timeStampIndexer; @@ -227,11 +227,11 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter var obsId = idEncoders.getObsIdEncoder().encodeID(key); - xmlWriter.setOutput(os); + cotWriter.setOutput(os); - xmlWriter.writeStartElement("event"); - xmlWriter.writeCotAttribute("version", "2.0"); - xmlWriter.writeCotAttribute("uid", obsId); + cotWriter.writeStartElement("event"); + cotWriter.writeCotAttribute("version", "2.0"); + cotWriter.writeCotAttribute("uid", obsId); double longitude = 0; double latitude = 0; From bdd73806696c689d645d7784acf04a5d27b4b510 Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 12 Mar 2026 10:13:03 -0500 Subject: [PATCH 07/15] reorganizing data into maps, fixing format/response type issues --- .../java/org/vast/swe/fast/CotDataReader.java | 8 - .../java/org/vast/swe/fast/CotDataWriter.java | 76 ++++---- .../impl/service/consys/SWECommonUtils.java | 7 +- .../service/consys/obs/ObsBindingCotXml.java | 163 +++++++++++++----- .../consys/obs/ObsBindingSweCommon.java | 2 + .../consys/resource/BaseResourceHandler.java | 8 +- .../resource/ResourceBindingCotXml.java | 5 - .../consys/task/CommandBindingSweCommon.java | 2 + .../task/CommandResultBindingSweCommon.java | 2 + .../consys/task/CommandStreamBindingJson.java | 1 + 10 files changed, 178 insertions(+), 96 deletions(-) diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java index c0f6f8a1c1..551e717db9 100644 --- a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java @@ -57,14 +57,6 @@ public class CotDataReader extends XmlDataParser { protected String namespace; protected String prefix; protected Map countWriters = new HashMap<>(); - private Strictness strictness = Strictness.LEGACY_STRICT; - private boolean serializeNulls = true; - private FormattingStyle formattingStyle; - // These fields cache data derived from the formatting style, to avoid having to - // re-evaluate it every time something is written - private String formattedColon; - private String formattedComma; - private boolean usesEmptyNewlineAndIndent; public CotDataReader(Reader in) { this.in = Objects.requireNonNull(in, "in == null"); diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java index 2b63401628..8372c73179 100644 --- a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java @@ -51,12 +51,10 @@ // xmldatawriter? public class CotDataWriter extends XmlDataWriter { static final String COT_ERROR = "Error writing XML stream for "; - - protected XMLStreamWriter xmlWriter; + protected String namespace; protected String prefix; protected Map countWriters = new HashMap<>(); - private Strictness strictness = Strictness.LEGACY_STRICT; private boolean serializeNulls = true; private FormattingStyle formattingStyle; // These fields cache data derived from the formatting style, to avoid having to @@ -91,12 +89,22 @@ public void writeCotAttribute(String var1, String var2) throws XMLStreamExceptio xmlWriter.writeAttribute(var1, var2); } - public final void setStrictness(Strictness strictness) { - this.strictness = Objects.requireNonNull(strictness); + @Override + public void startStream(boolean addWrapper) throws IOException + { + try + { + if (addWrapper) + xmlWriter.writeStartElement("event"); + } + catch (XMLStreamException e) + { + throw new IOException(e.getMessage(), e.getCause()); + } } - public final Strictness getStrictness() { - return strictness; + public void writeCotEndElement() throws XMLStreamException { + xmlWriter.writeEndElement(); } public final void setSerializeNulls(boolean serializeNulls) { @@ -112,32 +120,32 @@ public final boolean getSerializeNulls() { return serializeNulls; } - public final void setFormattingStyle(FormattingStyle formattingStyle) { - this.formattingStyle = Objects.requireNonNull(formattingStyle); - - this.formattedComma = ","; - if (this.formattingStyle.usesSpaceAfterSeparators()) { - this.formattedColon = ": "; - - // Only add space if no newline is written - if (this.formattingStyle.getNewline().isEmpty()) { - this.formattedComma = ", "; - } - } else { - this.formattedColon = ":"; - } - - this.usesEmptyNewlineAndIndent = - this.formattingStyle.getNewline().isEmpty() && this.formattingStyle.getIndent().isEmpty(); - } - - - public final void setIndent(String indent) { - if (indent.isEmpty()) { - setFormattingStyle(FormattingStyle.COMPACT); - } else { - setFormattingStyle(FormattingStyle.PRETTY.withIndent(indent)); - } - } +// public final void setFormattingStyle(FormattingStyle formattingStyle) { +// this.formattingStyle = Objects.requireNonNull(formattingStyle); +// +// this.formattedComma = ","; +// if (this.formattingStyle.usesSpaceAfterSeparators()) { +// this.formattedColon = ": "; +// +// // Only add space if no newline is written +// if (this.formattingStyle.getNewline().isEmpty()) { +// this.formattedComma = ", "; +// } +// } else { +// this.formattedColon = ":"; +// } +// +// this.usesEmptyNewlineAndIndent = +// this.formattingStyle.getNewline().isEmpty() && this.formattingStyle.getIndent().isEmpty(); +// } +// +// +// public final void setIndent(String indent) { +// if (indent.isEmpty()) { +// setFormattingStyle(FormattingStyle.COMPACT); +// } else { +// setFormattingStyle(FormattingStyle.PRETTY.withIndent(indent)); +// } +// } } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java index 860ff1ead7..f14e265da9 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java @@ -102,7 +102,7 @@ else if (format.isOneOf(ResourceFormat.SWE_TEXT, ResourceFormat.TEXT_PLAIN, Reso { return new TextEncodingImpl(); } - else if (format.isOneOf(ResourceFormat.SWE_XML, ResourceFormat.TEXT_XML)) + else if (format.isOneOf(ResourceFormat.SWE_XML, ResourceFormat.TEXT_XML, ResourceFormat.COT_XML)) { return new XMLEncodingImpl(); } @@ -118,7 +118,7 @@ else if (format.isOneOf(ResourceFormat.SWE_TEXT, ResourceFormat.TEXT_PLAIN, Reso { return defaultEncoding instanceof TextEncoding ? defaultEncoding : new TextEncodingImpl(); } - else if (format.isOneOf(ResourceFormat.SWE_XML, ResourceFormat.TEXT_XML)) + else if (format.isOneOf(ResourceFormat.SWE_XML, ResourceFormat.TEXT_XML, ResourceFormat.COT_XML)) { return new XMLEncodingImpl(); } @@ -216,10 +216,9 @@ public static Collection getAvailableFormats(IDataStreamInfo dsInfo, Map formatList.add(ResourceFormat.SWE_JSON.getMimeType()); formatList.add(ResourceFormat.SWE_TEXT.getMimeType()); formatList.add(ResourceFormat.SWE_XML.getMimeType()); + formatList.add(ResourceFormat.COT_XML.getMimeType()); } - formatList.add(ResourceFormat.COT_XML.getMimeType()); - formatList.add(ResourceFormat.GEO_JSON.getMimeType()); formatList.add(ResourceFormat.SWE_BINARY.getMimeType()); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java index 34d807b3f4..d7269daad2 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -19,6 +19,8 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; +import net.opengis.OgcPropertyList; +import net.opengis.swe.v20.DataComponent; import org.sensorhub.api.common.BigId; import org.sensorhub.api.common.IdEncoders; import org.sensorhub.api.data.IDataStreamInfo; @@ -68,8 +70,6 @@ public class ObsBindingCotXml extends ResourceBindingCotXml ObsHandlerContextData contextData; IObsStore obsStore; XmlDataParser resultReader; - CotDataReader cotReader; // unused... - CotDataWriter cotWriter = new CotDataWriter(); Map resultWriters; DOMHelper dom; ScalarIndexer timeStampIndexer; @@ -216,6 +216,27 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter Set locationComponents = new HashSet<>(); var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); + Map fieldValues = new HashMap<>(); + Map locationValues = new HashMap<>(); + Map dateFields = new HashMap<>(); + + OgcPropertyList recordStruct = null; + AbstractDataBlock[] resultBlock = null; +// for (int i = 0; i < recordStruct.size() && i < resultBlock.length; i++) { +// String fieldName = recordStruct.get(i).getName(); +// AbstractDataBlock fieldBlock = resultBlock[i]; +// +//// if (fieldBlock != null) { +//// if (locationBlock != null && locationBlock.getAtomCount() >= 2) { +//// var latName = component.getComponent(0).getName(); +//// var latValue = locationBlock.getStringValue(0); +//// locationValues.put(latName, latValue); +//// } +//// } +// +// String version = fieldValues.get("version").toString(); +// } + for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { var component = dataStream.getRecordStructure().getComponent(i); if (LOCATION_DEFINITIONS.contains(component.getDefinition())) { @@ -227,12 +248,6 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter var obsId = idEncoders.getObsIdEncoder().encodeID(key); - cotWriter.setOutput(os); - - cotWriter.writeStartElement("event"); - cotWriter.writeCotAttribute("version", "2.0"); - cotWriter.writeCotAttribute("uid", obsId); - double longitude = 0; double latitude = 0; @@ -243,14 +258,19 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter longitude = locationDataBlock.getDoubleValue(1); } - var recordStruct = ((DataRecordImpl) dataStream.getRecordStructure()).getFieldList(); + recordStruct = ((DataRecordImpl) dataStream.getRecordStructure()).getFieldList(); - var resultBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject(); - - cotWriter.writeCotStartElement("event"); + resultBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject(); int i = 0; + Map unmatchedData = new HashMap<>(); + Map pointData = new HashMap<>(); + Map eventData = new HashMap<>(); + Map remarksData = new HashMap<>(); + + xmlWriter.writeCotAttribute("version", "2.0"); + for (AbstractDataBlock abstractResultBlock : resultBlock) { String value = abstractResultBlock.getStringValue(); String fieldName = recordStruct.get(i).getName(); @@ -258,49 +278,110 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter OffsetDateTime timeResult = null; switch (fieldName) { - case "version": - cotWriter.writeCotAttribute("version", value); + case "version": // event + eventData.put("version", "2.0"); break; - case "type": - cotWriter.writeCotAttribute("type", value); + case "type": // event + eventData.put("type", value); break; - case "uid": - cotWriter.writeCotAttribute("uid", value); + case "uuid", "uid": // event + eventData.put("uid", value); break; - case "time": + case "time": // event timeResult = abstractResultBlock.getDateTime(); - cotWriter.writeCotAttribute("time", timeResult.toString()); + eventData.put("time", timeResult.toString()); break; - case "start": + case "start": // event timeResult = abstractResultBlock.getDateTime(); - cotWriter.writeCotAttribute("start time", timeResult.toString()); + eventData.put("start time", timeResult.toString()); break; - case "stale": // how would i do the plus 1 year here - timeResult = abstractResultBlock.getDateTime(); - cotWriter.writeCotAttribute("stale time", timeResult.toString()); + case "stale": // event + timeResult = abstractResultBlock.getDateTime().plusYears(1); + eventData.put("stale time", timeResult.toString()); break; - case "how": - cotWriter.writeCotAttribute("how", value); + case "how": // event + eventData.put("how", value); break; - case "lat": - cotWriter.writeCotAttribute("lon", value); + case "ce": // point + pointData.put("ce", value); break; - case "ce": - cotWriter.writeCotAttribute("ce", value); + case "hae": // point + pointData.put("hae", value); break; - case "le": - cotWriter.writeCotAttribute("le", value); + case "le": // point + pointData.put("le", value); break; - case "source": - cotWriter.writeCotAttribute("source", value); + case "source": // remarks + remarksData.put("source", value); break; + case "location": // point + var locationBlockCount = abstractResultBlock.getAtomCount(); + String lat, lon, alt; + if (locationBlockCount == 2) { + lat = resultBlock[i].getStringValue(0); + lon = resultBlock[i].getStringValue(1); + + pointData.put("lat", lat); + pointData.put("lon", lon); + break; + } else if (locationBlockCount == 3) { + lat = resultBlock[i].getStringValue(0); + lon = resultBlock[i].getStringValue(0); + alt = resultBlock[i].getStringValue(0); + + pointData.put("lat", lat); + pointData.put("lon", lon); + pointData.put("alt", alt); + break; + } else { + break; + } + default: + unmatchedData.put(fieldName, value); } + i++; } -// if (!(longitude == 0.0 && latitude == 0.0)) { -// -// } + eventData.entrySet().forEach(entry -> { + try { + xmlWriter.writeCotAttribute(entry.getKey(), entry.getValue()); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + }); + + cotWriter.writeCotStartElement("detail"); + unmatchedData.entrySet().forEach(entry -> { + try { + xmlWriter.writeCotAttribute(entry.getKey(), entry.getValue()); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + }); + + cotWriter.writeCotStartElement("remarks"); + remarksData.entrySet().forEach(entry -> { + try { + xmlWriter.writeCotAttribute(entry.getKey(), entry.getValue()); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + }); + cotWriter.writeCotEndElement(); + + cotWriter.writeCotEndElement(); + cotWriter.writeCotStartElement("point"); + pointData.entrySet().forEach(entry -> { + try { + xmlWriter.writeCotAttribute(entry.getKey(), entry.getValue()); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + }); + cotWriter.writeCotEndElement(); + + cotWriter.endStream(); } @@ -346,9 +427,6 @@ protected AbstractDataWriter getSweCommonWriter(IDataStreamInfo dsInfo, OutputSt } protected XmlDataParser getSweCommonParser(IDataStreamInfo dsInfo, InputStream is) throws IOException { - //should be cotxmlparser... soon - // do i have to make a parser actually.....? - // create XML SWE parser var sweParser = new XmlDataParser(); sweParser.setDataComponents(dsInfo.getRecordStructure()); @@ -366,7 +444,6 @@ public void startCollection() throws XMLStreamException, IOException { @Override public void endCollection(Collection links) throws IOException, XMLStreamException { - cotWriter.close(); - cotWriter.flush(); + super.endCollection(links); } } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingSweCommon.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingSweCommon.java index 71234e3e6b..e360809b68 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingSweCommon.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingSweCommon.java @@ -72,6 +72,8 @@ public ObsBindingSweCommon(RequestContext ctx, IdEncoders idEncoders, boolean fo ctx.setResponseContentType(ResourceFormat.TEXT_PLAIN.getMimeType()); else if (ctx.getFormat().equals(ResourceFormat.SWE_XML)) ctx.setResponseContentType(ResourceFormat.APPLI_XML.getMimeType()); + else if (ctx.getFormat().equals(ResourceFormat.COT_XML)) + ctx.setResponseContentType(ResourceFormat.APPLI_XML.getMimeType()); else ctx.setResponseContentType(ctx.getFormat().getMimeType()); } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java index 849855bf82..cd0aae39e0 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java @@ -258,8 +258,12 @@ protected void list(final RequestContext ctx) throws IOException, XMLStreamExcep ctx.setFormatOptions(responseFormat, parseSelectArg(queryParams)); // set default content type - ctx.setResponseContentType(ResourceFormat.JSON.getMimeType()); - +// ctx.setResponseContentType(ResourceFormat.JSON.getMimeType()); + + ctx.setResponseContentType(responseFormat.getMimeType()); + +// ctx.setResponseContentType("application/xml"); + // stream and serialize all resources to servlet output var binding = getBinding(ctx, false); binding.startCollection(); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java index 4b6dbe2483..0a065f73c8 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java @@ -14,16 +14,12 @@ package org.sensorhub.impl.service.consys.resource; -import com.google.gson.Strictness; -import com.google.gson.stream.JsonReader; import org.sensorhub.api.common.IdEncoders; import org.vast.swe.fast.CotDataReader; import org.vast.swe.fast.CotDataWriter; import org.vast.xml.XMLImplFinder; import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import javax.xml.stream.XMLStreamWriter; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.Collection; @@ -103,7 +99,6 @@ protected CotDataWriter getCotWriter(OutputStream os) throws IOException } } - @Override public V deserialize() throws IOException { diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandBindingSweCommon.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandBindingSweCommon.java index 98cfdaf7a7..e3b90e42b8 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandBindingSweCommon.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandBindingSweCommon.java @@ -76,6 +76,8 @@ public CommandBindingSweCommon(RequestContext ctx, IdEncoders idEncoders, boolea ctx.setResponseContentType(ResourceFormat.TEXT_PLAIN.getMimeType()); else if (ctx.getFormat().equals(ResourceFormat.SWE_XML)) ctx.setResponseContentType(ResourceFormat.APPLI_XML.getMimeType()); + else if (ctx.getFormat().equals(ResourceFormat.COT_XML)) + ctx.setResponseContentType(ResourceFormat.APPLI_XML.getMimeType()); else ctx.setResponseContentType(ctx.getFormat().getMimeType()); } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandResultBindingSweCommon.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandResultBindingSweCommon.java index 9120e206b2..1143c95d39 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandResultBindingSweCommon.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandResultBindingSweCommon.java @@ -71,6 +71,8 @@ public CommandResultBindingSweCommon(RequestContext ctx, IdEncoders idEncoders, ctx.setResponseContentType(ResourceFormat.TEXT_PLAIN.getMimeType()); else if (ctx.getFormat().equals(ResourceFormat.SWE_XML)) ctx.setResponseContentType(ResourceFormat.APPLI_XML.getMimeType()); + else if (ctx.getFormat().equals(ResourceFormat.COT_XML)) + ctx.setResponseContentType(ResourceFormat.APPLI_XML.getMimeType()); else ctx.setResponseContentType(ctx.getFormat().getMimeType()); } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamBindingJson.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamBindingJson.java index b57b19d185..b4fee8b692 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamBindingJson.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/task/CommandStreamBindingJson.java @@ -287,6 +287,7 @@ public void serialize(CommandStreamKey key, ICommandStreamInfo csInfo, boolean s writer.value(ResourceFormat.SWE_JSON.getMimeType()); writer.value(ResourceFormat.SWE_TEXT.getMimeType()); writer.value(ResourceFormat.SWE_XML.getMimeType()); + writer.value(ResourceFormat.COT_XML.getMimeType()); } writer.value(ResourceFormat.SWE_BINARY.getMimeType()); writer.endArray(); From 7a7c89ebe59de1cf51a99a0f7a1e525305ede1e8 Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 12 Mar 2026 15:28:49 -0500 Subject: [PATCH 08/15] cleaning up code --- .../java/org/vast/swe/fast/CotDataReader.java | 2 - .../java/org/vast/swe/fast/CotDataWriter.java | 2 - .../service/consys/obs/ObsBindingCotXml.java | 155 +----------------- .../consys/resource/BaseResourceHandler.java | 2 - .../resource/ResourceBindingCotXml.java | 2 - .../consys/resource/ResourceFormat.java | 2 - 6 files changed, 1 insertion(+), 164 deletions(-) diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java index 551e717db9..827e088043 100644 --- a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataReader.java @@ -46,8 +46,6 @@ * @since Dec 2, 2025 */ -// xmlstreamreader -// or xmldataparser? public class CotDataReader extends XmlDataParser { static final String COT_ERROR = "Error writing XML stream for "; private final Reader in; diff --git a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java index 8372c73179..21fb273e9f 100644 --- a/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java +++ b/lib-ogc/swe-common-core/src/main/java/org/vast/swe/fast/CotDataWriter.java @@ -47,8 +47,6 @@ * @author Ashley Poteau * @since Oct 31, 2025 */ -// xmlstreamwriter -// xmldatawriter? public class CotDataWriter extends XmlDataWriter { static final String COT_ERROR = "Error writing XML stream for "; diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java index d7269daad2..3374343ac4 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingCotXml.java @@ -14,11 +14,7 @@ package org.sensorhub.impl.service.consys.obs; -import com.ctc.wstx.api.WstxOutputProperties; import com.google.common.collect.Sets; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; import net.opengis.OgcPropertyList; import net.opengis.swe.v20.DataComponent; import org.sensorhub.api.common.BigId; @@ -26,40 +22,27 @@ import org.sensorhub.api.data.IDataStreamInfo; import org.sensorhub.api.data.IObsData; import org.sensorhub.api.data.ObsData; -import org.sensorhub.api.datastore.feature.IFoiStore; import org.sensorhub.api.datastore.obs.DataStreamKey; import org.sensorhub.api.datastore.obs.IObsStore; -import org.sensorhub.impl.service.consys.ResourceParseException; -import org.sensorhub.impl.service.consys.SWECommonUtils; -import org.sensorhub.impl.service.consys.ServiceErrors; import org.sensorhub.impl.service.consys.obs.ObsHandler.ObsHandlerContextData; import org.sensorhub.impl.service.consys.resource.*; import org.sensorhub.utils.SWEDataUtils; -import org.vast.cdm.common.DataStreamWriter; import org.vast.data.AbstractDataBlock; import org.vast.data.DataBlockMixed; import org.vast.data.DataRecordImpl; import org.vast.data.XMLEncodingImpl; -import org.vast.swe.BinaryDataWriter; import org.vast.swe.SWEConstants; import org.vast.swe.ScalarIndexer; import org.vast.swe.fast.*; import org.vast.swe.helper.GeoPosHelper; -import net.opengis.swe.v20.DataBlock; -import org.sensorhub.api.data.DataEvent; -import org.vast.util.ReaderException; import org.vast.xml.DOMHelper; import net.opengis.swe.v20.DataRecord; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import javax.xml.stream.XMLStreamWriter; -import org.vast.swe.helper.CoTHelper; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.time.OffsetDateTime; -import java.time.format.DateTimeParseException; import java.util.*; import static org.sensorhub.impl.service.consys.SWECommonUtils.OM_COMPONENTS_FILTER; @@ -75,7 +58,6 @@ public class ObsBindingCotXml extends ResourceBindingCotXml ScalarIndexer timeStampIndexer; XMLOutputFactory factory = XMLOutputFactory.newInstance(); OutputStream os = ctx.getOutputStream(); - IFoiStore foiStore; protected DataRecord dataRec; private static final Set LOCATION_DEFINITIONS = Sets.newHashSet( @@ -122,120 +104,14 @@ public IObsData deserialize(CotDataReader xmlReader) throws IOException { return newObs; } -// @Override -// public IObsData deserialize(CotDataReader xmlReader) throws IOException { -// var obs = new ObsData.Builder() -// .withDataStream(contextData.dsID); -// -// CoTHelper fac = new CoTHelper(); -// -// String vers = "2.0"; -// -// dataRec = (DataRecord) fac.createRecord() -// .label("") -// .addField("version", fac.createCoTVersion()) -// .addField("type", fac.createType()) -// .addField("uid", fac.createUID()) -// .addField("time", fac.createPrecisionTimeStamp()) -// .addField("start-time", fac.createStartTime()) -// .addField("stale-time", fac.createStaleTime()) -// .addField("how", fac.createHow()) -// .label("") -// .label("") -// .addField("lat", fac.createLatitude()) -// .addField("lon", fac.createLongitude()) -// .addField("ce", fac.createCE()) -// // hae here?..... -// .addField("le", fac.createLE()) -// .label("") -// .label("") -// // -// .label("") -// .addField("source", fac.createRmkSrc()) -// .addField("time", fac.createPrecisionTimeStamp()) -// .label("") -// .label(""); -// -//// try { -//// while (xmlReader.hasNext()) { -//// xmlReader.next(); -//// -//// //var propName = reader.nextName(); -//// -//// if (xmlReader.isStartElement()) { -//// String propName = xmlReader.getLocalName(); -//// -//// if ("phenomenonTime".equals(propName)) -//// obs.withPhenomenonTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); -//// else if ("resultTime".equals(propName)) -//// obs.withResultTime(OffsetDateTime.parse(xmlReader.getElementText()).toInstant()); -//// else if ("foi@id".equals(propName)) { -//// try { -//// var foiID = idEncoders.getFoiIdEncoder().decodeID(xmlReader.getElementText()); -//// obs.withFoi(foiID); -//// } catch (IllegalArgumentException e) { -//// throw ServiceErrors.badRequest("Invalid FOI ID"); -//// } catch (XMLStreamException e) { -//// throw new RuntimeException(e); -//// } -//// } else if ("result".equals(propName)) { -//// //var result = xmlReader.next(); -//// obs.withResult((DataBlock) dataRec); -//// } -//// } -//// } -//// } -//// catch (DateTimeParseException e) -//// { -//// throw new ResourceParseException(INVALID_XML_ERROR_MSG + "Invalid ISO8601 date/time at " + xmlReader.getLocalName()); -//// } -//// catch (IllegalStateException e) -//// { -//// throw new ResourceParseException(INVALID_XML_ERROR_MSG + e.getMessage()); -//// } catch (XMLStreamException e) { -//// throw new RuntimeException(e); -//// } -// -// if (contextData.foiId != null && contextData.foiId != BigId.NONE) -// obs.withFoi(contextData.foiId); -// -// var newObs = obs.build(); -// -// // set timestamp in result data if present in schema -// if (timeStampIndexer != null) -// { -// var phenomenonTimeIdx = timeStampIndexer.getDataIndex(newObs.getResult()); -// newObs.getResult().setDoubleValue(phenomenonTimeIdx, newObs.getPhenomenonTime().toEpochMilli() / 1000.0); -// } -// -// return newObs; -// } - @Override public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter xmlWriter) throws IOException, XMLStreamException { Set locationComponents = new HashSet<>(); var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); - Map fieldValues = new HashMap<>(); - Map locationValues = new HashMap<>(); - Map dateFields = new HashMap<>(); - OgcPropertyList recordStruct = null; AbstractDataBlock[] resultBlock = null; -// for (int i = 0; i < recordStruct.size() && i < resultBlock.length; i++) { -// String fieldName = recordStruct.get(i).getName(); -// AbstractDataBlock fieldBlock = resultBlock[i]; -// -//// if (fieldBlock != null) { -//// if (locationBlock != null && locationBlock.getAtomCount() >= 2) { -//// var latName = component.getComponent(0).getName(); -//// var latValue = locationBlock.getStringValue(0); -//// locationValues.put(latName, latValue); -//// } -//// } -// -// String version = fieldValues.get("version").toString(); -// } + for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { var component = dataStream.getRecordStructure().getComponent(i); @@ -246,18 +122,6 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, CotDataWriter } } - var obsId = idEncoders.getObsIdEncoder().encodeID(key); - - double longitude = 0; - double latitude = 0; - - for (int index : locationComponents) { - var locationDataBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject()[index]; - // You'll still need to check if these are real values and not null - latitude = locationDataBlock.getDoubleValue(0); - longitude = locationDataBlock.getDoubleValue(1); - } - recordStruct = ((DataRecordImpl) dataStream.getRecordStructure()).getFieldList(); resultBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject(); @@ -398,28 +262,11 @@ protected AbstractDataWriter getSweCommonWriter(BigId dsID, OutputStream os) thr } protected AbstractDataWriter getSweCommonWriter(IDataStreamInfo dsInfo, OutputStream os) throws IOException { -// if (!SWECommonUtils.allowNonBinaryFormat(dsInfo.getRecordStructure(), dsInfo.getRecordEncoding())) -// return new BinaryDataWriter(); // i see i cant return BinaryDataWriter because this method and the one before are now - // AbstractDataWriter instead of DataStreamWriter, but idk what else to return... - // the auto fix just creates more errors and issues. i dont wanna meddle too much in other files - // not too sure what this does at all tbh - -//// if (dsInfo.getRecordEncoding() instanceof TextEncodingImpl) { -//// throw new IOException("Text encoding not supported for application/cot+xml"); -//// } - - // create cot/xml writer - //XmlDataWriter dataWriter = new XmlDataWriter(); //wraps writer. when you return writer, - // youre passing in a writer that knows how to write the specific xml data it needs. - //CotWriter responsible for writing cot spec compliant info - CotDataWriter dataWriter = new CotDataWriter(); - //xmlcotwriter extends xmldatawriter. new class. same with xmlcotparser and reader. convert it back into a swecommondata record that can be put in osh dataWriter.setDataEncoding(new XMLEncodingImpl()); dataWriter.setOutput(os); dataWriter.setDataComponents(dsInfo.getRecordStructure()); - //cotWriter.setDataEncoding(dsInfo.getRecordEncoding()); // filter out components that are already included in O&M dataWriter.setDataComponentFilter(OM_COMPONENTS_FILTER); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java index cd0aae39e0..d4a51533f6 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/BaseResourceHandler.java @@ -258,11 +258,9 @@ protected void list(final RequestContext ctx) throws IOException, XMLStreamExcep ctx.setFormatOptions(responseFormat, parseSelectArg(queryParams)); // set default content type -// ctx.setResponseContentType(ResourceFormat.JSON.getMimeType()); ctx.setResponseContentType(responseFormat.getMimeType()); -// ctx.setResponseContentType("application/xml"); // stream and serialize all resources to servlet output var binding = getBinding(ctx, false); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java index 0a065f73c8..4cfeece7fe 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceBindingCotXml.java @@ -42,8 +42,6 @@ public abstract class ResourceBindingCotXml extends ResourceBinding public static final String INVALID_XML_ERROR_MSG = "Invalid XML: "; public static final String MISSING_PROP_ERROR_MSG = "Missing property: "; -// protected final XMLStreamReader xmlReader; -// protected final XMLStreamWriter xmlWriter; protected final CotDataReader cotReader; protected final CotDataWriter cotWriter; diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java index eafc071924..7d94bf7a3b 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java @@ -38,10 +38,8 @@ public class ResourceFormat public static ResourceFormat SML_JSON = new ResourceFormat("application/sml+json", SHORT_SMLJSON); public static ResourceFormat SML_XML = new ResourceFormat("application/sml+xml", SHORT_SMLXML); - //BOW public static ResourceFormat GEO_JSON = new ResourceFormat("application/geo+json", SHORT_GEO_JSON); - //BOW (again) public static ResourceFormat COT_XML = new ResourceFormat("application/cot+xml", SHORT_COTXML); public static ResourceFormat OM_JSON = new ResourceFormat("application/om+json", SHORT_JSON); From 72d86110487a0689813ce8b91d43727808b3c40f Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 9 Apr 2026 11:48:01 -0500 Subject: [PATCH 09/15] adding protofiles on gh --- .../java/org/sensorhub/utils/ProtoWriter.java | 4 + .../consys/obs/ObsBindingProtobuf.java | 315 ++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java create mode 100644 sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java diff --git a/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java b/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java new file mode 100644 index 0000000000..c91657bf67 --- /dev/null +++ b/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java @@ -0,0 +1,4 @@ +package org.sensorhub.utils; + +public class ProtoWriter { +} diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java new file mode 100644 index 0000000000..0df3d96cd6 --- /dev/null +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java @@ -0,0 +1,315 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + + The contents of this file are subject to the Mozilla Public License, v. 2.0. + If a copy of the MPL was not distributed with this file, You can obtain one + at http://mozilla.org/MPL/2.0/. + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + Copyright (C) 2020 Sensia Software LLC. All Rights Reserved. + + ******************************* END LICENSE BLOCK ***************************/ + +package org.sensorhub.impl.service.consys.obs; + +import com.google.common.collect.Sets; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import org.sensorhub.api.common.BigId; +import org.sensorhub.api.common.IdEncoders; +import org.sensorhub.api.data.IDataStreamInfo; +import org.sensorhub.api.data.IObsData; +import org.sensorhub.api.data.ObsData; +import org.sensorhub.api.datastore.feature.IFoiStore; +import org.sensorhub.api.datastore.obs.DataStreamKey; +import org.sensorhub.api.datastore.obs.IObsStore; +import org.sensorhub.impl.service.consys.ResourceParseException; +import org.sensorhub.impl.service.consys.SWECommonUtils; +import org.sensorhub.impl.service.consys.ServiceErrors; +import org.sensorhub.impl.service.consys.obs.ObsHandler.ObsHandlerContextData; +import org.sensorhub.impl.service.consys.resource.PropertyFilter; +import org.sensorhub.impl.service.consys.resource.RequestContext; +import org.sensorhub.impl.service.consys.resource.ResourceBindingJson; +import org.sensorhub.impl.service.consys.resource.ResourceLink; +import org.sensorhub.utils.SWEDataUtils; +import org.vast.cdm.common.DataStreamWriter; +import org.vast.data.DataBlockMixed; +import org.vast.swe.BinaryDataWriter; +import org.vast.swe.SWEConstants; +import org.vast.swe.ScalarIndexer; +import org.vast.swe.fast.JsonDataParserGson; +import org.vast.swe.fast.JsonDataWriterGson; +import org.vast.swe.helper.GeoPosHelper; +import org.vast.util.ReaderException; + +import java.io.IOException; +import java.io.OutputStream; +import java.time.OffsetDateTime; +import java.time.format.DateTimeParseException; +import java.util.*; +import java.io.File; + +import org.sensorhub.utils.ProtoWriter; + +import javax.xml.stream.XMLStreamException; + +import static org.sensorhub.impl.service.consys.SWECommonUtils.OM_COMPONENTS_FILTER; + + +public class ObsBindingProtobuf extends ResourceBindingJson +{ + ObsHandlerContextData contextData; + IObsStore obsStore; + JsonDataParserGson resultReader; + Map resultWriters; + ScalarIndexer timeStampIndexer; + IFoiStore foiStore; + + + private static final Set LOCATION_DEFINITIONS = Sets.newHashSet( + SWEConstants.DEF_SENSOR_LOC, + SWEConstants.DEF_PLATFORM_LOC, + SWEConstants.DEF_SAMPLING_LOC, + GeoPosHelper.DEF_LOCATION + ); + + + public ObsBindingProtobuf(RequestContext ctx, IdEncoders idEncoders, boolean forReading, IObsStore obsStore) throws IOException + { + super(ctx, idEncoders, forReading); + this.contextData = (ObsHandlerContextData)ctx.getData(); + this.obsStore = obsStore; + + if (forReading) + { + resultReader = getSweCommonParser(contextData.dsInfo, reader); + resultReader.setRenewDataBlock(true); + timeStampIndexer = SWEDataUtils.getTimeStampIndexer(contextData.dsInfo.getRecordStructure()); + } + else + { + this.resultWriters = new HashMap<>(); + + // init result writer only in case of single datastream + // otherwise we'll do it later + if (contextData != null && contextData.dsInfo != null) + { + var resultWriter = getSweCommonWriter(contextData.dsInfo, writer, ctx.getPropertyFilter()); + resultWriters.put(ctx.getParentID(), resultWriter); + } + } + } + + + @Override + public IObsData deserialize(JsonReader reader) throws IOException + { + // if array, prepare to parse first element + if (reader.peek() == JsonToken.BEGIN_ARRAY) + reader.beginArray(); + + if (reader.peek() == JsonToken.END_DOCUMENT || !reader.hasNext()) + return null; + + var obs = new ObsData.Builder() + .withDataStream(contextData.dsID); + + try + { + reader.beginObject(); + + while (reader.hasNext()) + { + var propName = reader.nextName(); + + if ("phenomenonTime".equals(propName)) + obs.withPhenomenonTime(OffsetDateTime.parse(reader.nextString()).toInstant()); + else if ("resultTime".equals(propName)) + obs.withResultTime(OffsetDateTime.parse(reader.nextString()).toInstant()); + else if ("foi@id".equals(propName)) + { + try + { + var foiID = idEncoders.getFoiIdEncoder().decodeID(reader.nextString()); + obs.withFoi(foiID); + } + catch (IllegalArgumentException e) + { + throw ServiceErrors.badRequest("Invalid FOI ID"); + } + } + else if ("result".equals(propName)) + { + var result = resultReader.parseNextBlock(); + obs.withResult(result); + } + else + reader.skipValue(); + } + + reader.endObject(); + } + catch (DateTimeParseException e) + { + throw new ResourceParseException(INVALID_JSON_ERROR_MSG + "Invalid ISO8601 date/time at " + reader.getPath()); + } + catch (IllegalStateException | ReaderException e) + { + throw new ResourceParseException(INVALID_JSON_ERROR_MSG + e.getMessage()); + } + + if (contextData.foiId != null && contextData.foiId != BigId.NONE) + obs.withFoi(contextData.foiId); + + var newObs = obs.build(); + + // set timestamp in result data if present in schema + if (timeStampIndexer != null) + { + var phenomenonTimeIdx = timeStampIndexer.getDataIndex(newObs.getResult()); + newObs.getResult().setDoubleValue(phenomenonTimeIdx, newObs.getPhenomenonTime().toEpochMilli() / 1000.0); + } + + return newObs; + } + + @Override + public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter writer) throws IOException { + + ProtoWriter protoWriter = new ProtoWriter(); + + //protoWriter.writeProto(systemName, streamInfo); + + Set locationComponents = new HashSet<>(); + + var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); + for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { + var component = dataStream.getRecordStructure().getComponent(i); + if (LOCATION_DEFINITIONS.contains(component.getDefinition())) { + // This is how we know we have location components in the data structure + // So we can save this and parse specifically the location components into GeoJSON + locationComponents.add(i); + } + } + + double altitude = 0; + double longitude = 0; + double latitude = 0; + + for (int index : locationComponents) { + var locationDataBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject()[index]; + // You'll still need to check if these are real values and not null + latitude = locationDataBlock.getDoubleValue(0); + longitude = locationDataBlock.getDoubleValue(1); + altitude = locationDataBlock.getDoubleValue(2); + } + + var obsId = idEncoders.getObsIdEncoder().encodeID(key); + + var resultWriter = resultWriters.computeIfAbsent(obs.getDataStreamID(), + k -> getSweCommonWriter(k, writer, ctx.getPropertyFilter()) ); + + var obsRes = obs.getResult().toString(); + + var obsName = dataStream.getOutputName(); + + + + if (!(longitude == 0.0 && latitude == 0.0)) { + writer.beginObject(); + writer.name("type").value("Feature"); + + writer.name("geometry"); + writer.beginObject(); + writer.name("type").value("Point"); + + writer.name("coordinates").value("[" + longitude + ", " + latitude + "]"); + + writer.name("properties"); + + writer.beginObject(); + writer.name("name").value(obsName); + writer.name("id").value(obsId); + writer.name("phenomenonTime").value(obs.getPhenomenonTime().toString()); + writer.name("resultTime").value(obs.getResultTime().toString()); + + writer.endObject(); + writer.endObject(); + writer.endObject(); + writer.flush(); + } + } + + + protected JsonWriter getJsonWriter(OutputStream os, PropertyFilter propFilter) throws IOException + { + var writer = super.getJsonWriter(os, propFilter); + writer.setSerializeNulls(true); + return writer; + } + + + protected DataStreamWriter getSweCommonWriter(BigId dsID, JsonWriter writer, PropertyFilter propFilter) + { + var dsInfo = obsStore.getDataStreams().get(new DataStreamKey(dsID)); + return getSweCommonWriter(dsInfo, writer, propFilter); + } + + + protected DataStreamWriter getSweCommonWriter(IDataStreamInfo dsInfo, JsonWriter writer, PropertyFilter propFilter) + { + if (!SWECommonUtils.allowNonBinaryFormat(dsInfo.getRecordStructure(), dsInfo.getRecordEncoding())) + return new BinaryDataWriter(); + + // create JSON SWE writer + var sweWriter = new JsonDataWriterGson(writer); + sweWriter.setDataComponents(dsInfo.getRecordStructure()); + + // filter out components that are already included in O&M + sweWriter.setDataComponentFilter(OM_COMPONENTS_FILTER); + return sweWriter; + } + + + protected JsonDataParserGson getSweCommonParser(IDataStreamInfo dsInfo, JsonReader reader) + { + // create JSON SWE parser + var sweParser = new JsonDataParserGson(reader); + sweParser.setDataComponents(dsInfo.getRecordStructure()); + + // filter out components that are already included in O&M + sweParser.setDataComponentFilter(OM_COMPONENTS_FILTER); + return sweParser; + } + + + @Override + public void startCollection() throws IOException + { + if (reader != null) { + // if we're reading, just skip to the items array + // calls to deserialize() will take it from there + // TODO generalize this to all bindings + reader.beginObject(); + while (reader.hasNext()) { + var propName = reader.nextName(); + if (propName.equals(getItemsPropertyName())) + return; + else + reader.skipValue(); + } + } + else + startJsonCollection(writer); + } + + + @Override + public void endCollection(Collection links) throws IOException + { + endJsonCollection(writer, links); + } +} From b868e2d9418369771eeef04833b7ac780d3c2770 Mon Sep 17 00:00:00 2001 From: ashley Date: Wed, 15 Apr 2026 11:29:29 -0500 Subject: [PATCH 10/15] adding protowriter file --- .../java/org/sensorhub/utils/ProtoWriter.java | 118 +++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java b/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java index c91657bf67..4c9b4c68c6 100644 --- a/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java +++ b/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java @@ -1,4 +1,120 @@ +/***************************** BEGIN LICENSE BLOCK *************************** + + Copyright (C) 2025 Botts Innovative Research, Inc. All Rights Reserved. + + ******************************* END LICENSE BLOCK ***************************/ package org.sensorhub.utils; +import net.opengis.swe.v20.*; +import org.sensorhub.api.command.ICommandStreamInfo; +import org.sensorhub.api.data.IDataStreamInfo; + +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + public class ProtoWriter { -} + + private final StringBuilder sb; + private int indentLevel = 0; + // Protobuf fields MUST have a unique tag number starting at 1 + private int fieldTagCounter = 1; + + public ProtoWriter() { + this.sb = new StringBuilder(); + } + + public void writeProto(String systemName, IDataStreamInfo dsInfo) throws IOException { + startDocument(); + buildProtoForComponent(dsInfo.getRecordStructure()); + endDocument(systemName, dsInfo.getOutputName()); + } + + private void startDocument() { + sb.append("syntax = \"proto3\";\n\n"); + sb.append("message Record {\n"); + indentLevel++; + } + + private void buildProtoForComponent(DataComponent component) { + String name = cleanName(component.getName()); + + if (component instanceof DataChoice choice) { + writeLine("oneof " + name + " {"); + indentLevel++; + int tempTag = 1; + for (DataComponent item : choice.getItemList()) { + writeField(mapType(item), item.getName(), tempTag++); + } + indentLevel--; + writeLine("}"); + } + else if (component instanceof Category || component instanceof CategoryRange) { + writeField("string", name, fieldTagCounter++); + } + else if (component.getComponentCount() > 0) { + + writeLine("message " + capitalize(name) + " {"); + indentLevel++; + int savedCounter = fieldTagCounter; + fieldTagCounter = 1; + for (int i = 0; i < component.getComponentCount(); i++) { + buildProtoForComponent(component.getComponent(i)); + } + indentLevel--; + writeLine("}"); + writeField(capitalize(name), name, savedCounter); + fieldTagCounter = savedCounter + 1; + } + else { + // Simple scalars + writeField(mapType(component), name, fieldTagCounter++); + } + } + + private String mapType(DataComponent comp) { + if (comp instanceof Time) return "uint64"; + if (comp instanceof ScalarComponent scalar) { + return switch (scalar.getDataType()) { + case BOOLEAN -> "bool"; + case DOUBLE, FLOAT -> "double"; + case INT, SHORT, BYTE -> "int32"; + case LONG -> "int64"; + default -> "string"; + }; + } + return "string"; + } + + private void writeField(String type, String name, int tag) { + writeLine(type + " " + cleanName(name) + " = " + tag + ";"); + } + + private void writeLine(String text) { + sb.append(" ".repeat(indentLevel)).append(text).append("\n"); + } + + private String cleanName(String name) { + return name.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase(); + } + + private String capitalize(String str) { + return str.substring(0, 1).toUpperCase() + str.substring(1); + } + + private void endDocument(String systemName, String streamName) throws IOException { + indentLevel--; + sb.append("}\n"); + + systemName = systemName.replace(' ', '_'); + File file = new File("./schemas/" + systemName + "_" + streamName + ".proto"); + file.getParentFile().mkdirs(); + try (FileWriter fileWriter = new FileWriter(file)) { + fileWriter.write(sb.toString()); + } + } +} \ No newline at end of file From ebd46b2049d88106611502238260a8e704a9ad86 Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 14 May 2026 09:09:30 -0500 Subject: [PATCH 11/15] mapping osh <-> protobuf fields --- .../consys/obs/ObsBindingProtobuf.java | 48 +++++-------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java index 0df3d96cd6..a50829d69c 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java @@ -37,6 +37,7 @@ import org.sensorhub.utils.SWEDataUtils; import org.vast.cdm.common.DataStreamWriter; import org.vast.data.DataBlockMixed; +import org.vast.data.DataRecordImpl; import org.vast.swe.BinaryDataWriter; import org.vast.swe.SWEConstants; import org.vast.swe.ScalarIndexer; @@ -183,9 +184,20 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter wri //protoWriter.writeProto(systemName, streamInfo); + var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); + var recordStruct = ((DataRecordImpl) dataStream.getRecordStructure()).getFieldList(); + var resultBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject(); + + // map osh fields to proto fields + Map resultValues = new HashMap<>(); + for (int i = 0; i < resultBlock.length; i++) { + String fieldName = recordStruct.get(i).getName(); + String value = resultBlock[i].getStringValue(); + resultValues.put(fieldName, value); + } + Set locationComponents = new HashSet<>(); - var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { var component = dataStream.getRecordStructure().getComponent(i); if (LOCATION_DEFINITIONS.contains(component.getDefinition())) { @@ -195,19 +207,7 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter wri } } - double altitude = 0; - double longitude = 0; - double latitude = 0; - - for (int index : locationComponents) { - var locationDataBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject()[index]; - // You'll still need to check if these are real values and not null - latitude = locationDataBlock.getDoubleValue(0); - longitude = locationDataBlock.getDoubleValue(1); - altitude = locationDataBlock.getDoubleValue(2); - } - var obsId = idEncoders.getObsIdEncoder().encodeID(key); var resultWriter = resultWriters.computeIfAbsent(obs.getDataStreamID(), k -> getSweCommonWriter(k, writer, ctx.getPropertyFilter()) ); @@ -218,29 +218,7 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter wri - if (!(longitude == 0.0 && latitude == 0.0)) { - writer.beginObject(); - writer.name("type").value("Feature"); - writer.name("geometry"); - writer.beginObject(); - writer.name("type").value("Point"); - - writer.name("coordinates").value("[" + longitude + ", " + latitude + "]"); - - writer.name("properties"); - - writer.beginObject(); - writer.name("name").value(obsName); - writer.name("id").value(obsId); - writer.name("phenomenonTime").value(obs.getPhenomenonTime().toString()); - writer.name("resultTime").value(obs.getResultTime().toString()); - - writer.endObject(); - writer.endObject(); - writer.endObject(); - writer.flush(); - } } From 4aa1fc9bfd3a2f0bef865164ccc0b25767c41b4c Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 4 Jun 2026 08:21:04 -0500 Subject: [PATCH 12/15] serialization logic, dependencies, file structure --- sensorhub-service-consys/build.gradle | 1 + .../service/consys/obs/proto/Observation.java | 2137 +++++++++++++++++ .../consys/resource/ResourceFormat.java | 5 + .../src/main/proto/observation.proto | 21 + 4 files changed, 2164 insertions(+) create mode 100644 sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java create mode 100644 sensorhub-service-consys/src/main/proto/observation.proto diff --git a/sensorhub-service-consys/build.gradle b/sensorhub-service-consys/build.gradle index a9fbdf7c01..68adc7882f 100644 --- a/sensorhub-service-consys/build.gradle +++ b/sensorhub-service-consys/build.gradle @@ -10,6 +10,7 @@ dependencies { testImplementation project(':sensorhub-datastore-h2') testImplementation 'commons-io:commons-io:1.3.2' testImplementation 'org.jglue.fluent-json:fluent-json:2.0.3' + implementation 'com.google.protobuf:protobuf-java:3.25.1' } test { diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java new file mode 100644 index 0000000000..33800aac60 --- /dev/null +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java @@ -0,0 +1,2137 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: observation.proto + +package obs; + +public final class Observation { + private Observation() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + public interface OshObservationOrBuilder extends + // @@protoc_insertion_point(interface_extends:obs.OshObservation) + com.google.protobuf.MessageOrBuilder { + + /** + * string id = 1; + * @return The id. + */ + java.lang.String getId(); + /** + * string id = 1; + * @return The bytes for id. + */ + com.google.protobuf.ByteString + getIdBytes(); + + /** + * string datastreamId = 2; + * @return The datastreamId. + */ + java.lang.String getDatastreamId(); + /** + * string datastreamId = 2; + * @return The bytes for datastreamId. + */ + com.google.protobuf.ByteString + getDatastreamIdBytes(); + + /** + * string foiId = 3; + * @return The foiId. + */ + java.lang.String getFoiId(); + /** + * string foiId = 3; + * @return The bytes for foiId. + */ + com.google.protobuf.ByteString + getFoiIdBytes(); + + /** + * string phenomenonTime = 4; + * @return The phenomenonTime. + */ + java.lang.String getPhenomenonTime(); + /** + * string phenomenonTime = 4; + * @return The bytes for phenomenonTime. + */ + com.google.protobuf.ByteString + getPhenomenonTimeBytes(); + + /** + * string resultTime = 5; + * @return The resultTime. + */ + java.lang.String getResultTime(); + /** + * string resultTime = 5; + * @return The bytes for resultTime. + */ + com.google.protobuf.ByteString + getResultTimeBytes(); + + /** + * .obs.Results results = 6; + * @return Whether the results field is set. + */ + boolean hasResults(); + /** + * .obs.Results results = 6; + * @return The results. + */ + obs.Observation.Results getResults(); + /** + * .obs.Results results = 6; + */ + obs.Observation.ResultsOrBuilder getResultsOrBuilder(); + } + /** + * Protobuf type {@code obs.OshObservation} + */ + public static final class OshObservation extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:obs.OshObservation) + OshObservationOrBuilder { + private static final long serialVersionUID = 0L; + // Use OshObservation.newBuilder() to construct. + private OshObservation(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private OshObservation() { + id_ = ""; + datastreamId_ = ""; + foiId_ = ""; + phenomenonTime_ = ""; + resultTime_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new OshObservation(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return obs.Observation.internal_static_obs_OshObservation_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return obs.Observation.internal_static_obs_OshObservation_fieldAccessorTable + .ensureFieldAccessorsInitialized( + obs.Observation.OshObservation.class, obs.Observation.OshObservation.Builder.class); + } + + public static final int ID_FIELD_NUMBER = 1; + @SuppressWarnings("serial") + private volatile java.lang.Object id_ = ""; + /** + * string id = 1; + * @return The id. + */ + @java.lang.Override + public java.lang.String getId() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } + } + /** + * string id = 1; + * @return The bytes for id. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DATASTREAMID_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object datastreamId_ = ""; + /** + * string datastreamId = 2; + * @return The datastreamId. + */ + @java.lang.Override + public java.lang.String getDatastreamId() { + java.lang.Object ref = datastreamId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + datastreamId_ = s; + return s; + } + } + /** + * string datastreamId = 2; + * @return The bytes for datastreamId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getDatastreamIdBytes() { + java.lang.Object ref = datastreamId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + datastreamId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int FOIID_FIELD_NUMBER = 3; + @SuppressWarnings("serial") + private volatile java.lang.Object foiId_ = ""; + /** + * string foiId = 3; + * @return The foiId. + */ + @java.lang.Override + public java.lang.String getFoiId() { + java.lang.Object ref = foiId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + foiId_ = s; + return s; + } + } + /** + * string foiId = 3; + * @return The bytes for foiId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getFoiIdBytes() { + java.lang.Object ref = foiId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + foiId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PHENOMENONTIME_FIELD_NUMBER = 4; + @SuppressWarnings("serial") + private volatile java.lang.Object phenomenonTime_ = ""; + /** + * string phenomenonTime = 4; + * @return The phenomenonTime. + */ + @java.lang.Override + public java.lang.String getPhenomenonTime() { + java.lang.Object ref = phenomenonTime_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + phenomenonTime_ = s; + return s; + } + } + /** + * string phenomenonTime = 4; + * @return The bytes for phenomenonTime. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getPhenomenonTimeBytes() { + java.lang.Object ref = phenomenonTime_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + phenomenonTime_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int RESULTTIME_FIELD_NUMBER = 5; + @SuppressWarnings("serial") + private volatile java.lang.Object resultTime_ = ""; + /** + * string resultTime = 5; + * @return The resultTime. + */ + @java.lang.Override + public java.lang.String getResultTime() { + java.lang.Object ref = resultTime_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + resultTime_ = s; + return s; + } + } + /** + * string resultTime = 5; + * @return The bytes for resultTime. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getResultTimeBytes() { + java.lang.Object ref = resultTime_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + resultTime_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int RESULTS_FIELD_NUMBER = 6; + private obs.Observation.Results results_; + /** + * .obs.Results results = 6; + * @return Whether the results field is set. + */ + @java.lang.Override + public boolean hasResults() { + return results_ != null; + } + /** + * .obs.Results results = 6; + * @return The results. + */ + @java.lang.Override + public obs.Observation.Results getResults() { + return results_ == null ? obs.Observation.Results.getDefaultInstance() : results_; + } + /** + * .obs.Results results = 6; + */ + @java.lang.Override + public obs.Observation.ResultsOrBuilder getResultsOrBuilder() { + return results_ == null ? obs.Observation.Results.getDefaultInstance() : results_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(id_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, id_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(datastreamId_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, datastreamId_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(foiId_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, foiId_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(phenomenonTime_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 4, phenomenonTime_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(resultTime_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, resultTime_); + } + if (results_ != null) { + output.writeMessage(6, getResults()); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(id_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, id_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(datastreamId_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, datastreamId_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(foiId_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, foiId_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(phenomenonTime_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, phenomenonTime_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(resultTime_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, resultTime_); + } + if (results_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(6, getResults()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof obs.Observation.OshObservation)) { + return super.equals(obj); + } + obs.Observation.OshObservation other = (obs.Observation.OshObservation) obj; + + if (!getId() + .equals(other.getId())) return false; + if (!getDatastreamId() + .equals(other.getDatastreamId())) return false; + if (!getFoiId() + .equals(other.getFoiId())) return false; + if (!getPhenomenonTime() + .equals(other.getPhenomenonTime())) return false; + if (!getResultTime() + .equals(other.getResultTime())) return false; + if (hasResults() != other.hasResults()) return false; + if (hasResults()) { + if (!getResults() + .equals(other.getResults())) return false; + } + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId().hashCode(); + hash = (37 * hash) + DATASTREAMID_FIELD_NUMBER; + hash = (53 * hash) + getDatastreamId().hashCode(); + hash = (37 * hash) + FOIID_FIELD_NUMBER; + hash = (53 * hash) + getFoiId().hashCode(); + hash = (37 * hash) + PHENOMENONTIME_FIELD_NUMBER; + hash = (53 * hash) + getPhenomenonTime().hashCode(); + hash = (37 * hash) + RESULTTIME_FIELD_NUMBER; + hash = (53 * hash) + getResultTime().hashCode(); + if (hasResults()) { + hash = (37 * hash) + RESULTS_FIELD_NUMBER; + hash = (53 * hash) + getResults().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static obs.Observation.OshObservation parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static obs.Observation.OshObservation parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static obs.Observation.OshObservation parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static obs.Observation.OshObservation parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static obs.Observation.OshObservation parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static obs.Observation.OshObservation parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static obs.Observation.OshObservation parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static obs.Observation.OshObservation parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static obs.Observation.OshObservation parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static obs.Observation.OshObservation parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static obs.Observation.OshObservation parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static obs.Observation.OshObservation parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(obs.Observation.OshObservation prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code obs.OshObservation} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:obs.OshObservation) + obs.Observation.OshObservationOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return obs.Observation.internal_static_obs_OshObservation_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return obs.Observation.internal_static_obs_OshObservation_fieldAccessorTable + .ensureFieldAccessorsInitialized( + obs.Observation.OshObservation.class, obs.Observation.OshObservation.Builder.class); + } + + // Construct using obs.Observation.OshObservation.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + id_ = ""; + datastreamId_ = ""; + foiId_ = ""; + phenomenonTime_ = ""; + resultTime_ = ""; + results_ = null; + if (resultsBuilder_ != null) { + resultsBuilder_.dispose(); + resultsBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return obs.Observation.internal_static_obs_OshObservation_descriptor; + } + + @java.lang.Override + public obs.Observation.OshObservation getDefaultInstanceForType() { + return obs.Observation.OshObservation.getDefaultInstance(); + } + + @java.lang.Override + public obs.Observation.OshObservation build() { + obs.Observation.OshObservation result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public obs.Observation.OshObservation buildPartial() { + obs.Observation.OshObservation result = new obs.Observation.OshObservation(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(obs.Observation.OshObservation result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.datastreamId_ = datastreamId_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.foiId_ = foiId_; + } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.phenomenonTime_ = phenomenonTime_; + } + if (((from_bitField0_ & 0x00000010) != 0)) { + result.resultTime_ = resultTime_; + } + if (((from_bitField0_ & 0x00000020) != 0)) { + result.results_ = resultsBuilder_ == null + ? results_ + : resultsBuilder_.build(); + } + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof obs.Observation.OshObservation) { + return mergeFrom((obs.Observation.OshObservation)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(obs.Observation.OshObservation other) { + if (other == obs.Observation.OshObservation.getDefaultInstance()) return this; + if (!other.getId().isEmpty()) { + id_ = other.id_; + bitField0_ |= 0x00000001; + onChanged(); + } + if (!other.getDatastreamId().isEmpty()) { + datastreamId_ = other.datastreamId_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (!other.getFoiId().isEmpty()) { + foiId_ = other.foiId_; + bitField0_ |= 0x00000004; + onChanged(); + } + if (!other.getPhenomenonTime().isEmpty()) { + phenomenonTime_ = other.phenomenonTime_; + bitField0_ |= 0x00000008; + onChanged(); + } + if (!other.getResultTime().isEmpty()) { + resultTime_ = other.resultTime_; + bitField0_ |= 0x00000010; + onChanged(); + } + if (other.hasResults()) { + mergeResults(other.getResults()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + id_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + case 18: { + datastreamId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 26: { + foiId_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000004; + break; + } // case 26 + case 34: { + phenomenonTime_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000008; + break; + } // case 34 + case 42: { + resultTime_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000010; + break; + } // case 42 + case 50: { + input.readMessage( + getResultsFieldBuilder().getBuilder(), + extensionRegistry); + bitField0_ |= 0x00000020; + break; + } // case 50 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private java.lang.Object id_ = ""; + /** + * string id = 1; + * @return The id. + */ + public java.lang.String getId() { + java.lang.Object ref = id_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + id_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string id = 1; + * @return The bytes for id. + */ + public com.google.protobuf.ByteString + getIdBytes() { + java.lang.Object ref = id_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + id_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * string id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + id_ = getDefaultInstance().getId(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + /** + * string id = 1; + * @param value The bytes for id to set. + * @return This builder for chaining. + */ + public Builder setIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + private java.lang.Object datastreamId_ = ""; + /** + * string datastreamId = 2; + * @return The datastreamId. + */ + public java.lang.String getDatastreamId() { + java.lang.Object ref = datastreamId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + datastreamId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string datastreamId = 2; + * @return The bytes for datastreamId. + */ + public com.google.protobuf.ByteString + getDatastreamIdBytes() { + java.lang.Object ref = datastreamId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + datastreamId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string datastreamId = 2; + * @param value The datastreamId to set. + * @return This builder for chaining. + */ + public Builder setDatastreamId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + datastreamId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * string datastreamId = 2; + * @return This builder for chaining. + */ + public Builder clearDatastreamId() { + datastreamId_ = getDefaultInstance().getDatastreamId(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * string datastreamId = 2; + * @param value The bytes for datastreamId to set. + * @return This builder for chaining. + */ + public Builder setDatastreamIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + datastreamId_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private java.lang.Object foiId_ = ""; + /** + * string foiId = 3; + * @return The foiId. + */ + public java.lang.String getFoiId() { + java.lang.Object ref = foiId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + foiId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string foiId = 3; + * @return The bytes for foiId. + */ + public com.google.protobuf.ByteString + getFoiIdBytes() { + java.lang.Object ref = foiId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + foiId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string foiId = 3; + * @param value The foiId to set. + * @return This builder for chaining. + */ + public Builder setFoiId( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + foiId_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * string foiId = 3; + * @return This builder for chaining. + */ + public Builder clearFoiId() { + foiId_ = getDefaultInstance().getFoiId(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + * string foiId = 3; + * @param value The bytes for foiId to set. + * @return This builder for chaining. + */ + public Builder setFoiIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + foiId_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + + private java.lang.Object phenomenonTime_ = ""; + /** + * string phenomenonTime = 4; + * @return The phenomenonTime. + */ + public java.lang.String getPhenomenonTime() { + java.lang.Object ref = phenomenonTime_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + phenomenonTime_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string phenomenonTime = 4; + * @return The bytes for phenomenonTime. + */ + public com.google.protobuf.ByteString + getPhenomenonTimeBytes() { + java.lang.Object ref = phenomenonTime_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + phenomenonTime_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string phenomenonTime = 4; + * @param value The phenomenonTime to set. + * @return This builder for chaining. + */ + public Builder setPhenomenonTime( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + phenomenonTime_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + * string phenomenonTime = 4; + * @return This builder for chaining. + */ + public Builder clearPhenomenonTime() { + phenomenonTime_ = getDefaultInstance().getPhenomenonTime(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + return this; + } + /** + * string phenomenonTime = 4; + * @param value The bytes for phenomenonTime to set. + * @return This builder for chaining. + */ + public Builder setPhenomenonTimeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + phenomenonTime_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + + private java.lang.Object resultTime_ = ""; + /** + * string resultTime = 5; + * @return The resultTime. + */ + public java.lang.String getResultTime() { + java.lang.Object ref = resultTime_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + resultTime_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string resultTime = 5; + * @return The bytes for resultTime. + */ + public com.google.protobuf.ByteString + getResultTimeBytes() { + java.lang.Object ref = resultTime_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + resultTime_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string resultTime = 5; + * @param value The resultTime to set. + * @return This builder for chaining. + */ + public Builder setResultTime( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + resultTime_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + /** + * string resultTime = 5; + * @return This builder for chaining. + */ + public Builder clearResultTime() { + resultTime_ = getDefaultInstance().getResultTime(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + return this; + } + /** + * string resultTime = 5; + * @param value The bytes for resultTime to set. + * @return This builder for chaining. + */ + public Builder setResultTimeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + resultTime_ = value; + bitField0_ |= 0x00000010; + onChanged(); + return this; + } + + private obs.Observation.Results results_; + private com.google.protobuf.SingleFieldBuilderV3< + obs.Observation.Results, obs.Observation.Results.Builder, obs.Observation.ResultsOrBuilder> resultsBuilder_; + /** + * .obs.Results results = 6; + * @return Whether the results field is set. + */ + public boolean hasResults() { + return ((bitField0_ & 0x00000020) != 0); + } + /** + * .obs.Results results = 6; + * @return The results. + */ + public obs.Observation.Results getResults() { + if (resultsBuilder_ == null) { + return results_ == null ? obs.Observation.Results.getDefaultInstance() : results_; + } else { + return resultsBuilder_.getMessage(); + } + } + /** + * .obs.Results results = 6; + */ + public Builder setResults(obs.Observation.Results value) { + if (resultsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + results_ = value; + } else { + resultsBuilder_.setMessage(value); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + * .obs.Results results = 6; + */ + public Builder setResults( + obs.Observation.Results.Builder builderForValue) { + if (resultsBuilder_ == null) { + results_ = builderForValue.build(); + } else { + resultsBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + * .obs.Results results = 6; + */ + public Builder mergeResults(obs.Observation.Results value) { + if (resultsBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0) && + results_ != null && + results_ != obs.Observation.Results.getDefaultInstance()) { + getResultsBuilder().mergeFrom(value); + } else { + results_ = value; + } + } else { + resultsBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000020; + onChanged(); + return this; + } + /** + * .obs.Results results = 6; + */ + public Builder clearResults() { + bitField0_ = (bitField0_ & ~0x00000020); + results_ = null; + if (resultsBuilder_ != null) { + resultsBuilder_.dispose(); + resultsBuilder_ = null; + } + onChanged(); + return this; + } + /** + * .obs.Results results = 6; + */ + public obs.Observation.Results.Builder getResultsBuilder() { + bitField0_ |= 0x00000020; + onChanged(); + return getResultsFieldBuilder().getBuilder(); + } + /** + * .obs.Results results = 6; + */ + public obs.Observation.ResultsOrBuilder getResultsOrBuilder() { + if (resultsBuilder_ != null) { + return resultsBuilder_.getMessageOrBuilder(); + } else { + return results_ == null ? + obs.Observation.Results.getDefaultInstance() : results_; + } + } + /** + * .obs.Results results = 6; + */ + private com.google.protobuf.SingleFieldBuilderV3< + obs.Observation.Results, obs.Observation.Results.Builder, obs.Observation.ResultsOrBuilder> + getResultsFieldBuilder() { + if (resultsBuilder_ == null) { + resultsBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + obs.Observation.Results, obs.Observation.Results.Builder, obs.Observation.ResultsOrBuilder>( + getResults(), + getParentForChildren(), + isClean()); + results_ = null; + } + return resultsBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:obs.OshObservation) + } + + // @@protoc_insertion_point(class_scope:obs.OshObservation) + private static final obs.Observation.OshObservation DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new obs.Observation.OshObservation(); + } + + public static obs.Observation.OshObservation getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public OshObservation parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public obs.Observation.OshObservation getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface ResultsOrBuilder extends + // @@protoc_insertion_point(interface_extends:obs.Results) + com.google.protobuf.MessageOrBuilder { + + /** + * map<string, string> values = 1; + */ + int getValuesCount(); + /** + * map<string, string> values = 1; + */ + boolean containsValues( + java.lang.String key); + /** + * Use {@link #getValuesMap()} instead. + */ + @java.lang.Deprecated + java.util.Map + getValues(); + /** + * map<string, string> values = 1; + */ + java.util.Map + getValuesMap(); + /** + * map<string, string> values = 1; + */ + /* nullable */ +java.lang.String getValuesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue); + /** + * map<string, string> values = 1; + */ + java.lang.String getValuesOrThrow( + java.lang.String key); + } + /** + * Protobuf type {@code obs.Results} + */ + public static final class Results extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:obs.Results) + ResultsOrBuilder { + private static final long serialVersionUID = 0L; + // Use Results.newBuilder() to construct. + private Results(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private Results() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Results(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return obs.Observation.internal_static_obs_Results_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + @java.lang.Override + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 1: + return internalGetValues(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return obs.Observation.internal_static_obs_Results_fieldAccessorTable + .ensureFieldAccessorsInitialized( + obs.Observation.Results.class, obs.Observation.Results.Builder.class); + } + + public static final int VALUES_FIELD_NUMBER = 1; + private static final class ValuesDefaultEntryHolder { + static final com.google.protobuf.MapEntry< + java.lang.String, java.lang.String> defaultEntry = + com.google.protobuf.MapEntry + .newDefaultInstance( + obs.Observation.internal_static_obs_Results_ValuesEntry_descriptor, + com.google.protobuf.WireFormat.FieldType.STRING, + "", + com.google.protobuf.WireFormat.FieldType.STRING, + ""); + } + @SuppressWarnings("serial") + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> values_; + private com.google.protobuf.MapField + internalGetValues() { + if (values_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ValuesDefaultEntryHolder.defaultEntry); + } + return values_; + } + public int getValuesCount() { + return internalGetValues().getMap().size(); + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public boolean containsValues( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetValues().getMap().containsKey(key); + } + /** + * Use {@link #getValuesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getValues() { + return getValuesMap(); + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public java.util.Map getValuesMap() { + return internalGetValues().getMap(); + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getValuesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetValues().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public java.lang.String getValuesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetValues().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + com.google.protobuf.GeneratedMessageV3 + .serializeStringMapTo( + output, + internalGetValues(), + ValuesDefaultEntryHolder.defaultEntry, + 1); + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (java.util.Map.Entry entry + : internalGetValues().getMap().entrySet()) { + com.google.protobuf.MapEntry + values__ = ValuesDefaultEntryHolder.defaultEntry.newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build(); + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, values__); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof obs.Observation.Results)) { + return super.equals(obj); + } + obs.Observation.Results other = (obs.Observation.Results) obj; + + if (!internalGetValues().equals( + other.internalGetValues())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + if (!internalGetValues().getMap().isEmpty()) { + hash = (37 * hash) + VALUES_FIELD_NUMBER; + hash = (53 * hash) + internalGetValues().hashCode(); + } + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static obs.Observation.Results parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static obs.Observation.Results parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static obs.Observation.Results parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static obs.Observation.Results parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static obs.Observation.Results parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static obs.Observation.Results parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static obs.Observation.Results parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static obs.Observation.Results parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static obs.Observation.Results parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static obs.Observation.Results parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static obs.Observation.Results parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static obs.Observation.Results parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(obs.Observation.Results prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code obs.Results} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:obs.Results) + obs.Observation.ResultsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return obs.Observation.internal_static_obs_Results_descriptor; + } + + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMapField( + int number) { + switch (number) { + case 1: + return internalGetValues(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @SuppressWarnings({"rawtypes"}) + protected com.google.protobuf.MapField internalGetMutableMapField( + int number) { + switch (number) { + case 1: + return internalGetMutableValues(); + default: + throw new RuntimeException( + "Invalid map field number: " + number); + } + } + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return obs.Observation.internal_static_obs_Results_fieldAccessorTable + .ensureFieldAccessorsInitialized( + obs.Observation.Results.class, obs.Observation.Results.Builder.class); + } + + // Construct using obs.Observation.Results.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + internalGetMutableValues().clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return obs.Observation.internal_static_obs_Results_descriptor; + } + + @java.lang.Override + public obs.Observation.Results getDefaultInstanceForType() { + return obs.Observation.Results.getDefaultInstance(); + } + + @java.lang.Override + public obs.Observation.Results build() { + obs.Observation.Results result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public obs.Observation.Results buildPartial() { + obs.Observation.Results result = new obs.Observation.Results(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(obs.Observation.Results result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.values_ = internalGetValues(); + result.values_.makeImmutable(); + } + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof obs.Observation.Results) { + return mergeFrom((obs.Observation.Results)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(obs.Observation.Results other) { + if (other == obs.Observation.Results.getDefaultInstance()) return this; + internalGetMutableValues().mergeFrom( + other.internalGetValues()); + bitField0_ |= 0x00000001; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + com.google.protobuf.MapEntry + values__ = input.readMessage( + ValuesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); + internalGetMutableValues().getMutableMap().put( + values__.getKey(), values__.getValue()); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private com.google.protobuf.MapField< + java.lang.String, java.lang.String> values_; + private com.google.protobuf.MapField + internalGetValues() { + if (values_ == null) { + return com.google.protobuf.MapField.emptyMapField( + ValuesDefaultEntryHolder.defaultEntry); + } + return values_; + } + private com.google.protobuf.MapField + internalGetMutableValues() { + if (values_ == null) { + values_ = com.google.protobuf.MapField.newMapField( + ValuesDefaultEntryHolder.defaultEntry); + } + if (!values_.isMutable()) { + values_ = values_.copy(); + } + bitField0_ |= 0x00000001; + onChanged(); + return values_; + } + public int getValuesCount() { + return internalGetValues().getMap().size(); + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public boolean containsValues( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + return internalGetValues().getMap().containsKey(key); + } + /** + * Use {@link #getValuesMap()} instead. + */ + @java.lang.Override + @java.lang.Deprecated + public java.util.Map getValues() { + return getValuesMap(); + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public java.util.Map getValuesMap() { + return internalGetValues().getMap(); + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public /* nullable */ +java.lang.String getValuesOrDefault( + java.lang.String key, + /* nullable */ +java.lang.String defaultValue) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetValues().getMap(); + return map.containsKey(key) ? map.get(key) : defaultValue; + } + /** + * map<string, string> values = 1; + */ + @java.lang.Override + public java.lang.String getValuesOrThrow( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + java.util.Map map = + internalGetValues().getMap(); + if (!map.containsKey(key)) { + throw new java.lang.IllegalArgumentException(); + } + return map.get(key); + } + public Builder clearValues() { + bitField0_ = (bitField0_ & ~0x00000001); + internalGetMutableValues().getMutableMap() + .clear(); + return this; + } + /** + * map<string, string> values = 1; + */ + public Builder removeValues( + java.lang.String key) { + if (key == null) { throw new NullPointerException("map key"); } + internalGetMutableValues().getMutableMap() + .remove(key); + return this; + } + /** + * Use alternate mutation accessors instead. + */ + @java.lang.Deprecated + public java.util.Map + getMutableValues() { + bitField0_ |= 0x00000001; + return internalGetMutableValues().getMutableMap(); + } + /** + * map<string, string> values = 1; + */ + public Builder putValues( + java.lang.String key, + java.lang.String value) { + if (key == null) { throw new NullPointerException("map key"); } + if (value == null) { throw new NullPointerException("map value"); } + internalGetMutableValues().getMutableMap() + .put(key, value); + bitField0_ |= 0x00000001; + return this; + } + /** + * map<string, string> values = 1; + */ + public Builder putAllValues( + java.util.Map values) { + internalGetMutableValues().getMutableMap() + .putAll(values); + bitField0_ |= 0x00000001; + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:obs.Results) + } + + // @@protoc_insertion_point(class_scope:obs.Results) + private static final obs.Observation.Results DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new obs.Observation.Results(); + } + + public static obs.Observation.Results getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Results parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public obs.Observation.Results getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_obs_OshObservation_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_obs_OshObservation_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_obs_Results_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_obs_Results_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_obs_Results_ValuesEntry_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_obs_Results_ValuesEntry_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\021observation.proto\022\003obs\"\214\001\n\016OshObservat" + + "ion\022\n\n\002id\030\001 \001(\t\022\024\n\014datastreamId\030\002 \001(\t\022\r\n" + + "\005foiId\030\003 \001(\t\022\026\n\016phenomenonTime\030\004 \001(\t\022\022\n\n" + + "resultTime\030\005 \001(\t\022\035\n\007results\030\006 \001(\0132\014.obs." + + "Results\"b\n\007Results\022(\n\006values\030\001 \003(\0132\030.obs" + + ".Results.ValuesEntry\032-\n\013ValuesEntry\022\013\n\003k" + + "ey\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001b\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_obs_OshObservation_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_obs_OshObservation_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_obs_OshObservation_descriptor, + new java.lang.String[] { "Id", "DatastreamId", "FoiId", "PhenomenonTime", "ResultTime", "Results", }); + internal_static_obs_Results_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_obs_Results_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_obs_Results_descriptor, + new java.lang.String[] { "Values", }); + internal_static_obs_Results_ValuesEntry_descriptor = + internal_static_obs_Results_descriptor.getNestedTypes().get(0); + internal_static_obs_Results_ValuesEntry_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_obs_Results_ValuesEntry_descriptor, + new java.lang.String[] { "Key", "Value", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java index 7d94bf7a3b..c07b69b560 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/resource/ResourceFormat.java @@ -30,6 +30,7 @@ public class ResourceFormat public static String SHORT_HTML = "html"; private static String SHORT_GEO_JSON = "geo_json"; public static String SHORT_COTXML = "cot"; + public static String SHORT_PROTOBUF = "proto"; public static ResourceFormat HTML = new ResourceFormat("text/html", SHORT_HTML); public static ResourceFormat JSON = new ResourceFormat("application/json", SHORT_JSON); @@ -42,6 +43,8 @@ public class ResourceFormat public static ResourceFormat COT_XML = new ResourceFormat("application/cot+xml", SHORT_COTXML); + public static ResourceFormat PROTOBUF = new ResourceFormat("application/protobuf", SHORT_PROTOBUF); + public static ResourceFormat OM_JSON = new ResourceFormat("application/om+json", SHORT_JSON); public static ResourceFormat OM_XML = new ResourceFormat("application/om+xml"); @@ -80,6 +83,8 @@ else if (SHORT_GEOJSON.equals(format)) return ResourceFormat.GEOJSON; else if (SHORT_GEO_JSON.equals(format)) return ResourceFormat.GEO_JSON; + else if (SHORT_PROTOBUF.equals(format)) + return ResourceFormat.PROTOBUF; else if (SHORT_SMLJSON.equals(format)) return ResourceFormat.SML_JSON; else if (SHORT_SMLXML.equals(format)) diff --git a/sensorhub-service-consys/src/main/proto/observation.proto b/sensorhub-service-consys/src/main/proto/observation.proto new file mode 100644 index 0000000000..3f791ca40e --- /dev/null +++ b/sensorhub-service-consys/src/main/proto/observation.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +package obs; + +message OshObservation { + + string id = 1; + string datastreamId = 2; + string foiId = 3; + string phenomenonTime = 4; + string resultTime = 5; + + Results results = 6; + +} + +message Results { + + map values = 1; + +} From 5fa79db68db546e553d07456aab78e62c275bb6e Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 11 Jun 2026 10:00:46 -0500 Subject: [PATCH 13/15] got link working, serialization logic done, testing in progress rn --- .../impl/service/consys/SWECommonUtils.java | 1 + .../consys/obs/ObsBindingProtobuf.java | 45 ++-- .../impl/service/consys/obs/ObsHandler.java | 2 + .../service/consys/obs/proto/Observation.java | 219 +++++++++--------- .../src/main/proto/observation.proto | 3 + 5 files changed, 138 insertions(+), 132 deletions(-) diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java index f14e265da9..8cb7c1a616 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/SWECommonUtils.java @@ -218,6 +218,7 @@ public static Collection getAvailableFormats(IDataStreamInfo dsInfo, Map formatList.add(ResourceFormat.SWE_XML.getMimeType()); formatList.add(ResourceFormat.COT_XML.getMimeType()); } + formatList.add(ResourceFormat.PROTOBUF.getMimeType()); formatList.add(ResourceFormat.GEO_JSON.getMimeType()); diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java index a50829d69c..3cfbc79936 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java @@ -45,6 +45,9 @@ import org.vast.swe.fast.JsonDataWriterGson; import org.vast.swe.helper.GeoPosHelper; import org.vast.util.ReaderException; +import org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation; +import org.sensorhub.impl.service.consys.obs.proto.Observation.Results; +import org.vast.data.DataRecordImpl; import java.io.IOException; import java.io.OutputStream; @@ -189,35 +192,29 @@ public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter wri var resultBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject(); // map osh fields to proto fields - Map resultValues = new HashMap<>(); + //Map resultValues = new HashMap<>(); + Results.Builder resultsBuilder = Results.newBuilder(); for (int i = 0; i < resultBlock.length; i++) { String fieldName = recordStruct.get(i).getName(); String value = resultBlock[i].getStringValue(); - resultValues.put(fieldName, value); - } - - Set locationComponents = new HashSet<>(); - - for (int i = 0; i < dataStream.getRecordStructure().getComponentCount(); i++) { - var component = dataStream.getRecordStructure().getComponent(i); - if (LOCATION_DEFINITIONS.contains(component.getDefinition())) { - // This is how we know we have location components in the data structure - // So we can save this and parse specifically the location components into GeoJSON - locationComponents.add(i); - } + resultsBuilder.putValues(fieldName, value); } - - - var resultWriter = resultWriters.computeIfAbsent(obs.getDataStreamID(), - k -> getSweCommonWriter(k, writer, ctx.getPropertyFilter()) ); - - var obsRes = obs.getResult().toString(); - - var obsName = dataStream.getOutputName(); - - - + OshObservation protoObs = OshObservation.newBuilder() + .setId(idEncoders.getObsIdEncoder().encodeID(key)) + .setDatastreamId(idEncoders.getDataStreamIdEncoder().encodeID(obs.getDataStreamID())) + .setFoiId(obs.getFoiID() != null + ? idEncoders.getFoiIdEncoder().encodeID(obs.getFoiID()) + : "") + .setPhenomenonTime(String.valueOf(obs.getPhenomenonTime().toEpochMilli())) + .setResultTime(String.valueOf(obs.getResultTime().toEpochMilli())) + .setResults(resultsBuilder.build()) + .build(); + + // serialize to bytes and write to output + byte[] bytes = protoObs.toByteArray(); + ctx.getOutputStream().write(bytes); + ctx.getOutputStream().flush(); } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java index 59b049883b..6000a8cb70 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsHandler.java @@ -155,6 +155,8 @@ else if (format.equals(ResourceFormat.GEO_JSON)) return new ObsBindingGeoJson(ctx, idEncoders, forReading, dataStore); else if (format.equals(ResourceFormat.COT_XML)) return new ObsBindingCotXml(ctx, idEncoders, forReading, dataStore); + else if (format.equals(ResourceFormat.PROTOBUF)) + return new ObsBindingProtobuf(ctx, idEncoders, forReading, dataStore); else return new ObsBindingSweCommon(ctx, idEncoders, forReading, dataStore); } diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java index 33800aac60..362a734ceb 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/proto/Observation.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! -// source: observation.proto +// source: include/osh-core/sensorhub-service-consys/src/main/proto/observation.proto -package obs; +package org.sensorhub.impl.service.consys.obs.proto; public final class Observation { private Observation() {} @@ -87,11 +87,11 @@ public interface OshObservationOrBuilder extends * .obs.Results results = 6; * @return The results. */ - obs.Observation.Results getResults(); + org.sensorhub.impl.service.consys.obs.proto.Observation.Results getResults(); /** * .obs.Results results = 6; */ - obs.Observation.ResultsOrBuilder getResultsOrBuilder(); + org.sensorhub.impl.service.consys.obs.proto.Observation.ResultsOrBuilder getResultsOrBuilder(); } /** * Protobuf type {@code obs.OshObservation} @@ -127,15 +127,15 @@ protected java.lang.Object newInstance( } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return obs.Observation.internal_static_obs_OshObservation_descriptor; + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_OshObservation_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return obs.Observation.internal_static_obs_OshObservation_fieldAccessorTable + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_OshObservation_fieldAccessorTable .ensureFieldAccessorsInitialized( - obs.Observation.OshObservation.class, obs.Observation.OshObservation.Builder.class); + org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation.class, org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation.Builder.class); } public static final int ID_FIELD_NUMBER = 1; @@ -334,7 +334,7 @@ public java.lang.String getResultTime() { } public static final int RESULTS_FIELD_NUMBER = 6; - private obs.Observation.Results results_; + private org.sensorhub.impl.service.consys.obs.proto.Observation.Results results_; /** * .obs.Results results = 6; * @return Whether the results field is set. @@ -348,15 +348,15 @@ public boolean hasResults() { * @return The results. */ @java.lang.Override - public obs.Observation.Results getResults() { - return results_ == null ? obs.Observation.Results.getDefaultInstance() : results_; + public org.sensorhub.impl.service.consys.obs.proto.Observation.Results getResults() { + return results_ == null ? org.sensorhub.impl.service.consys.obs.proto.Observation.Results.getDefaultInstance() : results_; } /** * .obs.Results results = 6; */ @java.lang.Override - public obs.Observation.ResultsOrBuilder getResultsOrBuilder() { - return results_ == null ? obs.Observation.Results.getDefaultInstance() : results_; + public org.sensorhub.impl.service.consys.obs.proto.Observation.ResultsOrBuilder getResultsOrBuilder() { + return results_ == null ? org.sensorhub.impl.service.consys.obs.proto.Observation.Results.getDefaultInstance() : results_; } private byte memoizedIsInitialized = -1; @@ -429,10 +429,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof obs.Observation.OshObservation)) { + if (!(obj instanceof org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation)) { return super.equals(obj); } - obs.Observation.OshObservation other = (obs.Observation.OshObservation) obj; + org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation other = (org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation) obj; if (!getId() .equals(other.getId())) return false; @@ -479,69 +479,69 @@ public int hashCode() { return hash; } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static obs.Observation.OshObservation parseFrom(byte[] data) + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static obs.Observation.OshObservation parseFrom(java.io.InputStream input) + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static obs.Observation.OshObservation parseDelimitedFrom(java.io.InputStream input) + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static obs.Observation.OshObservation parseDelimitedFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static obs.Observation.OshObservation parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -554,7 +554,7 @@ public static obs.Observation.OshObservation parseFrom( public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(obs.Observation.OshObservation prototype) { + public static Builder newBuilder(org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -575,21 +575,21 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements // @@protoc_insertion_point(builder_implements:obs.OshObservation) - obs.Observation.OshObservationOrBuilder { + org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservationOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return obs.Observation.internal_static_obs_OshObservation_descriptor; + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_OshObservation_descriptor; } @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return obs.Observation.internal_static_obs_OshObservation_fieldAccessorTable + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_OshObservation_fieldAccessorTable .ensureFieldAccessorsInitialized( - obs.Observation.OshObservation.class, obs.Observation.OshObservation.Builder.class); + org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation.class, org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation.Builder.class); } - // Construct using obs.Observation.OshObservation.newBuilder() + // Construct using org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation.newBuilder() private Builder() { } @@ -619,17 +619,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return obs.Observation.internal_static_obs_OshObservation_descriptor; + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_OshObservation_descriptor; } @java.lang.Override - public obs.Observation.OshObservation getDefaultInstanceForType() { - return obs.Observation.OshObservation.getDefaultInstance(); + public org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation getDefaultInstanceForType() { + return org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation.getDefaultInstance(); } @java.lang.Override - public obs.Observation.OshObservation build() { - obs.Observation.OshObservation result = buildPartial(); + public org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation build() { + org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -637,14 +637,14 @@ public obs.Observation.OshObservation build() { } @java.lang.Override - public obs.Observation.OshObservation buildPartial() { - obs.Observation.OshObservation result = new obs.Observation.OshObservation(this); + public org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation buildPartial() { + org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation result = new org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(obs.Observation.OshObservation result) { + private void buildPartial0(org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { result.id_ = id_; @@ -702,16 +702,16 @@ public Builder addRepeatedField( } @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof obs.Observation.OshObservation) { - return mergeFrom((obs.Observation.OshObservation)other); + if (other instanceof org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation) { + return mergeFrom((org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(obs.Observation.OshObservation other) { - if (other == obs.Observation.OshObservation.getDefaultInstance()) return this; + public Builder mergeFrom(org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation other) { + if (other == org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation.getDefaultInstance()) return this; if (!other.getId().isEmpty()) { id_ = other.id_; bitField0_ |= 0x00000001; @@ -1175,9 +1175,9 @@ public Builder setResultTimeBytes( return this; } - private obs.Observation.Results results_; + private org.sensorhub.impl.service.consys.obs.proto.Observation.Results results_; private com.google.protobuf.SingleFieldBuilderV3< - obs.Observation.Results, obs.Observation.Results.Builder, obs.Observation.ResultsOrBuilder> resultsBuilder_; + org.sensorhub.impl.service.consys.obs.proto.Observation.Results, org.sensorhub.impl.service.consys.obs.proto.Observation.Results.Builder, org.sensorhub.impl.service.consys.obs.proto.Observation.ResultsOrBuilder> resultsBuilder_; /** * .obs.Results results = 6; * @return Whether the results field is set. @@ -1189,9 +1189,9 @@ public boolean hasResults() { * .obs.Results results = 6; * @return The results. */ - public obs.Observation.Results getResults() { + public org.sensorhub.impl.service.consys.obs.proto.Observation.Results getResults() { if (resultsBuilder_ == null) { - return results_ == null ? obs.Observation.Results.getDefaultInstance() : results_; + return results_ == null ? org.sensorhub.impl.service.consys.obs.proto.Observation.Results.getDefaultInstance() : results_; } else { return resultsBuilder_.getMessage(); } @@ -1199,7 +1199,7 @@ public obs.Observation.Results getResults() { /** * .obs.Results results = 6; */ - public Builder setResults(obs.Observation.Results value) { + public Builder setResults(org.sensorhub.impl.service.consys.obs.proto.Observation.Results value) { if (resultsBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -1216,7 +1216,7 @@ public Builder setResults(obs.Observation.Results value) { * .obs.Results results = 6; */ public Builder setResults( - obs.Observation.Results.Builder builderForValue) { + org.sensorhub.impl.service.consys.obs.proto.Observation.Results.Builder builderForValue) { if (resultsBuilder_ == null) { results_ = builderForValue.build(); } else { @@ -1229,11 +1229,11 @@ public Builder setResults( /** * .obs.Results results = 6; */ - public Builder mergeResults(obs.Observation.Results value) { + public Builder mergeResults(org.sensorhub.impl.service.consys.obs.proto.Observation.Results value) { if (resultsBuilder_ == null) { if (((bitField0_ & 0x00000020) != 0) && results_ != null && - results_ != obs.Observation.Results.getDefaultInstance()) { + results_ != org.sensorhub.impl.service.consys.obs.proto.Observation.Results.getDefaultInstance()) { getResultsBuilder().mergeFrom(value); } else { results_ = value; @@ -1261,7 +1261,7 @@ public Builder clearResults() { /** * .obs.Results results = 6; */ - public obs.Observation.Results.Builder getResultsBuilder() { + public org.sensorhub.impl.service.consys.obs.proto.Observation.Results.Builder getResultsBuilder() { bitField0_ |= 0x00000020; onChanged(); return getResultsFieldBuilder().getBuilder(); @@ -1269,23 +1269,23 @@ public obs.Observation.Results.Builder getResultsBuilder() { /** * .obs.Results results = 6; */ - public obs.Observation.ResultsOrBuilder getResultsOrBuilder() { + public org.sensorhub.impl.service.consys.obs.proto.Observation.ResultsOrBuilder getResultsOrBuilder() { if (resultsBuilder_ != null) { return resultsBuilder_.getMessageOrBuilder(); } else { return results_ == null ? - obs.Observation.Results.getDefaultInstance() : results_; + org.sensorhub.impl.service.consys.obs.proto.Observation.Results.getDefaultInstance() : results_; } } /** * .obs.Results results = 6; */ private com.google.protobuf.SingleFieldBuilderV3< - obs.Observation.Results, obs.Observation.Results.Builder, obs.Observation.ResultsOrBuilder> + org.sensorhub.impl.service.consys.obs.proto.Observation.Results, org.sensorhub.impl.service.consys.obs.proto.Observation.Results.Builder, org.sensorhub.impl.service.consys.obs.proto.Observation.ResultsOrBuilder> getResultsFieldBuilder() { if (resultsBuilder_ == null) { resultsBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - obs.Observation.Results, obs.Observation.Results.Builder, obs.Observation.ResultsOrBuilder>( + org.sensorhub.impl.service.consys.obs.proto.Observation.Results, org.sensorhub.impl.service.consys.obs.proto.Observation.Results.Builder, org.sensorhub.impl.service.consys.obs.proto.Observation.ResultsOrBuilder>( getResults(), getParentForChildren(), isClean()); @@ -1310,12 +1310,12 @@ public final Builder mergeUnknownFields( } // @@protoc_insertion_point(class_scope:obs.OshObservation) - private static final obs.Observation.OshObservation DEFAULT_INSTANCE; + private static final org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new obs.Observation.OshObservation(); + DEFAULT_INSTANCE = new org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation(); } - public static obs.Observation.OshObservation getDefaultInstance() { + public static org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -1351,7 +1351,7 @@ public com.google.protobuf.Parser getParserForType() { } @java.lang.Override - public obs.Observation.OshObservation getDefaultInstanceForType() { + public org.sensorhub.impl.service.consys.obs.proto.Observation.OshObservation getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -1424,7 +1424,7 @@ protected java.lang.Object newInstance( } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return obs.Observation.internal_static_obs_Results_descriptor; + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_Results_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -1442,9 +1442,9 @@ protected com.google.protobuf.MapField internalGetMapField( @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return obs.Observation.internal_static_obs_Results_fieldAccessorTable + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_Results_fieldAccessorTable .ensureFieldAccessorsInitialized( - obs.Observation.Results.class, obs.Observation.Results.Builder.class); + org.sensorhub.impl.service.consys.obs.proto.Observation.Results.class, org.sensorhub.impl.service.consys.obs.proto.Observation.Results.Builder.class); } public static final int VALUES_FIELD_NUMBER = 1; @@ -1453,7 +1453,7 @@ private static final class ValuesDefaultEntryHolder { java.lang.String, java.lang.String> defaultEntry = com.google.protobuf.MapEntry .newDefaultInstance( - obs.Observation.internal_static_obs_Results_ValuesEntry_descriptor, + org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_Results_ValuesEntry_descriptor, com.google.protobuf.WireFormat.FieldType.STRING, "", com.google.protobuf.WireFormat.FieldType.STRING, @@ -1575,10 +1575,10 @@ public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof obs.Observation.Results)) { + if (!(obj instanceof org.sensorhub.impl.service.consys.obs.proto.Observation.Results)) { return super.equals(obj); } - obs.Observation.Results other = (obs.Observation.Results) obj; + org.sensorhub.impl.service.consys.obs.proto.Observation.Results other = (org.sensorhub.impl.service.consys.obs.proto.Observation.Results) obj; if (!internalGetValues().equals( other.internalGetValues())) return false; @@ -1602,69 +1602,69 @@ public int hashCode() { return hash; } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static obs.Observation.Results parseFrom(byte[] data) + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static obs.Observation.Results parseFrom(java.io.InputStream input) + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static obs.Observation.Results parseDelimitedFrom(java.io.InputStream input) + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static obs.Observation.Results parseDelimitedFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static obs.Observation.Results parseFrom( + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -1677,7 +1677,7 @@ public static obs.Observation.Results parseFrom( public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(obs.Observation.Results prototype) { + public static Builder newBuilder(org.sensorhub.impl.service.consys.obs.proto.Observation.Results prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } @java.lang.Override @@ -1698,10 +1698,10 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements // @@protoc_insertion_point(builder_implements:obs.Results) - obs.Observation.ResultsOrBuilder { + org.sensorhub.impl.service.consys.obs.proto.Observation.ResultsOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return obs.Observation.internal_static_obs_Results_descriptor; + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_Results_descriptor; } @SuppressWarnings({"rawtypes"}) @@ -1729,12 +1729,12 @@ protected com.google.protobuf.MapField internalGetMutableMapField( @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return obs.Observation.internal_static_obs_Results_fieldAccessorTable + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_Results_fieldAccessorTable .ensureFieldAccessorsInitialized( - obs.Observation.Results.class, obs.Observation.Results.Builder.class); + org.sensorhub.impl.service.consys.obs.proto.Observation.Results.class, org.sensorhub.impl.service.consys.obs.proto.Observation.Results.Builder.class); } - // Construct using obs.Observation.Results.newBuilder() + // Construct using org.sensorhub.impl.service.consys.obs.proto.Observation.Results.newBuilder() private Builder() { } @@ -1755,17 +1755,17 @@ public Builder clear() { @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return obs.Observation.internal_static_obs_Results_descriptor; + return org.sensorhub.impl.service.consys.obs.proto.Observation.internal_static_obs_Results_descriptor; } @java.lang.Override - public obs.Observation.Results getDefaultInstanceForType() { - return obs.Observation.Results.getDefaultInstance(); + public org.sensorhub.impl.service.consys.obs.proto.Observation.Results getDefaultInstanceForType() { + return org.sensorhub.impl.service.consys.obs.proto.Observation.Results.getDefaultInstance(); } @java.lang.Override - public obs.Observation.Results build() { - obs.Observation.Results result = buildPartial(); + public org.sensorhub.impl.service.consys.obs.proto.Observation.Results build() { + org.sensorhub.impl.service.consys.obs.proto.Observation.Results result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } @@ -1773,14 +1773,14 @@ public obs.Observation.Results build() { } @java.lang.Override - public obs.Observation.Results buildPartial() { - obs.Observation.Results result = new obs.Observation.Results(this); + public org.sensorhub.impl.service.consys.obs.proto.Observation.Results buildPartial() { + org.sensorhub.impl.service.consys.obs.proto.Observation.Results result = new org.sensorhub.impl.service.consys.obs.proto.Observation.Results(this); if (bitField0_ != 0) { buildPartial0(result); } onBuilt(); return result; } - private void buildPartial0(obs.Observation.Results result) { + private void buildPartial0(org.sensorhub.impl.service.consys.obs.proto.Observation.Results result) { int from_bitField0_ = bitField0_; if (((from_bitField0_ & 0x00000001) != 0)) { result.values_ = internalGetValues(); @@ -1822,16 +1822,16 @@ public Builder addRepeatedField( } @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof obs.Observation.Results) { - return mergeFrom((obs.Observation.Results)other); + if (other instanceof org.sensorhub.impl.service.consys.obs.proto.Observation.Results) { + return mergeFrom((org.sensorhub.impl.service.consys.obs.proto.Observation.Results)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(obs.Observation.Results other) { - if (other == obs.Observation.Results.getDefaultInstance()) return this; + public Builder mergeFrom(org.sensorhub.impl.service.consys.obs.proto.Observation.Results other) { + if (other == org.sensorhub.impl.service.consys.obs.proto.Observation.Results.getDefaultInstance()) return this; internalGetMutableValues().mergeFrom( other.internalGetValues()); bitField0_ |= 0x00000001; @@ -2030,12 +2030,12 @@ public final Builder mergeUnknownFields( } // @@protoc_insertion_point(class_scope:obs.Results) - private static final obs.Observation.Results DEFAULT_INSTANCE; + private static final org.sensorhub.impl.service.consys.obs.proto.Observation.Results DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new obs.Observation.Results(); + DEFAULT_INSTANCE = new org.sensorhub.impl.service.consys.obs.proto.Observation.Results(); } - public static obs.Observation.Results getDefaultInstance() { + public static org.sensorhub.impl.service.consys.obs.proto.Observation.Results getDefaultInstance() { return DEFAULT_INSTANCE; } @@ -2071,7 +2071,7 @@ public com.google.protobuf.Parser getParserForType() { } @java.lang.Override - public obs.Observation.Results getDefaultInstanceForType() { + public org.sensorhub.impl.service.consys.obs.proto.Observation.Results getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -2101,13 +2101,16 @@ public obs.Observation.Results getDefaultInstanceForType() { descriptor; static { java.lang.String[] descriptorData = { - "\n\021observation.proto\022\003obs\"\214\001\n\016OshObservat" + - "ion\022\n\n\002id\030\001 \001(\t\022\024\n\014datastreamId\030\002 \001(\t\022\r\n" + - "\005foiId\030\003 \001(\t\022\026\n\016phenomenonTime\030\004 \001(\t\022\022\n\n" + - "resultTime\030\005 \001(\t\022\035\n\007results\030\006 \001(\0132\014.obs." + - "Results\"b\n\007Results\022(\n\006values\030\001 \003(\0132\030.obs" + - ".Results.ValuesEntry\032-\n\013ValuesEntry\022\013\n\003k" + - "ey\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001b\006proto3" + "\nJinclude/osh-core/sensorhub-service-con" + + "sys/src/main/proto/observation.proto\022\003ob" + + "s\"\214\001\n\016OshObservation\022\n\n\002id\030\001 \001(\t\022\024\n\014data" + + "streamId\030\002 \001(\t\022\r\n\005foiId\030\003 \001(\t\022\026\n\016phenome" + + "nonTime\030\004 \001(\t\022\022\n\nresultTime\030\005 \001(\t\022\035\n\007res" + + "ults\030\006 \001(\0132\014.obs.Results\"b\n\007Results\022(\n\006v" + + "alues\030\001 \003(\0132\030.obs.Results.ValuesEntry\032-\n" + + "\013ValuesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t" + + ":\0028\001B:\n+org.sensorhub.impl.service.consy" + + "s.obs.protoB\013Observationb\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, diff --git a/sensorhub-service-consys/src/main/proto/observation.proto b/sensorhub-service-consys/src/main/proto/observation.proto index 3f791ca40e..132546c83a 100644 --- a/sensorhub-service-consys/src/main/proto/observation.proto +++ b/sensorhub-service-consys/src/main/proto/observation.proto @@ -2,6 +2,9 @@ syntax = "proto3"; package obs; +option java_package = "org.sensorhub.impl.service.consys.obs.proto"; +option java_outer_classname = "Observation"; + message OshObservation { string id = 1; From 3a894b0fc80fbc5a092adc5b4b2eea62b6a3c8ad Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 18 Jun 2026 09:04:14 -0500 Subject: [PATCH 14/15] links work, binary file is produced, verifying validity of results --- .../impl/service/consys/obs/ObsBindingProtobuf.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java index 3cfbc79936..0201db1673 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java @@ -265,9 +265,6 @@ protected JsonDataParserGson getSweCommonParser(IDataStreamInfo dsInfo, JsonRead public void startCollection() throws IOException { if (reader != null) { - // if we're reading, just skip to the items array - // calls to deserialize() will take it from there - // TODO generalize this to all bindings reader.beginObject(); while (reader.hasNext()) { var propName = reader.nextName(); @@ -277,14 +274,12 @@ public void startCollection() throws IOException reader.skipValue(); } } - else - startJsonCollection(writer); } @Override public void endCollection(Collection links) throws IOException { - endJsonCollection(writer, links); + //endJsonCollection(writer, links); } } From a36c323efe4972f80490ff0a0d6208ef97c1d135 Mon Sep 17 00:00:00 2001 From: ashley Date: Thu, 18 Jun 2026 10:02:55 -0500 Subject: [PATCH 15/15] cleaning up code, removing protowriter file, seems to work --- .../java/org/sensorhub/utils/ProtoWriter.java | 120 ------------------ .../consys/obs/ObsBindingProtobuf.java | 8 -- 2 files changed, 128 deletions(-) delete mode 100644 sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java diff --git a/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java b/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java deleted file mode 100644 index 4c9b4c68c6..0000000000 --- a/sensorhub-core/src/main/java/org/sensorhub/utils/ProtoWriter.java +++ /dev/null @@ -1,120 +0,0 @@ -/***************************** BEGIN LICENSE BLOCK *************************** - - Copyright (C) 2025 Botts Innovative Research, Inc. All Rights Reserved. - - ******************************* END LICENSE BLOCK ***************************/ -package org.sensorhub.utils; - -import net.opengis.swe.v20.*; -import org.sensorhub.api.command.ICommandStreamInfo; -import org.sensorhub.api.data.IDataStreamInfo; - -import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -public class ProtoWriter { - - private final StringBuilder sb; - private int indentLevel = 0; - // Protobuf fields MUST have a unique tag number starting at 1 - private int fieldTagCounter = 1; - - public ProtoWriter() { - this.sb = new StringBuilder(); - } - - public void writeProto(String systemName, IDataStreamInfo dsInfo) throws IOException { - startDocument(); - buildProtoForComponent(dsInfo.getRecordStructure()); - endDocument(systemName, dsInfo.getOutputName()); - } - - private void startDocument() { - sb.append("syntax = \"proto3\";\n\n"); - sb.append("message Record {\n"); - indentLevel++; - } - - private void buildProtoForComponent(DataComponent component) { - String name = cleanName(component.getName()); - - if (component instanceof DataChoice choice) { - writeLine("oneof " + name + " {"); - indentLevel++; - int tempTag = 1; - for (DataComponent item : choice.getItemList()) { - writeField(mapType(item), item.getName(), tempTag++); - } - indentLevel--; - writeLine("}"); - } - else if (component instanceof Category || component instanceof CategoryRange) { - writeField("string", name, fieldTagCounter++); - } - else if (component.getComponentCount() > 0) { - - writeLine("message " + capitalize(name) + " {"); - indentLevel++; - int savedCounter = fieldTagCounter; - fieldTagCounter = 1; - for (int i = 0; i < component.getComponentCount(); i++) { - buildProtoForComponent(component.getComponent(i)); - } - indentLevel--; - writeLine("}"); - writeField(capitalize(name), name, savedCounter); - fieldTagCounter = savedCounter + 1; - } - else { - // Simple scalars - writeField(mapType(component), name, fieldTagCounter++); - } - } - - private String mapType(DataComponent comp) { - if (comp instanceof Time) return "uint64"; - if (comp instanceof ScalarComponent scalar) { - return switch (scalar.getDataType()) { - case BOOLEAN -> "bool"; - case DOUBLE, FLOAT -> "double"; - case INT, SHORT, BYTE -> "int32"; - case LONG -> "int64"; - default -> "string"; - }; - } - return "string"; - } - - private void writeField(String type, String name, int tag) { - writeLine(type + " " + cleanName(name) + " = " + tag + ";"); - } - - private void writeLine(String text) { - sb.append(" ".repeat(indentLevel)).append(text).append("\n"); - } - - private String cleanName(String name) { - return name.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase(); - } - - private String capitalize(String str) { - return str.substring(0, 1).toUpperCase() + str.substring(1); - } - - private void endDocument(String systemName, String streamName) throws IOException { - indentLevel--; - sb.append("}\n"); - - systemName = systemName.replace(' ', '_'); - File file = new File("./schemas/" + systemName + "_" + streamName + ".proto"); - file.getParentFile().mkdirs(); - try (FileWriter fileWriter = new FileWriter(file)) { - fileWriter.write(sb.toString()); - } - } -} \ No newline at end of file diff --git a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java index 0201db1673..f2bc8c6046 100644 --- a/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java +++ b/sensorhub-service-consys/src/main/java/org/sensorhub/impl/service/consys/obs/ObsBindingProtobuf.java @@ -54,11 +54,7 @@ import java.time.OffsetDateTime; import java.time.format.DateTimeParseException; import java.util.*; -import java.io.File; -import org.sensorhub.utils.ProtoWriter; - -import javax.xml.stream.XMLStreamException; import static org.sensorhub.impl.service.consys.SWECommonUtils.OM_COMPONENTS_FILTER; @@ -183,16 +179,12 @@ else if ("result".equals(propName)) @Override public void serialize(BigId key, IObsData obs, boolean showLinks, JsonWriter writer) throws IOException { - ProtoWriter protoWriter = new ProtoWriter(); - - //protoWriter.writeProto(systemName, streamInfo); var dataStream = this.obsStore.getDataStreams().get(new DataStreamKey(obs.getDataStreamID())); var recordStruct = ((DataRecordImpl) dataStream.getRecordStructure()).getFieldList(); var resultBlock = ((DataBlockMixed) obs.getResult()).getUnderlyingObject(); // map osh fields to proto fields - //Map resultValues = new HashMap<>(); Results.Builder resultsBuilder = Results.newBuilder(); for (int i = 0; i < resultBlock.length; i++) { String fieldName = recordStruct.get(i).getName();