public IEnumerable<JObject> ReadElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("elevation", JObject.FromObject(element));

            //If not a feature return null;
            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadSequenceNumberElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            int v;
            currentObject.AddToProperties("sequenceNumber", int.TryParse(element.Value, out v) ? (JToken)v:(JToken)element.Value);

            return Enumerable.Empty<JObject>();
        }
 public void WriteSequenceNumberElement(IAixmConverter converter, int flow, JObject feature, XmlWriter writer)
 {
     if (flow == 0)
     {
         WriteStringElement(feature, writer, "sequenceNumber", "aixm", "sequenceNumber");
     }
 }
        public void WriteElement(IAixmConverter converter, int flow, JObject feature, XmlWriter writer)
        {
            var validTime = feature["properties"]["avalibility"];
              var type = feature["properties"]["AixmType"];
              if (type != null)
              {
                  if (flow == 0)
                  {
                      writer.WriteStartElement("aixm", "timeSlice", null);
                      writer.WriteStartElement("aixm", type.ToString() + "TimeSlice", null);
                      if (validTime != null)
                      {
                          writer.WriteStartElement("gml", "validTime", null);
                          writer.WriteStartElement("gml", "TimePeriod", null);

                          writer.WriteElementString("gml", "beginPosition", null, "");
                          writer.WriteElementString("gml", "endPosition", null, "");

                          writer.WriteEndElement();
                          writer.WriteEndElement();
                      }
                     
                  }
                  else
                  {
                      writer.WriteEndElement();
                      writer.WriteEndElement();
                  }
              }
        }
 public void WriteAixmTypeElement(IAixmConverter converter, int flow, JObject feature, XmlWriter writer)
 {
     if (flow == 0)
     {
         WriteStringElement(feature, writer, "aixmType", "aixm", "type");
     }
 }
        public void WriteElement(IAixmConverter converter, int flow, JObject feature, XmlWriter writer)
        {
            var id = feature["properties"]["id"];

            if (flow == 0)
            {
                if (id != null)
                {
                    if (id is JObject)
                    {
                        writer.WriteStartElement("gml", "identifier", null);
                        var obj = id as JObject;
                        foreach(var prop in obj.Properties().Where(p=>p.Name.StartsWith("@")))
                        { 
                            writer.WriteAttributeString(prop.Name.Substring(1), prop.Value.ToString());
                        }
                        writer.WriteValue(id["#text"].ToString());
                        writer.WriteEndElement();


                    }else{
                        writer.WriteElementString("gml", "identifier", null, id.ToString());
                    }
                }   
            }
            else
            {
               

            }
        }
        public IEnumerable<JObject> ReadElementElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
           
            var elementElement = element.Elements().ToArray();
            if(elementElement.Length != 1)
            {
                throw new NotSupportedException("ReadElementElement do not support more than one nested element");
            }
         
            var id = currentObject["properties"]["id"];
            currentObject.SetGeometry(new JObject());
            var obj = new JObject(new JProperty("properties",new JObject(
                new JProperty("elementSource",elementElement[0].Name.LocalName),
                new JProperty("parent", id is JObject ? id["#text"].ToString() : id.ToString())
                )));

            //Need to yield the current feature when going to sub types.
            //When no sub features are returned the current feature is automaticly returned for all other cases.
            yield return currentObject;

            foreach (var feature in converter.ReadElement(obj, elementElement[0].Elements()).ToList())
            {
                yield return feature;
            }
            
       
          
        }
 public IEnumerable<JObject> ReadElevatedSurfaceElement(IAixmConverter converter, JObject currentObject, XElement element)
 {
   
     //Read elevation property and return
     return ReadSurfaceElement(converter, currentObject, element).Concat(
         converter.ReadElement(currentObject, element.Elements(aximNs + "elevation")));
 }
 public IEnumerable<JObject> ReadElement(IAixmConverter converter, JObject currentObject, XElement element)
 {
     var AixmElement = element.Elements().First();
     var feature = new JObject(new JProperty("type","Feature"));
     feature.AddToProperties("AixmType", AixmElement.Name.LocalName.ToString());
     return converter.ReadElement(feature, AixmElement.Elements());
 }
 public void WriteInterpretationElement(IAixmConverter converter, int flow, JObject feature, XmlWriter writer)
 {
     if (flow == 0)
     {
         WriteStringElement(feature, writer, "interpretation", "aixm", "interpretation");
     }
 }
        public IEnumerable<JObject> ReadElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("#type",element.Name.ToString());

            currentObject.Add("type", "FeatureCollection");
            currentObject.Add("features", converter.ReadElements(currentObject,element.Elements()));

           yield return currentObject;
        }
        public IEnumerable<JObject> ReadElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            var AixmTimeSlice = element.Elements().First();

          
            currentObject.AddToProperties("AixmTimeSlice", JToken.FromObject(AixmTimeSlice.Attributes().ToDictionary(a=>a.Name,a=>a.Value)));

            return converter.ReadElement(currentObject, AixmTimeSlice.Elements());
        }
        public IEnumerable<JObject> ReadExtentElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
         
            currentObject.AddToProperties("geometrySource", "extent");
            //set the ElementType of the extent on feature property extentSource, to be used when writing back.
            currentObject.AddToProperties("extentSource", element.Elements().First().Name.LocalName);

            return converter.ReadElement(currentObject, element.Elements());           
        }
        public IEnumerable<JObject> ReadElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
           
            XNamespace aximNs = "http://www.aixm.aero/schema/5.1";
            var AirspaceVolume = element.Descendants(aximNs + "AirspaceVolume").ToArray();
            if (AirspaceVolume.Length != 1)
                throw new NotSupportedException("AirSpaceVolme must be of length 1");


            return converter.ReadElement(currentObject, AirspaceVolume.Elements());


        }
        public IEnumerable<JObject> ReadElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            XNamespace aximNs = "http://www.aixm.aero/schema/5.1";

            //Convert ElevatedPoint to a GML Surface and convert to geojson.
            var geometry = GeometryFactory.GmlToGeometry(DownCastToPointElement(element));
                       
            //Set the geometry
            currentObject.SetGeometry(geometry);

            //Set the projection on the feature obj.
            currentObject.SetSrs(element);

            //Read elevation property and return
            return converter.ReadElement(currentObject, element.Elements(aximNs + "elevation"));
        }
        public IEnumerable<JObject> ReadSurfaceElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
           
            //Convert ElevatedSurface to a GML Surface and convert to geojson.
            var geometry = GeometryFactory.GmlToGeometry(DownCastToSurfaceElement(element));

            //Set the geometry
            currentObject.SetGeometry(geometry);

            //Set the projection on the feature obj.
            currentObject.SetSrs(element);

            return Enumerable.Empty<JObject>();

          
        }
        public void WriteElementStart(IAixmConverter converter, int flow, JObject feature, XmlWriter writer)
        {
            var type = feature["properties"]["AixmType"];
            if (flow == 0)
            {
                writer.WriteStartElement("message", "hasMember", null);
                if (type != null)
                {
                    writer.WriteStartElement("aixm", type.ToString(),null);
                }
               
            }
            else
            {
                if (type != null)
                {
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }


        }
        public IEnumerable<JObject> ReadTimeSliceMetadataElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("timeSliceMetadata", JObject.FromObject(element));

            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadSurfacePropertiesElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("surfaceProperties", JObject.FromObject(element));

            return Enumerable.Empty<JObject>();
        }
 public IEnumerable<JObject> ReadLocationElement(IAixmConverter converter, JObject currentObject, XElement element)
 {
     return converter.ReadElement(currentObject, element.Elements());
    
 }
        public IEnumerable<JObject> ReadTypeElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("aixmType", element.Value);

            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadGeometryComponenentElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("geometrySource", element.Elements().First().Name.LocalName);

            return converter.ReadElement(currentObject, element.Elements());
          //  currentObject.Add("geometry", JObject.FromObject(element));
          

            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadAssociatedApronElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
    
            currentObject.AddToProperties("associatedApron", JToken.FromObject(element.Attributes().ToDictionary(a => a.Name, a => a.Value)));

            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadCorrectionNumberElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("correctionNumber", JObject.FromObject(element));

            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadAvailabilityElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("availability", JObject.FromObject(element));

            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadInterpretationElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("interpretation", element.Value);

            return Enumerable.Empty<JObject>();
        }
        public IEnumerable<JObject> ReadLowerLimitElement(IAixmConverter converter, JObject currentObject, XElement element)
        {
            currentObject.AddToProperties("lowerLimit", JObject.FromObject(element));

            return Enumerable.Empty<JObject>();
        }