diff --git a/src/DotNetStac.Test/DotNetStac.Test.csproj b/src/DotNetStac.Test/DotNetStac.Test.csproj
index 72fb9dbd..ed5f4106 100644
--- a/src/DotNetStac.Test/DotNetStac.Test.csproj
+++ b/src/DotNetStac.Test/DotNetStac.Test.csproj
@@ -14,7 +14,6 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
diff --git a/src/DotNetStac/StacExtent.cs b/src/DotNetStac/Collection/StacExtent.cs
similarity index 89%
rename from src/DotNetStac/StacExtent.cs
rename to src/DotNetStac/Collection/StacExtent.cs
index 8e4d950b..de8ec1d9 100644
--- a/src/DotNetStac/StacExtent.cs
+++ b/src/DotNetStac/Collection/StacExtent.cs
@@ -1,10 +1,8 @@
-using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
-using Stac.Item;
-namespace Stac
+namespace Stac.Collection
{
[JsonObject]
public class StacExtent
@@ -15,7 +13,7 @@ public class StacExtent
[JsonProperty("temporal")]
public StacTemporalExtent Temporal { get; set; }
- public static StacExtent Create(IEnumerable items)
+ public static StacExtent Create(IEnumerable items)
{
return new StacExtent()
{
diff --git a/src/DotNetStac/Converters/StacExtensionsConverter.cs b/src/DotNetStac/Converters/StacExtensionsConverter.cs
new file mode 100644
index 00000000..7aff5ef2
--- /dev/null
+++ b/src/DotNetStac/Converters/StacExtensionsConverter.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Newtonsoft.Json;
+using Stac.Collection;
+using Stac.Extensions;
+using Stac.Extensions;
+
+namespace Stac.Converters
+{
+ internal class StacExtensionsConverter : JsonConverter
+ {
+ public override bool CanConvert(Type objectType)
+ {
+ return (objectType == typeof(IEnumerable));
+ }
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ IEnumerable extensions = serializer.Deserialize>(reader);
+
+ return new StacExtensions(extensions);
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ Dictionary summaries = (Dictionary)value;
+
+ serializer.Serialize(writer, summaries.ToDictionary(k => k.Key, k => k.Value.AsJToken));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/DotNetStac.csproj b/src/DotNetStac/DotNetStac.csproj
index 7430b433..1424b9da 100644
--- a/src/DotNetStac/DotNetStac.csproj
+++ b/src/DotNetStac/DotNetStac.csproj
@@ -21,10 +21,12 @@
-
+
+
+
diff --git a/src/DotNetStac/Exceptions/DuplicateKeyException.cs b/src/DotNetStac/Exceptions/DuplicateKeyException.cs
new file mode 100644
index 00000000..293c8c60
--- /dev/null
+++ b/src/DotNetStac/Exceptions/DuplicateKeyException.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Stac.Extensions
+{
+ [Serializable]
+ internal class DuplicateKeyException : Exception
+ {
+ public DuplicateKeyException()
+ {
+ }
+
+ public DuplicateKeyException(string message) : base(message)
+ {
+ }
+
+ public DuplicateKeyException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected DuplicateKeyException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/ExtensionNotAssignedException.cs b/src/DotNetStac/Exceptions/ExtensionNotAssignedException.cs
similarity index 96%
rename from src/DotNetStac/Extensions/ExtensionNotAssignedException.cs
rename to src/DotNetStac/Exceptions/ExtensionNotAssignedException.cs
index 1e0f19f3..4c6a59b0 100644
--- a/src/DotNetStac/Extensions/ExtensionNotAssignedException.cs
+++ b/src/DotNetStac/Exceptions/ExtensionNotAssignedException.cs
@@ -1,7 +1,7 @@
using System;
using System.Runtime.Serialization;
-namespace Stac.Extensions
+namespace Stac.Exceptions
{
[Serializable]
public class ExtensionNotAssignedException : Exception
diff --git a/src/DotNetStac/Exceptions/InvalidStacDataException.cs b/src/DotNetStac/Exceptions/InvalidStacDataException.cs
index 02ea3c97..e5cdcae5 100644
--- a/src/DotNetStac/Exceptions/InvalidStacDataException.cs
+++ b/src/DotNetStac/Exceptions/InvalidStacDataException.cs
@@ -1,7 +1,7 @@
using System;
using System.Runtime.Serialization;
-namespace Stac
+namespace Stac.Exceptions
{
[Serializable]
internal class InvalidStacDataException : Exception
diff --git a/src/DotNetStac/Exceptions/InvalidStacSchemaException.cs b/src/DotNetStac/Exceptions/InvalidStacSchemaException.cs
new file mode 100644
index 00000000..5d9aea1a
--- /dev/null
+++ b/src/DotNetStac/Exceptions/InvalidStacSchemaException.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Stac.Exceptions
+{
+ [Serializable]
+ internal class InvalidStacSchemaException : Exception
+ {
+ public InvalidStacSchemaException()
+ {
+ }
+
+ public InvalidStacSchemaException(string message) : base(message)
+ {
+ }
+
+ public InvalidStacSchemaException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected InvalidStacSchemaException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/AssignableStacExtension.cs b/src/DotNetStac/Extensions/AssignableStacExtension.cs
deleted file mode 100644
index 312af1bf..00000000
--- a/src/DotNetStac/Extensions/AssignableStacExtension.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System;
-using System.Reflection;
-using Newtonsoft.Json.Linq;
-using Stac.Item;
-
-namespace Stac.Extensions
-{
- public abstract class AssignableStacExtension : IStacExtension
- {
- private string prefix;
- private IStacPropertiesContainer stacPropertiesContainer;
-
- public AssignableStacExtension(string prefix, IStacObject stacObject) : this(prefix, stacObject as IStacPropertiesContainer)
- {
- }
-
- public AssignableStacExtension(string prefix, IStacPropertiesContainer stacPropertiesContainer)
- {
- this.prefix = prefix;
- this.stacPropertiesContainer = stacPropertiesContainer;
- if (stacPropertiesContainer is IStacObject)
- InitStacObject(stacPropertiesContainer as IStacObject);
-
- }
-
- public virtual string Id => prefix;
-
- public IStacObject StacObject
- {
- get
- {
- if (!(StacPropertiesContainer is IStacObject))
- throw new ExtensionNotAssignedException("Extension {0} is not assigned to a Stac object", Id);
- return stacPropertiesContainer as IStacObject;
- }
- }
-
- public IStacPropertiesContainer StacPropertiesContainer
- {
- get
- {
- if (stacPropertiesContainer == null)
- throw new ExtensionNotAssignedException("Extension {0} is not assigned to a Stac properties container", Id);
- return stacPropertiesContainer;
- }
- }
-
- public void InitStacObject(IStacObject stacObject)
- {
- stacObject.StacExtensions.Remove(prefix);
- stacObject.StacExtensions.Add(prefix, this);
- }
-
- protected void SetField(string key, object value)
- {
- StacPropertiesContainer.Properties.Remove(prefix + ":" + key);
- StacPropertiesContainer.Properties.Add(prefix + ":" + key, value);
- }
-
- protected object GetField(string fieldName)
- {
- string key = prefix + ":" + fieldName;
- if (!StacPropertiesContainer.Properties.ContainsKey(key))
- return null;
- return StacPropertiesContainer.Properties[key];
- }
-
- protected T GetField(string fieldName)
- {
- var @object = GetField(fieldName);
- if (@object == null) return default(T);
- if (@object is JToken)
- return (@object as JToken).ToObject();
- if (typeof(T).GetTypeInfo().IsEnum)
- return (T)Enum.Parse(typeof(T), @object.ToString());
- return (T)Convert.ChangeType(@object, typeof(T));
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/DummyStacExtension.cs b/src/DotNetStac/Extensions/DummyStacExtension.cs
new file mode 100644
index 00000000..40823bc5
--- /dev/null
+++ b/src/DotNetStac/Extensions/DummyStacExtension.cs
@@ -0,0 +1,12 @@
+namespace Stac.Extensions
+{
+ internal class DummyStacExtension : IStacExtension
+ {
+ public DummyStacExtension(string identifier)
+ {
+ Identifier = identifier;
+ }
+
+ public string Identifier { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/Eo/EoStacExtension.cs b/src/DotNetStac/Extensions/Eo/EoStacExtension.cs
index c171eaca..c1279dda 100644
--- a/src/DotNetStac/Extensions/Eo/EoStacExtension.cs
+++ b/src/DotNetStac/Extensions/Eo/EoStacExtension.cs
@@ -1,64 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Newtonsoft.Json.Linq;
-using Stac;
-using Stac.Extensions;
-using Stac.Item;
namespace Stac.Extensions.Eo
{
- public class EoStacExtension : AssignableStacExtension, IStacExtension
+ public class EoStacExtension : StacPropertiesContainerExtension, IStacExtension
{
+ private static IDictionary itemFields;
- public const string Prefix = "eo";
- public const string BandsField = "bands";
- public const string CloudCoverField = "cloud_cover";
+ public const string JsonSchemaUrl = "https://stac-extensions.github.io/eo/v1.0.0/schema.json";
+ public const string BandsField = "eo:bands";
+ public const string CloudCoverField = "eo:cloud_cover";
- public double CloudCover
- {
- get { return base.GetField(CloudCoverField); }
- set { base.SetField(CloudCoverField, value); }
- }
-
- public EoStacExtension(IStacObject stacObject) : base(Prefix, stacObject)
+ public EoStacExtension(IStacPropertiesContainer stacpropertiesContainer) : base(JsonSchemaUrl, stacpropertiesContainer)
{
+ itemFields = new Dictionary();
+ itemFields.Add(BandsField, typeof(EoBandObject[]) );
+ itemFields.Add(CloudCoverField, typeof(double) );
}
- public EoStacExtension(StacAsset stacAsset) : base(Prefix, stacAsset)
+ public double CloudCover
{
+ get { return StacPropertiesContainer.GetProperty(CloudCoverField); }
+ set { StacPropertiesContainer.SetProperty(CloudCoverField, value); }
}
public EoBandObject[] Bands
{
- get { return base.GetField(BandsField); }
- set { base.SetField(BandsField, value); }
+ get { return StacPropertiesContainer.GetProperty(BandsField); }
+ set { StacPropertiesContainer.SetProperty(BandsField, value); }
}
- public EoBandObject[] GetAssetBandObjects(StacAsset stacAsset)
+ public override IDictionary ItemFields => itemFields;
+ }
+
+ public static class EoStacExtensionExtensions
+ {
+ public static EoStacExtension EoExtension(this StacItem stacItem)
{
- string key = Id + ":" + BandsField;
- if (stacAsset.Properties.ContainsKey(key))
- return stacAsset.GetProperty(key);
- return null;
+ return new EoStacExtension(stacItem);
}
- public StacAsset GetAsset(EoBandCommonName commonName)
+ public static EoStacExtension EoExtension(this StacAsset stacAsset)
{
- StacItem item = null;
- try { item = StacObject as StacItem; }
- catch { }
- if (item != null)
- return item.Assets.Values.FirstOrDefault(a => GetAssetBandObjects(a).Any(b => b.CommonName == commonName));
- return null;
+ return new EoStacExtension(stacAsset);
}
- public void SetAssetBandObjects(StacAsset stacAsset, EoBandObject[] eoBandObjects)
+ public static StacAsset GetAsset(this StacItem stacItem, EoBandCommonName commonName)
{
- string key = Id + ":" + BandsField;
- if (stacAsset.Properties.ContainsKey(key))
- stacAsset.Properties.Remove(key);
- stacAsset.Properties.Add(key, eoBandObjects);
+ return stacItem.Assets.Values.FirstOrDefault(a => a.EoExtension().Bands.Any(b => b.CommonName == commonName));
}
}
}
diff --git a/src/DotNetStac/Extensions/Eo/EoStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Eo/EoStacExtensionExtensions.cs
index 8f898e86..bd541688 100644
--- a/src/DotNetStac/Extensions/Eo/EoStacExtensionExtensions.cs
+++ b/src/DotNetStac/Extensions/Eo/EoStacExtensionExtensions.cs
@@ -1,11 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Newtonsoft.Json.Linq;
-using Stac;
-using Stac.Extensions;
-using Stac.Item;
-
namespace Stac.Extensions.Eo
{
public static class EoStacExtensionExtensions
diff --git a/src/DotNetStac/Extensions/GenericStacExtension.cs b/src/DotNetStac/Extensions/GenericStacExtension.cs
index 3366b838..3bc38561 100644
--- a/src/DotNetStac/Extensions/GenericStacExtension.cs
+++ b/src/DotNetStac/Extensions/GenericStacExtension.cs
@@ -1,13 +1,13 @@
-using System;
-using Stac.Item;
+using Newtonsoft.Json.Schema;
namespace Stac.Extensions
{
- public class GenericStacExtension : AssignableStacExtension
+ public class GenericStacExtension : StacPropertiesContainerExtension
{
- public GenericStacExtension(string prefix, IStacObject stacObject) : base(prefix, stacObject)
+ public GenericStacExtension(JSchema jsonSchema, string fieldNamePrefix) : base(jsonSchema, fieldNamePrefix)
{
}
+ // TODO helpers to dicover automatically the fields
}
}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/IStacExtension.cs b/src/DotNetStac/Extensions/IStacExtension.cs
index 638c2fa2..28679c43 100644
--- a/src/DotNetStac/Extensions/IStacExtension.cs
+++ b/src/DotNetStac/Extensions/IStacExtension.cs
@@ -1,10 +1,11 @@
-using Stac.Item;
+using System;
+using System.Collections.Generic;
namespace Stac.Extensions
{
public interface IStacExtension
{
- string Id { get; }
+ string Identifier { get; }
}
}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/ITypeStacExtension.cs b/src/DotNetStac/Extensions/ITypeStacExtension.cs
new file mode 100644
index 00000000..d22c4d86
--- /dev/null
+++ b/src/DotNetStac/Extensions/ITypeStacExtension.cs
@@ -0,0 +1,6 @@
+namespace Stac.Extensions
+{
+ internal interface ITypeStacExtension
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs b/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs
index da614820..19b7b5c1 100644
--- a/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs
+++ b/src/DotNetStac/Extensions/Processing/ProcessingStacExtension.cs
@@ -1,18 +1,13 @@
-using System;
using System.Collections.Generic;
using System.Collections.Specialized;
-using System.Linq;
-using Newtonsoft.Json.Linq;
-using ProjNet.CoordinateSystems;
-using Stac;
-using Stac.Extensions;
-using Stac.Item;
+using Stac.Model;
namespace Stac.Extensions.Processing
{
- public class ProcessingStacExtension : AssignableStacExtension, IStacExtension
+ public class ProcessingStacExtension : StacPropertiesContainerExtension, IStacExtension
{
+ public const string JsonSchemaUrl = "https://stac-extensions.github.io/processing/v1.0.0/schema.json";
public const string Prefix = "processing";
public const string LineageField = "lineage";
public const string LevelField = "level";
diff --git a/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs b/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs
index c478c140..809e5e08 100644
--- a/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs
+++ b/src/DotNetStac/Extensions/Projection/ProjectionStacExtension.cs
@@ -1,18 +1,12 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Newtonsoft.Json.Linq;
using ProjNet.CoordinateSystems;
-using Stac;
-using Stac.Extensions;
-using Stac.Item;
namespace Stac.Extensions.Projection
{
- public class ProjectionStacExtension : AssignableStacExtension, IStacExtension
+ public class ProjectionStacExtension : StacPropertiesContainerExtension, IStacExtension
{
- public const string Prefix = "proj";
+ public const string JsonSchemaUrl = "https://stac-extensions.github.io/projection/v1.0.0/schema.json";
+
public const string EpsgField = "epsg";
public const string Wkt2Field = "wkt2";
@@ -29,7 +23,7 @@ public string Wkt2
set { base.SetField(Wkt2Field, value); }
}
- public ProjectionStacExtension(IStacObject stacObject) : base(Prefix, stacObject)
+ public ProjectionStacExtension(IStacObject stacObject) : base()
{
}
diff --git a/src/DotNetStac/Extensions/Sar/SarStacExtension.cs b/src/DotNetStac/Extensions/Sar/SarStacExtension.cs
index b9dad982..124d67c3 100644
--- a/src/DotNetStac/Extensions/Sar/SarStacExtension.cs
+++ b/src/DotNetStac/Extensions/Sar/SarStacExtension.cs
@@ -1,143 +1,154 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Newtonsoft.Json.Linq;
-using Stac;
-using Stac.Extensions;
-using Stac.Item;
namespace Stac.Extensions.Sar
{
- public class SarStacExtension : AssignableStacExtension, IStacExtension
+ public class SarStacExtension : StacPropertiesContainerExtension, IStacExtension
{
- public const string Prefix = "sar";
-
- public const string InstrumentModeField = "instrument_mode";
- public const string FrequencyBandField = "frequency_band";
- public const string CenterFrequencyField = "center_frequency";
- public const string PolarizationsField = "polarizations";
- public const string ProductTypeField = "product_type";
- public const string ResolutionRangeField = "resolution_range";
- public const string ResolutionAzimuthField = "resolution_azimuth";
- public const string PixelSpacingRangeField = "pixel_spacing_range";
- public const string PixelSpacingAzimuthField = "pixel_spacing_azimuth";
- public const string LooksRangeField = "looks_range";
- public const string LooksAzimuthField = "looks_azimuth";
- public const string LooksEquivalentNumberField = "looks_equivalent_number";
- public const string ObservationDirectionField = "observation_direction";
-
- internal SarStacExtension(IStacObject stacObject) : base(Prefix, stacObject)
- {
- }
-
- public SarStacExtension(IStacObject stacObject, string instrumentMode, SarCommonFrequencyBandName frequencyBandName, string[] polarizations, string productType) : base(Prefix, stacObject)
- {
- InstrumentMode = instrumentMode;
- FrequencyBand = frequencyBandName;
- Polarizations = polarizations;
- ProductType = productType;
+ public const string JsonSchemaUrl = "https://stac-extensions.github.io/sar/v1.0.0/schema.json";
+
+ public const string InstrumentModeField = "sar:instrument_mode";
+ public const string FrequencyBandField = "sar:frequency_band";
+ public const string CenterFrequencyField = "sar:center_frequency";
+ public const string PolarizationsField = "sar:polarizations";
+ public const string ProductTypeField = "sar:product_type";
+ public const string ResolutionRangeField = "sar:resolution_range";
+ public const string ResolutionAzimuthField = "sar:resolution_azimuth";
+ public const string PixelSpacingRangeField = "sar:pixel_spacing_range";
+ public const string PixelSpacingAzimuthField = "sar:pixel_spacing_azimuth";
+ public const string LooksRangeField = "sar:looks_range";
+ public const string LooksAzimuthField = "sar:looks_azimuth";
+ public const string LooksEquivalentNumberField = "sar:looks_equivalent_number";
+ public const string ObservationDirectionField = "sar:observation_direction";
+ private readonly IDictionary itemFields;
+
+ internal SarStacExtension(IStacPropertiesContainer stacPropertiesContainer) : base(JsonSchemaUrl, stacPropertiesContainer)
+ {
+ itemFields = new Dictionary();
+ itemFields.Add(InstrumentModeField, typeof(string[]));
+ itemFields.Add(FrequencyBandField, typeof(SarCommonFrequencyBandName));
+ itemFields.Add(CenterFrequencyField, typeof(double));
+ itemFields.Add(PolarizationsField, typeof(string[]));
+ itemFields.Add(ProductTypeField, typeof(string));
+ itemFields.Add(ResolutionRangeField, typeof(double));
+ itemFields.Add(ResolutionAzimuthField, typeof(double));
+ itemFields.Add(PixelSpacingRangeField, typeof(double));
+ itemFields.Add(PixelSpacingAzimuthField, typeof(double));
+ itemFields.Add(LooksRangeField, typeof(double));
+ itemFields.Add(LooksAzimuthField, typeof(double));
+ itemFields.Add(LooksEquivalentNumberField, typeof(double));
+ itemFields.Add(ObservationDirectionField, typeof(string));
}
public string InstrumentMode
{
- get { return base.GetField(InstrumentModeField); }
- set { base.SetField(InstrumentModeField, value); }
+ get { return StacPropertiesContainer.GetProperty(InstrumentModeField); }
+ set { StacPropertiesContainer.SetProperty(InstrumentModeField, value); }
}
public SarCommonFrequencyBandName FrequencyBand
{
- get { return base.GetField(FrequencyBandField); }
- set { base.SetField(FrequencyBandField, value); }
+ get { return StacPropertiesContainer.GetProperty(FrequencyBandField); }
+ set { StacPropertiesContainer.SetProperty(FrequencyBandField, value); }
}
public double CenterFrequency
{
- get { return base.GetField(CenterFrequencyField); }
- set { base.SetField(CenterFrequencyField, value); }
+ get { return StacPropertiesContainer.GetProperty(CenterFrequencyField); }
+ set { StacPropertiesContainer.SetProperty(CenterFrequencyField, value); }
}
public string[] Polarizations
{
- get { return base.GetField(PolarizationsField); }
- set { base.SetField(PolarizationsField, value); }
+ get { return StacPropertiesContainer.GetProperty(PolarizationsField); }
+ set { StacPropertiesContainer.SetProperty(PolarizationsField, value); }
}
public string ProductType
{
- get { return base.GetField(ProductTypeField); }
- set { base.SetField(ProductTypeField, value); }
+ get { return StacPropertiesContainer.GetProperty(ProductTypeField); }
+ set { StacPropertiesContainer.SetProperty(ProductTypeField, value); }
}
public double ResolutionRange
{
- get { return base.GetField(ResolutionRangeField); }
- set { base.SetField(ResolutionRangeField, value); }
+ get { return StacPropertiesContainer.GetProperty(ResolutionRangeField); }
+ set { StacPropertiesContainer.SetProperty(ResolutionRangeField, value); }
}
public double ResolutionAzimuth
{
- get { return base.GetField(ResolutionAzimuthField); }
- set { base.SetField(ResolutionAzimuthField, value); }
+ get { return StacPropertiesContainer.GetProperty(ResolutionAzimuthField); }
+ set { StacPropertiesContainer.SetProperty(ResolutionAzimuthField, value); }
}
public double PixelSpacingRange
{
- get { return base.GetField(PixelSpacingRangeField); }
- set { base.SetField(PixelSpacingRangeField, value); }
+ get { return StacPropertiesContainer.GetProperty(PixelSpacingRangeField); }
+ set { StacPropertiesContainer.SetProperty(PixelSpacingRangeField, value); }
}
public double PixelSpacingAzimuth
{
- get { return base.GetField(PixelSpacingAzimuthField); }
- set { base.SetField(PixelSpacingAzimuthField, value); }
+ get { return StacPropertiesContainer.GetProperty(PixelSpacingAzimuthField); }
+ set { StacPropertiesContainer.SetProperty(PixelSpacingAzimuthField, value); }
}
public double LooksRange
{
- get { return base.GetField(LooksRangeField); }
- set { base.SetField(LooksRangeField, value); }
+ get { return StacPropertiesContainer.GetProperty(LooksRangeField); }
+ set { StacPropertiesContainer.SetProperty(LooksRangeField, value); }
}
public double LooksAzimuth
{
- get { return base.GetField(LooksAzimuthField); }
- set { base.SetField(LooksAzimuthField, value); }
+ get { return StacPropertiesContainer.GetProperty(LooksAzimuthField); }
+ set { StacPropertiesContainer.SetProperty(LooksAzimuthField, value); }
}
public double LooksEquivalentNumber
{
- get { return base.GetField(LooksEquivalentNumberField); }
- set { base.SetField(LooksEquivalentNumberField, value); }
+ get { return StacPropertiesContainer.GetProperty(LooksEquivalentNumberField); }
+ set { StacPropertiesContainer.SetProperty(LooksEquivalentNumberField, value); }
}
public string ObservationDirection
{
- get { return base.GetField(ObservationDirectionField); }
- set { base.SetField(ObservationDirectionField, value); }
+ get { return StacPropertiesContainer.GetProperty(ObservationDirectionField); }
+ set { StacPropertiesContainer.SetProperty(ObservationDirectionField, value); }
}
+ }
- public static string[] GetAssetPolarization(StacAsset stacAsset)
+ public static class SarStacExtensionExtensions
+ {
+ public static SarStacExtension SarExtension(this StacItem stacItem)
{
- string key = Prefix + ":" + PolarizationsField;
- if (stacAsset.Properties.ContainsKey(key))
- return (string[])stacAsset.Properties[key];
- return null;
+ return new SarStacExtension(stacItem);
}
- public StacAsset GetAsset(string polarization)
+ public static SarStacExtension SarExtension(this StacAsset stacAsset)
{
- StacItem item = StacObject as StacItem;
- if (item == null) return null;
- return item.Assets.Values.FirstOrDefault(a => GetAssetPolarization(a).Contains(polarization));
+ return new SarStacExtension(stacAsset);
}
- public static void SetAssetBandObjects(StacAsset stacAsset, string[] polarizations)
+ public static StacAsset GetAsset(this StacItem stacItem, string polarization)
{
- string key = Prefix + ":" + PolarizationsField;
- if (stacAsset.Properties.ContainsKey(key))
- stacAsset.Properties.Remove(key);
- stacAsset.Properties.Add(key, polarizations);
+ return stacItem.Assets.Values.FirstOrDefault(a => a.SarExtension().Polarizations.Contains(polarization));
}
+ public static void Required(this SarStacExtension sarStacExtension,
+ string instrumentMode,
+ SarCommonFrequencyBandName frequencyBandName,
+ string[] polarizations,
+ string productType)
+ {
+ sarStacExtension.InstrumentMode = instrumentMode;
+ sarStacExtension.FrequencyBand = frequencyBandName;
+ sarStacExtension.Polarizations = polarizations;
+ sarStacExtension.ProductType = productType;
+ }
}
+
+
}
diff --git a/src/DotNetStac/Extensions/Sar/SarStacExtensionExtensions.cs b/src/DotNetStac/Extensions/Sar/SarStacExtensionExtensions.cs
deleted file mode 100644
index ff224809..00000000
--- a/src/DotNetStac/Extensions/Sar/SarStacExtensionExtensions.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace Stac.Extensions.Sar
-{
- public static class SarStacExtensionExtensions
- {
-
- public static string[] GetPolarizations(this StacAsset stacAsset)
- {
- string key = Sar.SarStacExtension.Prefix + ":" + Sar.SarStacExtension.PolarizationsField;
- if (stacAsset.Properties.ContainsKey(key))
- return (string[])stacAsset.Properties[key];
- return null;
- }
-
- public static void SetEoBandObjects(this StacAsset stacAsset, string[] eoBandObjects)
- {
- string key = Sar.SarStacExtension.Prefix + ":" + Sar.SarStacExtension.PolarizationsField;
- if (stacAsset.Properties.ContainsKey(key))
- stacAsset.Properties.Remove(key);
- stacAsset.Properties.Add(key, eoBandObjects);
- }
-
- }
-}
diff --git a/src/DotNetStac/Extensions/Sat/SatStacExtension.cs b/src/DotNetStac/Extensions/Sat/SatStacExtension.cs
index bd03d9d0..f16879ef 100644
--- a/src/DotNetStac/Extensions/Sat/SatStacExtension.cs
+++ b/src/DotNetStac/Extensions/Sat/SatStacExtension.cs
@@ -2,15 +2,12 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
-using Stac;
-using Stac.Extensions;
-using Stac.Item;
namespace Stac.Extensions.Sat
{
- public class SatStacExtension : AssignableStacExtension, IStacExtension
+ public class SatStacExtension : StacPropertiesContainerExtension, IStacExtension
{
- public const string Prefix = "sat";
+ public const string JsonSchemaUrl = "https://stac-extensions.github.io/sat/v1.0.0/schema.json";
public const string OrbitStateVectorField = "orbit_state_vectors";
public const string AscendingNodeCrossingDateTimeField = "anx_datetime";
public const string SceneCenterCoordinatesField = "scene_center_coordinates";
@@ -20,6 +17,10 @@ public class SatStacExtension : AssignableStacExtension, IStacExtension
public const string PlatformInternationalDesignatorField = "platform_international_designator";
+ public SatStacExtension(IStacObject stacObject) : base(JsonSchemaUrl, "sat", stacObject)
+ {
+ }
+
public SortedDictionary OrbitStateVectors
{
get
@@ -73,16 +74,14 @@ public string OrbitState
private SortedDictionary SortOrbitStateVectors(JToken osvarray)
{
if (!(osvarray is JArray))
- throw new FormatException(string.Format("[{0}] field {1}: not an array", Id, OrbitStateVectorField));
+ throw new FormatException(string.Format("[{0}] field {1}: not an array", FieldNamePrefix, OrbitStateVectorField));
var osvlist = osvarray.ToObject>();
return new SortedDictionary(osvlist.ToDictionary(osv => osv.Time, osv => osv));
}
- public SatStacExtension(IStacObject stacObject) : base(Prefix, stacObject)
- {
- }
+
}
}
diff --git a/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs b/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs
index 61b8cc71..c9b8e706 100644
--- a/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs
+++ b/src/DotNetStac/Extensions/Sat/SatStacExtensionHelpers.cs
@@ -11,13 +11,13 @@ public static class SatStacExtensionHelpers
{
public static BaselineVector CalculateBaseline(this SatStacExtension sat1, SatStacExtension sat2)
{
- if (sat1.StacObject.IsCatalog)
- throw new OperationCanceledException(string.Format("{0} must be an item to calculate baseline", sat1.StacObject.Id));
- if (sat2.StacObject.IsCatalog)
- throw new OperationCanceledException(string.Format("{0} must be an item to calculate baseline", sat1.StacObject.Id));
+ if (!(sat1.StacItem is StacItem))
+ throw new OperationCanceledException(string.Format("{0} must be an item to calculate baseline", sat1.StacItem.Id));
+ if (!(sat2.StacItem is StacItem))
+ throw new OperationCanceledException(string.Format("{0} must be an item to calculate baseline", sat1.StacItem.Id));
- IStacItem masterItem = sat1.StacObject as IStacItem;
- IStacItem slaveItem = sat2.StacObject as IStacItem;
+ StacItem masterItem = sat1.StacItem as StacItem;
+ StacItem slaveItem = sat2.StacItem as StacItem;
if (sat1.OrbitStateVectors.Count() == 0)
throw new OperationCanceledException("sat1 has no orbit state vectors");
diff --git a/src/DotNetStac/Extensions/SchemaBasedStacExtension.cs b/src/DotNetStac/Extensions/SchemaBasedStacExtension.cs
new file mode 100644
index 00000000..f56e2222
--- /dev/null
+++ b/src/DotNetStac/Extensions/SchemaBasedStacExtension.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using Stac.Exceptions;
+
+namespace Stac.Extensions
+{
+ public class SchemaBasedStacExtension : StacPropertiesContainerExtension, IStacExtension
+ {
+ private readonly IStacObject stacObject;
+
+ public SchemaBasedStacExtension(JSchema jsonSchema,
+ IStacObject stacObject) : base(jsonSchema.Id.ToString(),
+ null,
+ stacObject)
+ {
+ Preconditions.CheckNotNull(jsonSchema, "jsonSchema");
+ JsonSchema = jsonSchema;
+ this.stacObject = stacObject;
+ }
+
+ public SchemaBasedStacExtension(Uri schemaUri,
+ StacSchemaResolver stacSchemaResolver,
+ IStacObject stacObject) : base(schemaUri.ToString(),
+ null,
+ stacObject)
+ {
+ Preconditions.CheckNotNull(schemaUri, "schemaUri");
+ this.stacObject = stacObject;
+ JsonSchema = stacSchemaResolver.LoadSchema(schemaUri.ToString());
+ }
+
+
+ public static SchemaBasedStacExtension Create(string shortcut,
+ StacSchemaResolver stacSchemaResolver,
+ IStacObject stacObject)
+ {
+ if ( StacSchemaResolver.CoreTypes.Contains(shortcut) )
+ throw new Exceptions.InvalidStacSchemaException(shortcut + "is not an extension");
+ var jsonSchema = stacSchemaResolver.LoadSchema(version: stacObject.StacVersion.ToString(), shortcut: shortcut);
+ return new SchemaBasedStacExtension(jsonSchema, stacObject);
+ }
+
+ public override string Identifier => JsonSchema.Id.ToString();
+
+ public JSchema JsonSchema { get; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/StacAssetExtension.cs b/src/DotNetStac/Extensions/StacAssetExtension.cs
new file mode 100644
index 00000000..3128ee35
--- /dev/null
+++ b/src/DotNetStac/Extensions/StacAssetExtension.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using Stac.Exceptions;
+
+namespace Stac.Extensions
+{
+ public abstract class StacAssetExtension : IStacExtension
+ {
+ private readonly string identifier;
+
+ public StacAssetExtension(string identifier, StacAsset stacAsset)
+ {
+ this.identifier = identifier;
+ StacAsset = stacAsset;
+ }
+
+ public virtual string Identifier => identifier;
+
+ public StacAsset StacAsset { get; private set; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/StacExtensions.cs b/src/DotNetStac/Extensions/StacExtensions.cs
deleted file mode 100644
index 334bb07e..00000000
--- a/src/DotNetStac/Extensions/StacExtensions.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using Stac.Item;
-
-namespace Stac.Extensions
-{
- public class StacExtensions : Dictionary, IEnumerable
- {
- public StacExtensions(IEnumerable stacExtensions = null)
- {
- if (stacExtensions != null)
- {
- foreach (var stacExtension in stacExtensions)
- {
- Add(stacExtension);
- }
- }
- }
-
- public void InitStacObject(IStacObject stacObject)
- {
- foreach (var stacExtension in Values.OfType().ToList())
- {
- stacExtension.InitStacObject(stacObject);
- }
- }
-
- public void Add(IStacExtension extension)
- {
- Add(extension.Id, extension);
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.Values.GetEnumerator();
- }
- }
-}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/StacExtensionsConverter.cs b/src/DotNetStac/Extensions/StacExtensionsConverter.cs
deleted file mode 100644
index 407a926e..00000000
--- a/src/DotNetStac/Extensions/StacExtensionsConverter.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Newtonsoft.Json;
-
-namespace Stac
-{
- internal class StacExtensionsConverter : JsonConverter
- {
- public override bool CanConvert(Type objectType)
- {
- return (objectType == typeof(IEnumerable));
- }
-
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
- {
- Dictionary summaries = new Dictionary();
- Dictionary objDic = serializer.Deserialize>(reader);
-
- foreach (var key in objDic.Keys)
- {
- if (objDic[key] is JArray)
- {
- JArray enumerable = (objDic[key] as JArray);
- switch (enumerable.First().Type)
- {
- case JTokenType.Boolean:
- summaries.Add(key, new StacSummaryValueSet(enumerable));
- break;
- case JTokenType.Date:
- summaries.Add(key, new StacSummaryValueSet(enumerable));
- break;
- case JTokenType.String:
- summaries.Add(key, new StacSummaryValueSet(enumerable));
- break;
- case JTokenType.Integer:
- summaries.Add(key, new StacSummaryValueSet(enumerable));
- break;
- case JTokenType.Float:
- summaries.Add(key, new StacSummaryValueSet(enumerable));
- break;
- case JTokenType.Object:
- summaries.Add(key, new StacSummaryValueSet(enumerable));
- break;
- }
- }
- if (objDic[key] is JObject)
- {
- JObject obj = (objDic[key] as JObject);
- if (obj.ContainsKey("min") && obj.ContainsKey("max"))
- {
- switch (obj["min"].Type)
- {
- case JTokenType.Date:
- summaries.Add(key, new StacSummaryStatsObject(obj));
- break;
- case JTokenType.String:
- summaries.Add(key, new StacSummaryStatsObject(obj));
- break;
- case JTokenType.Integer:
- summaries.Add(key, new StacSummaryStatsObject(obj));
- break;
- case JTokenType.Float:
- summaries.Add(key, new StacSummaryStatsObject(obj));
- break;
- }
- }
- }
- }
-
- return summaries;
- }
-
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
- {
- Dictionary summaries = (Dictionary)value;
-
- serializer.Serialize(writer, summaries.ToDictionary(k => k.Key, k => k.Value.AsJToken));
- }
- }
-}
-}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/StacExtensionsFactory.cs b/src/DotNetStac/Extensions/StacExtensionsFactory.cs
deleted file mode 100644
index 91f1196b..00000000
--- a/src/DotNetStac/Extensions/StacExtensionsFactory.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Stac.Extensions
-{
- public class StacExtensionsFactory : IStacExtensionsFactory
- {
-
- Dictionary stacExtensionsDictionary = new Dictionary();
-
- public StacExtensionsFactory(Dictionary stacExtensions)
- {
- this.stacExtensionsDictionary = stacExtensions;
- }
-
- internal StacExtensionsFactory()
- {
- this.stacExtensionsDictionary.Add("sat", typeof(Sat.SatStacExtension));
- this.stacExtensionsDictionary.Add("eo", typeof(Eo.EoStacExtension));
- this.stacExtensionsDictionary.Add("view", typeof(View.ViewStacExtension));
- this.stacExtensionsDictionary.Add("proj", typeof(Projection.ProjectionStacExtension));
- this.stacExtensionsDictionary.Add("sar", typeof(Sar.SarStacExtension));
- }
-
- public static StacExtensionsFactory @default;
-
- public static StacExtensionsFactory Default
- {
- get
- {
- if (@default == null)
- @default = StacExtensionsFactory.CreateDefaultFactory();
- return @default;
- }
- }
-
- public Dictionary StacExtensionsDictionary => stacExtensionsDictionary;
-
- public static StacExtensionsFactory CreateDefaultFactory()
- {
- return new StacExtensionsFactory();
- }
-
- public IStacExtension InitStacExtension(string prefix, IStacObject stacObject)
- {
- if (stacExtensionsDictionary.ContainsKey(prefix))
- {
- var ctor = stacExtensionsDictionary[prefix].GetConstructor(new Type[1] { typeof(IStacObject) });
- if (ctor == null) return null;
- return (IStacExtension)ctor.Invoke(new object[1] { stacObject });
- }
-
- return new GenericStacExtension(prefix, stacObject);
- }
-
- public StacExtensions LoadStacExtensions(IEnumerable extensionPrefixes, IStacObject stacObject)
- {
- StacExtensions stacExtensions = new StacExtensions();
- if (extensionPrefixes != null)
- {
- foreach (var extensionPrefix in extensionPrefixes)
- {
- var stacExtension = InitStacExtension(extensionPrefix, stacObject);
- if (stacExtension != null)
- stacExtensions.Add(stacExtension);
- }
- }
- return stacExtensions;
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/StacPropertiesContainerExtension.cs b/src/DotNetStac/Extensions/StacPropertiesContainerExtension.cs
new file mode 100644
index 00000000..38c0f9b6
--- /dev/null
+++ b/src/DotNetStac/Extensions/StacPropertiesContainerExtension.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using Stac.Exceptions;
+
+namespace Stac.Extensions
+{
+ public abstract class StacPropertiesContainerExtension : IStacExtension
+ {
+ private readonly string identifier;
+
+ public StacPropertiesContainerExtension(string identifier, IStacPropertiesContainer stacPropertiesContainer)
+ {
+ this.identifier = identifier;
+ StacPropertiesContainer = stacPropertiesContainer;
+ }
+
+ public virtual string Identifier => identifier;
+
+ public IStacPropertiesContainer StacPropertiesContainer { get; private set; }
+
+ public abstract IDictionary ItemFields { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/Extensions/View/ViewStacExtension.cs b/src/DotNetStac/Extensions/View/ViewStacExtension.cs
index fbe902f1..3366ce2b 100644
--- a/src/DotNetStac/Extensions/View/ViewStacExtension.cs
+++ b/src/DotNetStac/Extensions/View/ViewStacExtension.cs
@@ -1,24 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Newtonsoft.Json.Linq;
-using Stac;
-using Stac.Extensions;
-using Stac.Item;
-
namespace Stac.Extensions.View
{
- public class ViewStacExtension : AssignableStacExtension, IStacExtension
+ public class ViewStacExtension : StacPropertiesContainerExtension, IStacExtension
{
+ public const string JsonSchemaUrl = "https://stac-extensions.github.io/sat/v1.0.0/schema.json";
public static string OffNadirField => "off_nadir";
public static string IncidenceAngleField => "incidence_angle";
public static string AzimuthField => "azimuth";
public static string SunAzimuthField => "sun_azimuth";
public static string SunElevationField => "sun_elevation";
-
- public ViewStacExtension(IStacObject stacObject) : base("view", stacObject)
+ public ViewStacExtension(IStacObject stacObject) : base(JsonSchemaUrl, "view", stacObject)
{
}
diff --git a/src/DotNetStac/IStacExtensionAssignable.cs b/src/DotNetStac/IStacExtensionAssignable.cs
deleted file mode 100644
index 427037eb..00000000
--- a/src/DotNetStac/IStacExtensionAssignable.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using Stac.Extensions;
-
-namespace Stac
-{
- public interface IStacExtensionAssignable
- {
- StacExtensions StacExtensions { get; }
- }
-}
\ No newline at end of file
diff --git a/src/DotNetStac/IStacObject.cs b/src/DotNetStac/IStacObject.cs
index 962efc26..3a24f7cf 100644
--- a/src/DotNetStac/IStacObject.cs
+++ b/src/DotNetStac/IStacObject.cs
@@ -11,7 +11,7 @@ namespace Stac
///
/// Common interface for all Stac objects
///
- public interface IStacObject : IStacPropertiesContainer, IStacExtensionAssignable
+ public interface IStacObject : IStacPropertiesContainer
{
string Id { get; }
@@ -19,5 +19,8 @@ public interface IStacObject : IStacPropertiesContainer, IStacExtensionAssignabl
Collection Links { get; }
+ ContentType MediaType { get; }
+
+ Collection StacExtensions { get; }
}
}
\ No newline at end of file
diff --git a/src/DotNetStac/IStacParent.cs b/src/DotNetStac/IStacParent.cs
index 2aec02bc..f3ea20ac 100644
--- a/src/DotNetStac/IStacParent.cs
+++ b/src/DotNetStac/IStacParent.cs
@@ -12,6 +12,6 @@ namespace Stac
///
public interface IStacParent : IStacObject
{
-
+
}
}
\ No newline at end of file
diff --git a/src/DotNetStac/Item/StacItemExtensions.cs b/src/DotNetStac/Item/StacItemExtensions.cs
deleted file mode 100644
index d58d9cb6..00000000
--- a/src/DotNetStac/Item/StacItemExtensions.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading.Tasks;
-using Stac;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Stac.Extensions;
-
-namespace Stac.Item
-{
- public partial class StacItem : IStacItem, IStacObject
- {
-
- public static async Task LoadUri(Uri uri)
- {
- var catalog = await StacFactory.LoadUriAsync(uri);
- if (catalog is IStacItem)
- return (IStacItem)catalog;
- throw new InvalidOperationException(string.Format("This is not a STAC item {0}", catalog.Uri));
- }
-
- public static async Task LoadStacLink(StacLink link)
- {
- var catalog = await link.LoadAsync();
- if (catalog is IStacItem)
- return (IStacItem)catalog;
- throw new InvalidOperationException(string.Format("This is not a STAC item {0}", catalog.Uri));
- }
-
- public static IStacItem LoadJToken(JToken jsonRoot, Uri uri)
- {
- IStacItem item = LoadStacItem(jsonRoot);
- ((IInternalStacObject)item).Uri = uri;
- return item;
- }
-
-
-
-
-
- }
-}
diff --git a/src/DotNetStac/Preconditions.cs b/src/DotNetStac/Preconditions.cs
index 2e69944a..e1d343ae 100644
--- a/src/DotNetStac/Preconditions.cs
+++ b/src/DotNetStac/Preconditions.cs
@@ -6,11 +6,11 @@ namespace Stac
{
public static class Preconditions
{
- public static T CheckNotNull(T value) where T : class
+ public static T CheckNotNull(T value, string argName = null) where T : class
{
if (value == null)
{
- throw new ArgumentNullException();
+ throw new ArgumentNullException(argName);
}
return value;
}
diff --git a/src/DotNetStac/Schemas/StacSchemaResolver.cs b/src/DotNetStac/Schemas/StacSchemaResolver.cs
new file mode 100644
index 00000000..34d8f04c
--- /dev/null
+++ b/src/DotNetStac/Schemas/StacSchemaResolver.cs
@@ -0,0 +1,76 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Schema;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Stac.Extensions
+{
+ public class StacSchemaResolver
+ {
+ private readonly JSchemaResolver jSchemaResolver;
+ private IDictionary schemaCompiled;
+
+ public static string[] CoreTypes = new string[] { "item", "catalog", "collection" };
+
+ public StacSchemaResolver(JSchemaResolver jSchemaResolver)
+ {
+ this.jSchemaResolver = jSchemaResolver;
+ this.schemaCompiled = new Dictionary();
+ }
+
+ private static IDictionary schemaMap = new Dictionary();
+
+ public JSchema LoadSchema(string baseUrl = null, string version = null, string shortcut = null)
+ {
+ string vversion = string.IsNullOrEmpty(version) ? "unversioned" : "v" + version;
+ Uri baseUri = null;
+ if (string.IsNullOrEmpty(baseUrl))
+ {
+ if (CoreTypes.Contains(shortcut))
+ baseUri = new Uri($"https://schemas.stacspec.org/{vversion}/");
+ else
+ baseUri = new Uri($"https://schemas.stacspec.org/");
+ }
+ else
+ baseUri = new Uri(baseUrl);
+
+ Uri schemaUri = null;
+ bool isExtension = false;
+ if (shortcut == "item" || shortcut == "catalog" || shortcut == "collection")
+ schemaUri = new Uri(baseUri, $"{shortcut}-spec/json-schema/{shortcut}.json");
+ else if (!string.IsNullOrEmpty(shortcut))
+ {
+ if (shortcut == "proj")
+ {
+ // Capture a very common mistake and give a better explanation (see #4)
+ throw new Exception("'stac_extensions' must contain 'projection instead of 'proj'.");
+ }
+ schemaUri = new Uri(baseUri, $"extensions/{shortcut}/json-schema/schema.json`");
+ isExtension = true;
+ }
+ else
+ {
+ schemaUri = baseUri;
+ }
+
+ if (!string.IsNullOrEmpty(baseUrl) && schemaMap.ContainsKey(baseUrl))
+ {
+ schemaUri = schemaMap[baseUrl];
+ }
+
+ if (schemaCompiled.ContainsKey(schemaUri.ToString()))
+ {
+ return schemaCompiled[schemaUri.ToString()];
+ }
+ else
+ {
+ var stream = jSchemaResolver.GetSchemaResource(null, new SchemaReference() { BaseUri = schemaUri } );
+ var sr = new StreamReader(stream);
+ schemaCompiled[schemaUri.ToString()] = JSchema.Parse(sr.ReadToEnd(), jSchemaResolver);
+ return schemaCompiled[schemaUri.ToString()];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/StacAccessorsHelpers.cs b/src/DotNetStac/StacAccessorsHelpers.cs
index b22d5a3d..ff4f17f9 100644
--- a/src/DotNetStac/StacAccessorsHelpers.cs
+++ b/src/DotNetStac/StacAccessorsHelpers.cs
@@ -13,9 +13,9 @@ public static void SetProperty(this IStacObject stacObject, string key, object v
stacObject.Properties.SetProperty(key, value);
}
- public static void SetProperty(this StacAsset stacAsset, string key, object value)
+ public static void SetProperty(this IStacPropertiesContainer stacPropertiesContainer, string key, object value)
{
- stacAsset.Properties.SetProperty(key, value);
+ stacPropertiesContainer.Properties.SetProperty(key, value);
}
public static void SetProperty(this IDictionary properties, string key, object value)
@@ -24,24 +24,14 @@ public static void SetProperty(this IDictionary properties, stri
properties.Add(key, value);
}
- public static object GetProperty(this IStacObject stacObject, string key)
+ public static object GetProperty(this IStacPropertiesContainer propertiesContainer, string key)
{
- return stacObject.Properties.GetProperty(key);
+ return propertiesContainer.Properties.GetProperty(key);
}
- public static T GetProperty(this IStacObject stacObject, string key)
+ public static T GetProperty(this IStacPropertiesContainer propertiesContainer, string key)
{
- return stacObject.Properties.GetProperty(key);
- }
-
- public static object GetProperty(this StacAsset stacAsset, string key)
- {
- return stacAsset.Properties.GetProperty(key);
- }
-
- public static T GetProperty(this StacAsset stacAsset, string key)
- {
- return stacAsset.Properties.GetProperty(key);
+ return propertiesContainer.Properties.GetProperty(key);
}
public static object GetProperty(this IDictionary properties, string key)
diff --git a/src/DotNetStac/StacCatalog.cs b/src/DotNetStac/StacCatalog.cs
index 263a44f6..cc09978f 100644
--- a/src/DotNetStac/StacCatalog.cs
+++ b/src/DotNetStac/StacCatalog.cs
@@ -6,6 +6,7 @@
using Stac.Extensions;
using System.Net.Mime;
using Semver;
+using System.Runtime.Serialization;
namespace Stac
{
@@ -44,7 +45,7 @@ public StacCatalog(string id, string description, IEnumerable links =
this.Links = new Collection(links.ToList());
this.Properties = new Dictionary();
this.Summaries = new Dictionary();
- this.StacExtensions = new StacExtensions();
+ this.StacExtensions = new StacExtensions(this);
}
# region IStacObject
@@ -82,6 +83,9 @@ public Collection Links
get; internal set;
}
+ [JsonIgnore]
+ public ContentType MediaType => CATALOG_MEDIATYPE;
+
# endregion IStacObject
///
@@ -118,5 +122,15 @@ public Collection Links
[JsonExtensionData]
public IDictionary Properties { get; internal set; }
+ [OnDeserialized]
+ internal void OnDeserializedMethod(StreamingContext context)
+ {
+ foreach (StacLink link in Links)
+ {
+ link.Parent = this;
+ }
+ StacExtensions.stacObject = this;
+ }
+
}
}
diff --git a/src/DotNetStac/StacCollection.cs b/src/DotNetStac/StacCollection.cs
index d92dafa9..29f8aa83 100644
--- a/src/DotNetStac/StacCollection.cs
+++ b/src/DotNetStac/StacCollection.cs
@@ -6,8 +6,10 @@
using Stac.Extensions;
using Semver;
using System.Linq;
+using System.Runtime.Serialization;
+using Stac.Collection;
-namespace Stac.Collection
+namespace Stac
{
///
/// STAC Collection Object implementing STAC Collection spec (https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md)
@@ -40,7 +42,7 @@ public StacCollection(string id,
else
this.Assets = new Dictionary(assets);
this.Summaries = new Dictionary();
- this.StacExtensions = new StacExtensions();
+ this.StacExtensions = new StacExtensions(this);
this.License = license;
this.Keywords = new Collection();
this.Extent = extent;
@@ -81,6 +83,9 @@ public Collection Links
get; internal set;
}
+ [JsonIgnore]
+ public ContentType MediaType => COLLECTION_MEDIATYPE;
+
# endregion IStacObject
///
@@ -149,5 +154,14 @@ public Collection Links
[JsonProperty("assets")]
public IDictionary Assets { get; internal set; }
+ [OnDeserialized]
+ internal void OnDeserializedMethod(StreamingContext context)
+ {
+ foreach (StacLink link in Links)
+ {
+ link.Parent = this;
+ }
+ StacExtensions.stacObject = this;
+ }
}
}
diff --git a/src/DotNetStac/StacExtensionsExtensions.cs b/src/DotNetStac/StacExtensionsExtensions.cs
new file mode 100644
index 00000000..316c350c
--- /dev/null
+++ b/src/DotNetStac/StacExtensionsExtensions.cs
@@ -0,0 +1,14 @@
+using Newtonsoft.Json.Schema;
+using Stac.Exceptions;
+
+namespace Stac.Extensions
+{
+ public static class StacExtensionsExtensions
+ {
+ public static void AddExtension(this IStacObject stacObject, JSchema jsonSchema)
+ {
+ if ( stacObject.StacExtensions.ContainsKey(jsonSchema.Id.ToString()))
+ throw new DuplicateKeyException(jsonSchema.Id.ToString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotNetStac/StacGeometryHelpers.cs b/src/DotNetStac/StacGeometryHelpers.cs
index f2869b29..3c2f8d16 100644
--- a/src/DotNetStac/StacGeometryHelpers.cs
+++ b/src/DotNetStac/StacGeometryHelpers.cs
@@ -1,15 +1,13 @@
-using System.Collections;
using System.Linq;
using GeoJSON.Net;
using GeoJSON.Net.Geometry;
-using Stac.Item;
namespace Stac
{
public static class StacGeometryHelpers
{
- public static double[] GetBoundingBoxFromGeometryExtent(this IStacItem stacItem)
+ public static double[] GetBoundingBoxFromGeometryExtent(this StacItem stacItem)
{
var boundingBoxes = stacItem.Geometry.GetBoundingBox();
if (boundingBoxes[0].Altitude.HasValue)
diff --git a/src/DotNetStac/StacItem.cs b/src/DotNetStac/StacItem.cs
index 9d380f69..afb184f1 100644
--- a/src/DotNetStac/StacItem.cs
+++ b/src/DotNetStac/StacItem.cs
@@ -10,131 +10,78 @@
using System.Linq;
using System.Net.Mime;
using Newtonsoft.Json.Linq;
+using Semver;
namespace Stac
{
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
- public class StacItem : GeoJSON.Net.Feature.Feature, IStacObject, IInternalStacObject, IStacItem
+ public class StacItem : GeoJSON.Net.Feature.Feature, IStacObject
{
public const string MEDIATYPE = "application/json; profile=stac-item";
public readonly static ContentType ITEM_MEDIATYPE = new ContentType(MEDIATYPE);
- private Collection links;
-
- private Dictionary assets;
-
- private string stacVersion = StacVersionList.Current;
-
- private string collection;
-
- private Uri sourceUri;
-
- private string[] stacExtensionsStrings = new string[0];
-
[JsonConstructor]
- public StacItem(IGeometryObject geometry, IDictionary properties = null, string id = null) : base(Preconditions.CheckNotNull(geometry), properties, id)
+ public StacItem(string id,
+ IGeometryObject geometry,
+ IDictionary properties = null) :
+ base(Preconditions.CheckNotNull(geometry, "geometry"), properties, id)
{
- if (geometry == null) throw new ArgumentNullException("geometry");
+ Preconditions.CheckNotNull(id, "id");
+ StacExtensions = new Collection();
+ StacVersion = Versions.StacVersionList.Current;
+ Links = new Collection();
+ Assets = new Dictionary();
}
- public StacItem(IGeometryObject geometry, object properties, string id = null) : base(Preconditions.CheckNotNull(geometry), properties, id)
+ public StacItem(StacItem stacItem) : base(Preconditions.CheckNotNull(stacItem, "geometry").Geometry,
+ new Dictionary(Preconditions.CheckNotNull(stacItem).Properties),
+ Preconditions.CheckNotNull(stacItem, "id").Id)
{
- if (geometry == null) throw new ArgumentNullException("geometry");
- if (properties == null) throw new ArgumentNullException("properties");
+ this.StacExtensions = stacItem.StacExtensions;
+ this.StacVersion = stacItem.StacVersion;
+ this.Links = new Collection(stacItem.Links);
+ this.Assets = new Dictionary(stacItem.Assets);
+ this.Collection = stacItem.Collection;
}
- public StacItem(StacItem stacItem) : this(Preconditions.CheckNotNull(stacItem).Geometry,
- new Dictionary(Preconditions.CheckNotNull(stacItem).Properties),
- Preconditions.CheckNotNull(stacItem).Id)
- {
- this.stacExtensionsStrings = stacItem.stacExtensionsStrings;
- this.stacVersion = stacItem.stacVersion;
- this.links = new Collection(stacItem.Links);
- this.assets = new Dictionary(stacItem.Assets);
- this.collection = stacItem.collection;
- this.sourceUri = stacItem.sourceUri;
- this.extensions = new StacExtensions(stacItem.StacExtensions);
- }
-
- private static IStacItem LoadStacItem(JToken jsonRoot)
- {
- Type itemType = null;
- if (jsonRoot["stac_version"] == null)
- {
- throw new InvalidStacDataException("The document is not a valid STAC document. No 'stac_version' property found");
- }
-
- try
- {
- itemType = Stac.Model.SchemaDictionary.GetItemTypeFromVersion(jsonRoot["stac_version"].Value());
- }
- catch (KeyNotFoundException)
- {
- throw new NotSupportedException(string.Format("The document has a non supprted version: '{0}'.", jsonRoot["stac_version"].Value()));
- }
-
- return (IStacItem)jsonRoot.ToObject(itemType);
- }
-
- [JsonProperty("stac_extensions")]
- public string[] StacExtensionsStrings { get => stacExtensionsStrings; set => stacExtensionsStrings = value; }
-
+ # region IStacObject
+ ///
+ /// The STAC version the Item implements
+ ///
+ ///
[JsonProperty("stac_version")]
- public string StacVersion
- {
- get
- {
- return stacVersion;
- }
+ public SemVersion StacVersion { get; set; }
- set
- {
- stacVersion = value;
- }
- }
+ ///
+ /// A list of extension identifiers the Item implements
+ ///
+ ///
+ [JsonProperty("stac_extensions")]
+ [JsonConverter(typeof(StacExtensionsConverter))]
+ public Collection StacExtensions { get; private set; }
+ ///
+ /// A list of references to other documents.
+ ///
+ ///
[JsonConverter(typeof(CollectionConverter))]
[JsonProperty("links")]
public Collection Links
{
- get
- {
- if (links == null)
- links = new Collection();
- return links;
- }
- set
- {
- links = value;
- }
+ get; private set;
}
- [JsonProperty("assets")]
- public IDictionary Assets
- {
- get
- {
- if (assets == null)
- assets = new Dictionary();
- return assets;
- }
- }
+ [JsonIgnore]
+ public ContentType MediaType => ITEM_MEDIATYPE;
- [JsonProperty("collection")]
- public string Collection
- {
- get
- {
- return collection;
- }
- set
- {
- collection = value;
- }
- }
+ # endregion IStacObject
+ [JsonProperty("assets")]
+ public IDictionary Assets { get; private set; }
+ [JsonProperty("collection")]
+ public string Collection { get; internal set; }
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context)
@@ -143,7 +90,7 @@ internal void OnDeserializedMethod(StreamingContext context)
{
link.Parent = this;
}
- StacExtensions = StacExtensionsFactory.Default.LoadStacExtensions(StacExtensionsStrings.ToList(), this);
+ StacExtensions.ResolveExtensions(this);
}
[OnSerializing]
@@ -151,29 +98,6 @@ internal void OnSerializingMethod(StreamingContext context)
{
if (BoundingBoxes == null)
BoundingBoxes = this.GetBoundingBoxFromGeometryExtent();
- StacExtensionsStrings = StacExtensionsStrings.Concat(StacExtensions.Keys).Distinct().ToArray();
- }
-
- [JsonIgnore]
- public ContentType MediaType => ITEM_MEDIATYPE;
-
- [JsonIgnore]
- public Uri Uri
- {
- get
- {
- if (sourceUri == null)
- {
- return new Uri(Id + ".json", UriKind.Relative);
- }
- return sourceUri;
- }
- set { sourceUri = value; }
- }
-
- public IStacObject Upgrade()
- {
- return this;
}
[JsonIgnore]
@@ -243,27 +167,6 @@ public Itenso.TimePeriod.ITimePeriod DateTime
}
}
- private StacExtensions extensions;
-
- [JsonIgnore]
- public StacExtensions StacExtensions
- {
- get
- {
- if (extensions == null)
- {
- extensions = new StacExtensions();
- extensions.InitStacObject(this);
- }
- return extensions;
- }
- set
- {
- extensions = value;
- extensions.InitStacObject(this);
- }
- }
-
[JsonIgnore]
public string Title
{
diff --git a/src/DotNetStac/StacLink.cs b/src/DotNetStac/StacLink.cs
index 5ac5ab98..518c34ca 100644
--- a/src/DotNetStac/StacLink.cs
+++ b/src/DotNetStac/StacLink.cs
@@ -1,10 +1,8 @@
using System;
-using System.Collections.Generic;
using System.IO;
using System.Net.Mime;
using System.Threading.Tasks;
using Newtonsoft.Json;
-using Stac.Converters;
namespace Stac
{
@@ -60,11 +58,6 @@ public static StacLink CreateItemLink(IStacObject stacObject, IStacObject hostOb
#endregion
- Uri href;
- protected string rel, title;
- ContentType type;
- protected IStacObject hostObject;
- protected readonly ulong contentLength;
public StacLink()
{
@@ -77,8 +70,8 @@ public StacLink(Uri uri)
public StacLink(Uri uri, IStacObject hostObject)
{
- Uri = uri;
- this.hostObject = hostObject;
+ this.Uri = uri;
+ this.Parent = hostObject;
}
public StacLink(Uri uri, string relationshipType, string title, string mediaType, ulong contentLength = 0)
@@ -86,90 +79,45 @@ public StacLink(Uri uri, string relationshipType, string title, string mediaType
Uri = uri;
RelationshipType = relationshipType;
Title = title;
- MediaType = mediaType == null ? null : new ContentType(mediaType);
- this.contentLength = contentLength;
+ ContentType = mediaType == null ? null : new ContentType(mediaType);
+ this.Length = contentLength;
}
public StacLink(StacLink source)
{
if (source == null)
throw new ArgumentNullException("source");
- href = source.href;
- rel = source.rel;
- title = source.title;
- type = source.type;
- hostObject = source.hostObject;
- contentLength = source.Length;
+ Uri = source.Uri;
+ RelationshipType = source.RelationshipType;
+ Title = source.Title;
+ ContentType = source.ContentType;
+ Parent = source.Parent;
+ Length = source.Length;
}
[JsonProperty("type")]
[JsonConverter(typeof(ContentTypeConverter))]
- public virtual ContentType MediaType
- {
- get { return type; }
- set { type = value; }
- }
+ public virtual ContentType ContentType { get; set; }
[JsonProperty("rel")]
- public virtual string RelationshipType
- {
- get { return rel; }
- set { rel = value; }
- }
+ public virtual string RelationshipType { get; set; }
[JsonProperty("title")]
- public virtual string Title
- {
- get { return title; }
- set { title = value; }
- }
+ public virtual string Title { get; set; }
[JsonProperty("href")]
- public virtual Uri Uri
- {
- get { return href; }
- set { href = value; }
- }
-
- [JsonIgnore]
- private Uri AbsoluteUri
- {
- get
- {
- if (Uri.IsAbsoluteUri)
- return Uri;
-
- if (hostObject != null)
- return new Uri(new Uri(hostObject.Uri.AbsoluteUri.Substring(0, hostObject.Uri.AbsoluteUri.LastIndexOf('/') + 1)), Uri);
-
- return null;
- }
- }
+ public virtual Uri Uri { get; set; }
[JsonIgnore]
- public IStacObject Parent
- {
- get => hostObject;
- internal set
- {
- hostObject = value;
- }
- }
+ public IStacObject Parent { get; set; }
[JsonIgnore]
- public ulong Length => contentLength;
+ public ulong Length { get; set; }
public virtual StacLink Clone()
{
return new StacLink(this);
}
- public virtual async Task LoadAsync()
- {
- if (AbsoluteUri == null)
- throw new FileNotFoundException(string.Format("Cannot load STAC object from link ({0}) : No absolute entry point", Uri));
- return await StacFactory.LoadUriAsync(AbsoluteUri);
- }
-
}
}
diff --git a/src/DotNetStac/StacNavigationHelpers.cs b/src/DotNetStac/StacNavigationHelpers.cs
deleted file mode 100644
index 5b623cd5..00000000
--- a/src/DotNetStac/StacNavigationHelpers.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Runtime.Serialization;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Stac.Catalog;
-using Stac.Collection;
-using Stac.Extensions;
-using Stac.Item;
-using Stac.Model;
-
-namespace Stac
-{
- public static class StacNavigationHelpers
- {
- public static void AddChild(this IStacObject stacObject, IStacItem stacItem)
- {
- stacObject.Links.Add(new StacObjectLink(stacItem, stacObject));
- }
-
- public static IDictionary GetChildren(this IStacObject stacObject)
- {
- return GetChildrenAsync(stacObject).GetAwaiter().GetResult();
- }
-
- public static async Task> GetChildrenAsync(this IStacObject stacObject)
- {
- Dictionary children = new Dictionary();
- foreach (var link in stacObject.Links.Where(l => l.RelationshipType == "child"))
- {
- children.Add(link.Uri, (await link.LoadAsync()) as IStacCatalog);
- }
- return children;
- }
-
- public static IDictionary GetItems(this IStacObject stacObject)
- {
- return GetItemsAsync(stacObject).GetAwaiter().GetResult();
- }
-
- public static async Task> GetItemsAsync(this IStacObject stacObject)
- {
- Dictionary items = new Dictionary();
- foreach (var link in stacObject.Links.Where(l => l.RelationshipType == "item"))
- {
- items.Add(link.Uri, await StacItem.LoadStacLink(link));
- }
- return items;
- }
-
- public static IEnumerable GetChildrenLinks(this IStacObject stacObject, bool absolute = true)
- {
- return stacObject.Links.Where(l => l.RelationshipType == "child");
- }
-
- public static IEnumerable GetItemLinks(this IStacObject stacObject, bool absolute = true)
- {
- return stacObject.Links.Where(l => l.RelationshipType == "item");
- }
-
- public static StacItem UpgradeToCurrentVersion(this IStacItem item1)
- {
- IStacObject item = (IStacObject)item1;
- while (!(item is Item.StacItem))
- {
- item = item.Upgrade();
- }
- return (Item.StacItem)item;
- }
-
- public static StacCatalog UpgradeToCurrentVersion(this IStacCatalog catalog1)
- {
- IStacObject catalog = (IStacObject)catalog1;
- while (!(catalog is StacCatalog))
- {
- catalog = catalog.Upgrade();
- }
- return (StacCatalog)catalog;
- }
-
- public static T GetExtension(this IStacObject stacObject) where T : IStacExtension
- {
- return (T)stacObject.StacExtensions.Values.FirstOrDefault(e => e is T);
- }
- }
-}
diff --git a/src/DotNetStac/StacObjectLink.cs b/src/DotNetStac/StacObjectLink.cs
index 6c34e0ec..49a0085c 100644
--- a/src/DotNetStac/StacObjectLink.cs
+++ b/src/DotNetStac/StacObjectLink.cs
@@ -14,15 +14,15 @@ internal StacObjectLink(IStacObject stacObject, IStacObject hostObject = null)
{
this.stacObject = stacObject;
this.hostObject = hostObject;
- if ( stacObject is IStacItem )
+ if ( stacObject is StacItem )
this.RelationshipType = "item";
- if ( stacObject is IStacCatalog )
+ if ( stacObject is StacCatalog || stacObject is StacCollection )
this.RelationshipType = "child";
}
[JsonProperty("type")]
[JsonConverter(typeof(ContentTypeConverter))]
- public override ContentType MediaType
+ public override ContentType ContentType
{
get => stacObject.MediaType;
set
@@ -58,10 +58,5 @@ public override Uri Uri
}
}
- public override Task LoadAsync()
- {
- return Task.FromResult(stacObject);
- }
-
}
}
diff --git a/src/DotNetStac/Utils.cs b/src/DotNetStac/Utils.cs
index 853b905e..1a0bc451 100644
--- a/src/DotNetStac/Utils.cs
+++ b/src/DotNetStac/Utils.cs
@@ -1,8 +1,6 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
-using Stac.Catalog;
-using Stac.Collection;
namespace Stac
{