3636import java .net .http .HttpResponse .BodySubscriber ;
3737import java .net .http .HttpResponse .BodySubscribers ;
3838import java .nio .charset .StandardCharsets ;
39+ import java .time .Instant ;
3940import java .util .Arrays ;
4041import java .util .Collection ;
4142import java .util .Collections ;
9697import org .vast .util .BaseBuilder ;
9798import com .google .common .base .Strings ;
9899import com .google .common .net .HttpHeaders ;
100+ import com .google .common .net .UrlEscapers ;
99101import com .google .gson .JsonObject ;
100102import com .google .gson .JsonParser ;
101103import com .google .gson .JsonSyntaxException ;
@@ -145,7 +147,7 @@ protected ConSysApiClient() {}
145147
146148 public CompletableFuture <IDerivedProperty > getPropertyById (String id , ResourceFormat format )
147149 {
148- return sendGetRequest (endpoint .resolve (PROPERTIES_COLLECTION + "/" + id ), format , body -> {
150+ return sendGetRequest (endpoint .resolve (PROPERTIES_COLLECTION + "/" + urlPathEncode ( id ) ), format , body -> {
149151 try
150152 {
151153 var ctx = new RequestContext (body );
@@ -257,7 +259,7 @@ protected void endJsonCollection(JsonWriter writer, Collection<ResourceLink> lin
257259
258260 public CompletableFuture <IProcedureWithDesc > getProcedureById (String id , ResourceFormat format )
259261 {
260- return sendGetRequest (endpoint .resolve (PROCEDURES_COLLECTION + "/" + id ), format , body -> {
262+ return sendGetRequest (endpoint .resolve (PROCEDURES_COLLECTION + "/" + urlPathEncode ( id ) ), format , body -> {
261263 try
262264 {
263265 var ctx = new RequestContext (body );
@@ -275,7 +277,7 @@ public CompletableFuture<IProcedureWithDesc> getProcedureById(String id, Resourc
275277
276278 public CompletableFuture <IProcedureWithDesc > getProcedureByUid (String uid , ResourceFormat format )
277279 {
278- return sendGetRequest (endpoint .resolve (PROCEDURES_COLLECTION + "?id=" + uid ), format , body -> {
280+ return sendGetRequest (endpoint .resolve (PROCEDURES_COLLECTION + "?id=" + urlQueryEncode ( uid ) ), format , body -> {
279281 try
280282 {
281283 var ctx = new RequestContext (body );
@@ -372,7 +374,7 @@ protected void endJsonCollection(JsonWriter writer, Collection<ResourceLink> lin
372374
373375 public CompletableFuture <ISystemWithDesc > getSystemById (String id , ResourceFormat format )
374376 {
375- return sendGetRequest (endpoint .resolve (SYSTEMS_COLLECTION + "/" + id ), format , body -> {
377+ return sendGetRequest (endpoint .resolve (SYSTEMS_COLLECTION + "/" + urlPathEncode ( id ) ), format , body -> {
376378 try
377379 {
378380 var ctx = new RequestContext (body );
@@ -390,7 +392,7 @@ public CompletableFuture<ISystemWithDesc> getSystemById(String id, ResourceForma
390392
391393 public CompletableFuture <ISystemWithDesc > getSystemByUid (String uid , ResourceFormat format ) throws ExecutionException , InterruptedException
392394 {
393- return sendGetRequest (endpoint .resolve (SYSTEMS_COLLECTION + "?id=" + uid ), format , body -> {
395+ return sendGetRequest (endpoint .resolve (SYSTEMS_COLLECTION + "?id=" + urlQueryEncode ( uid ) ), format , body -> {
394396 try
395397 {
396398 var ctx = new RequestContext (body );
@@ -571,10 +573,10 @@ public CompletableFuture<Integer> updateSamplingFeature(String featureId, IFeatu
571573 }
572574
573575
574- public CompletableFuture <IFeature > getSamplingFeatureById (String featureId )
576+ public CompletableFuture <IFeature > getSamplingFeatureById (String id )
575577 {
576578 return sendGetRequest (
577- endpoint .resolve (SF_COLLECTION + "/" + featureId ),
579+ endpoint .resolve (SF_COLLECTION + "/" + urlPathEncode ( id ) ),
578580 ResourceFormat .GEOJSON ,
579581 body -> {
580582 try
@@ -593,7 +595,7 @@ public CompletableFuture<IFeature> getSamplingFeatureById(String featureId)
593595
594596 public CompletableFuture <IFeature > getSamplingFeatureByUid (String uid , ResourceFormat format )
595597 {
596- return sendGetRequest (endpoint .resolve (SF_COLLECTION + "?id=" + uid ), format , body -> {
598+ return sendGetRequest (endpoint .resolve (SF_COLLECTION + "?id=" + urlQueryEncode ( uid ) ), format , body -> {
597599 try
598600 {
599601 var ctx = new RequestContext (body );
@@ -637,9 +639,9 @@ public CompletableFuture<Stream<IFeature>> getSystemSamplingFeatures(String syst
637639 }
638640
639641
640- protected CompletableFuture <Stream <IFeature >> getSystemSamplingFeatures (String systemId , ResourceFormat format , int pageSize , int offset )
642+ protected CompletableFuture <Stream <IFeature >> getSystemSamplingFeatures (String sysId , ResourceFormat format , int pageSize , int offset )
641643 {
642- var request = SYSTEMS_COLLECTION + "/" + systemId + "/" + SF_COLLECTION + "?f=" + format + "&limit=" + pageSize + "&offset=" + offset ;
644+ var request = SYSTEMS_COLLECTION + "/" + urlPathEncode ( sysId ) + "/" + SF_COLLECTION + "?f=" + format + "&limit=" + pageSize + "&offset=" + offset ;
643645 log .debug ("{}" , request );
644646
645647 return sendGetRequest (endpoint .resolve (request ), format , body -> {
@@ -716,7 +718,7 @@ public Spliterator<IFeature> trySplit()
716718
717719 public CompletableFuture <IDataStreamInfo > getDatastreamById (String id , ResourceFormat format , boolean fetchSchema )
718720 {
719- var cf1 = sendGetRequest (endpoint .resolve (DATASTREAMS_COLLECTION + "/" + id ), format , body -> {
721+ var cf1 = sendGetRequest (endpoint .resolve (DATASTREAMS_COLLECTION + "/" + urlPathEncode ( id ) ), format , body -> {
720722 try
721723 {
722724 var ctx = new RequestContext (body );
@@ -751,8 +753,8 @@ public CompletableFuture<IDataStreamInfo> getDatastreamById(String id, ResourceF
751753
752754 public CompletableFuture <IDataStreamInfo > getDatastreamSchema (String id , ResourceFormat obsFormat , ResourceFormat format )
753755 {
754- var obsFormatStr = URLEncoder . encode (obsFormat .getMimeType (), StandardCharsets . UTF_8 );
755- return sendGetRequest (endpoint .resolve (DATASTREAMS_COLLECTION + "/" + id + "/schema?obsFormat=" +obsFormatStr ), format , body -> {
756+ var obsFormatStr = urlQueryEncode (obsFormat .getMimeType ());
757+ return sendGetRequest (endpoint .resolve (DATASTREAMS_COLLECTION + "/" + urlPathEncode ( id ) + "/schema?obsFormat=" +obsFormatStr ), format , body -> {
756758 try
757759 {
758760 var ctx = new RequestContext (body );
@@ -772,7 +774,7 @@ public CompletableFuture<IDataStreamInfo> getDatastreamSchema(String id, Resourc
772774 }
773775
774776
775- public CompletableFuture <String > addDataStream (String systemId , IDataStreamInfo datastream )
777+ public CompletableFuture <String > addDataStream (String sysId , IDataStreamInfo datastream )
776778 {
777779 try
778780 {
@@ -783,7 +785,7 @@ public CompletableFuture<String> addDataStream(String systemId, IDataStreamInfo
783785 binding .serialize (null , datastream , false );
784786
785787 return sendPostRequest (
786- endpoint .resolve (SYSTEMS_COLLECTION + "/" + systemId + "/" + DATASTREAMS_COLLECTION ),
788+ endpoint .resolve (SYSTEMS_COLLECTION + "/" + urlPathEncode ( sysId ) + "/" + DATASTREAMS_COLLECTION ),
787789 ResourceFormat .JSON ,
788790 buffer .toByteArray ());
789791 }
@@ -800,7 +802,7 @@ public CompletableFuture<Set<String>> addDataStreams(String systemId, IDataStrea
800802 }
801803
802804
803- public CompletableFuture <Set <String >> addDataStreams (String systemId , Collection <IDataStreamInfo > datastreams )
805+ public CompletableFuture <Set <String >> addDataStreams (String sysId , Collection <IDataStreamInfo > datastreams )
804806 {
805807 try
806808 {
@@ -826,7 +828,7 @@ protected void endJsonCollection(JsonWriter writer, Collection<ResourceLink> lin
826828 binding .endCollection (Collections .emptyList ());
827829
828830 return sendBatchPostRequest (
829- endpoint .resolve (SYSTEMS_COLLECTION + "/" + systemId + "/" + DATASTREAMS_COLLECTION ),
831+ endpoint .resolve (SYSTEMS_COLLECTION + "/" + urlPathEncode ( sysId ) + "/" + DATASTREAMS_COLLECTION ),
830832 ResourceFormat .JSON ,
831833 buffer .toByteArray ());
832834 }
@@ -841,7 +843,7 @@ protected void endJsonCollection(JsonWriter writer, Collection<ResourceLink> lin
841843 /* Control Streams */
842844 /*-----------------*/
843845
844- public CompletableFuture <String > addControlStream (String systemId , ICommandStreamInfo cmdstream )
846+ public CompletableFuture <String > addControlStream (String sysId , ICommandStreamInfo cmdstream )
845847 {
846848 try
847849 {
@@ -852,7 +854,7 @@ public CompletableFuture<String> addControlStream(String systemId, ICommandStrea
852854 binding .serializeCreate (cmdstream );
853855
854856 return sendPostRequest (
855- endpoint .resolve (SYSTEMS_COLLECTION + "/" + systemId + "/" + CONTROLSTREAMS_COLLECTION ),
857+ endpoint .resolve (SYSTEMS_COLLECTION + "/" + urlPathEncode ( sysId ) + "/" + CONTROLSTREAMS_COLLECTION ),
856858 ResourceFormat .JSON ,
857859 buffer .toByteArray ());
858860 }
@@ -869,7 +871,7 @@ public CompletableFuture<Set<String>> addControlStreams(String systemId, IComman
869871 }
870872
871873
872- public CompletableFuture <Set <String >> addControlStreams (String systemId , Collection <ICommandStreamInfo > cmdstreams )
874+ public CompletableFuture <Set <String >> addControlStreams (String sysId , Collection <ICommandStreamInfo > cmdstreams )
873875 {
874876 try
875877 {
@@ -895,7 +897,7 @@ protected void endJsonCollection(JsonWriter writer, Collection<ResourceLink> lin
895897 binding .endCollection (Collections .emptyList ());
896898
897899 return sendBatchPostRequest (
898- endpoint .resolve (SYSTEMS_COLLECTION + "/" + systemId + "/" + CONTROLSTREAMS_COLLECTION ),
900+ endpoint .resolve (SYSTEMS_COLLECTION + "/" + urlPathEncode ( sysId ) + "/" + CONTROLSTREAMS_COLLECTION ),
899901 ResourceFormat .JSON ,
900902 buffer .toByteArray ());
901903 }
@@ -908,7 +910,7 @@ protected void endJsonCollection(JsonWriter writer, Collection<ResourceLink> lin
908910
909911 public CompletableFuture <ICommandStreamInfo > getControlStreamById (String id , ResourceFormat format , boolean fetchSchema )
910912 {
911- var cf1 = sendGetRequest (endpoint .resolve (CONTROLSTREAMS_COLLECTION + "/" + id ), format , body -> {
913+ var cf1 = sendGetRequest (endpoint .resolve (CONTROLSTREAMS_COLLECTION + "/" + urlPathEncode ( id ) ), format , body -> {
912914 try
913915 {
914916 var ctx = new RequestContext (body );
@@ -943,7 +945,8 @@ public CompletableFuture<ICommandStreamInfo> getControlStreamById(String id, Res
943945
944946 public CompletableFuture <ICommandStreamInfo > getControlStreamSchema (String id , ResourceFormat obsFormat , ResourceFormat format )
945947 {
946- return sendGetRequest (endpoint .resolve (CONTROLSTREAMS_COLLECTION + "/" + id + "/schema?obsFormat=" + obsFormat ), format , body -> {
948+ var obsFormatStr = urlQueryEncode (format .getMimeType ());
949+ return sendGetRequest (endpoint .resolve (CONTROLSTREAMS_COLLECTION + "/" + urlPathEncode (id ) + "/schema?obsFormat=" + obsFormatStr ), format , body -> {
947950 try
948951 {
949952 var ctx = new RequestContext (body );
@@ -963,13 +966,13 @@ public CompletableFuture<ICommandStreamInfo> getControlStreamSchema(String id, R
963966 /* Observations */
964967 /*--------------*/
965968 // TODO: Be able to push different kinds of observations such as video
966- public CompletableFuture <String > pushObs (String dataStreamId , IDataStreamInfo dataStream , IObsData obs )
969+ public CompletableFuture <String > pushObs (String dsId , IDataStreamInfo dataStream , IObsData obs )
967970 {
968971 try
969972 {
970973 var buffer = new ByteArrayOutputStream ();
971974 var ctx = new RequestContext (buffer );
972- ctx .setParent (null , dataStreamId , obs .getDataStreamID ());
975+ ctx .setParent (null , dsId , obs .getDataStreamID ());
973976 ObsHandler .ObsHandlerContextData contextData = new ObsHandler .ObsHandlerContextData ();
974977 contextData .dsInfo = dataStream ;
975978 ctx .setData (contextData );
@@ -986,7 +989,7 @@ public CompletableFuture<String> pushObs(String dataStreamId, IDataStreamInfo da
986989 }
987990
988991 return sendPostRequest (
989- endpoint .resolve (DATASTREAMS_COLLECTION + "/" + dataStreamId + "/" + OBSERVATIONS_COLLECTION ),
992+ endpoint .resolve (DATASTREAMS_COLLECTION + "/" + urlPathEncode ( dsId ) + "/" + OBSERVATIONS_COLLECTION ),
990993 ctx .getFormat (),
991994 buffer .toByteArray ());
992995 }
@@ -1017,7 +1020,7 @@ public CompletableFuture<Stream<IObsData>> getObservations(String dsId, IDataStr
10171020
10181021 protected CompletableFuture <Stream <IObsData >> getObservations (String dsId , IDataStreamInfo dsInfo , TemporalFilter timeFilter , Set <String > foiIds , ResourceFormat format , int pageSize , int offset )
10191022 {
1020- var request = DATASTREAMS_COLLECTION + "/" + dsId + "/observations?f=" + format + "&limit=" + pageSize + "&offset=" + offset ;
1023+ var request = DATASTREAMS_COLLECTION + "/" + urlPathEncode ( dsId ) + "/observations?f=" + format + "&limit=" + pageSize + "&offset=" + offset ;
10211024
10221025 if (foiIds != null )
10231026 request += "&foi=" + String .join ("," , foiIds );
@@ -1026,6 +1029,24 @@ protected CompletableFuture<Stream<IObsData>> getObservations(String dsId, IData
10261029 {
10271030 if (timeFilter .isLatestTime ())
10281031 request += "&resultTime=latest" ;
1032+ else {
1033+ request += "&phenomenonTime=" ;
1034+
1035+ if (timeFilter .isCurrentTime ())
1036+ request += "now" ;
1037+ else if (timeFilter .endsNow ())
1038+ request += timeFilter .getMin () + "/now" ;
1039+ else if (timeFilter .beginsNow ())
1040+ request += "now/" + timeFilter .getMax ();
1041+ else if (timeFilter .isAllTimes ())
1042+ request += "../.." ;
1043+ else if (timeFilter .getMin () == Instant .MIN )
1044+ request += "../" + timeFilter .getMax ();
1045+ else if (timeFilter .getMax () == Instant .MAX )
1046+ request += timeFilter .getMin () + "/.." ;
1047+ else
1048+ request += timeFilter .getMin () + "/" + timeFilter .getMax ();
1049+ }
10291050 }
10301051
10311052 return sendGetRequest (endpoint .resolve (request ), format , body -> {
@@ -1098,13 +1119,13 @@ public Spliterator<IObsData> trySplit()
10981119 /* Commands */
10991120 /*----------*/
11001121
1101- public CompletableFuture <ICommandStatus > sendCommand (String controlstreamId , ICommandStreamInfo cmdStream , ICommandData cmd )
1122+ public CompletableFuture <ICommandStatus > sendCommand (String csId , ICommandStreamInfo cmdStream , ICommandData cmd )
11021123 {
11031124 try
11041125 {
11051126 var buffer = new ByteArrayOutputStream ();
11061127 var ctx = new RequestContext (buffer );
1107- ctx .setParent (null , controlstreamId , cmd .getCommandStreamID ());
1128+ ctx .setParent (null , csId , cmd .getCommandStreamID ());
11081129 var contextData = new CommandHandler .CommandHandlerContextData ();
11091130 contextData .csInfo = cmdStream ;
11101131 ctx .setData (contextData );
@@ -1121,7 +1142,7 @@ public CompletableFuture<ICommandStatus> sendCommand(String controlstreamId, ICo
11211142 }
11221143
11231144 return sendPostRequestAndReadResponse (
1124- endpoint .resolve (CONTROLSTREAMS_COLLECTION + "/" + controlstreamId + "/" + COMMANDS_COLLECTION ),
1145+ endpoint .resolve (CONTROLSTREAMS_COLLECTION + "/" + urlPathEncode ( csId ) + "/" + COMMANDS_COLLECTION ),
11251146 ctx .getFormat (),
11261147 buffer .toByteArray (),
11271148 responseBody -> {
@@ -1568,6 +1589,18 @@ protected void skipToCollectionItems(JsonReader reader) throws IOException
15681589 }
15691590
15701591
1592+ protected String urlPathEncode (String value )
1593+ {
1594+ return UrlEscapers .urlPathSegmentEscaper ().escape (value );
1595+ }
1596+
1597+
1598+ protected String urlQueryEncode (String value )
1599+ {
1600+ return URLEncoder .encode (value , StandardCharsets .UTF_8 );
1601+ }
1602+
1603+
15711604 public void setAuthToken (String token )
15721605 {
15731606 this .token = token ;
0 commit comments