public List <API.Common.Model.ChargePoint> Process(CoreReferenceData coreRefData)
        {
            List <ChargePoint> outputList = new List <ChargePoint>();

            string source = InputData;

            JObject o = JObject.Parse(source);

            var dataList = o["features"].ToArray();

            int itemCount = 0;

            // address, operator, chargepoint
            var dataMap = new Dictionary <Tuple <String, int?>, ChargePoint>();

            var unknownOperators = new Dictionary <String, int>();

            foreach (var dataItem in dataList)
            {
                var item = dataItem["attributes"];

                var cp = new POIDetails();

                cp.DataProviderID = this.DataProviderID; //Bundesnetzagentur
                ///cp.DataProvidersReference = item["OBJECTID"].ToString(); // - Note: There is no unique reference in this data source. The ObjectID seems to be a dynamic row id and using it results in unrelated data being overwritten between imports
                cp.DateLastStatusUpdate = DateTime.UtcNow;

                cp.AddressInfo = new AddressInfo();

                var locationStr = item["Standort_"].ToString();
                var address     = locationStr.Split(", ");
                cp.AddressInfo.AddressLine1 = address[0];
                cp.AddressInfo.Title        = address[0];

                var postcodeAndTown = address[1].Split(" ");
                cp.AddressInfo.Postcode = postcodeAndTown[0];
                cp.AddressInfo.Town     = String.Join(" ", postcodeAndTown[1..]);
        public List <API.Common.Model.ChargePoint> Process(CoreReferenceData coreRefData)
        {
            List <ChargePoint> outputList = new List <ChargePoint>();

            string source = InputData;

            JObject o = JObject.Parse(source);

            var dataList = o["ChargeDevice"].ToArray();

            int itemCount = 0;

            foreach (var dataItem in dataList)
            {
                bool skipPOI = false;
                var  item    = dataItem;
                var  cp      = new POIDetails();

                var deviceName = item["ChargeDeviceName"].ToString();

                //private addresses are skipped from import
                if (!String.IsNullOrEmpty(deviceName) && deviceName.ToLower().Contains("parkatmyhouse"))
                {
                    skipPOI = true;
                }

                var locationType = item["LocationType"].ToString();
                if (!String.IsNullOrEmpty(locationType))
                {
                    if (locationType.ToLower().Contains("home"))
                    {
                        skipPOI = true;
                    }
                }

                //parse reset of POI data
                cp.DataProviderID         = this.DataProviderID; //UK National Charge Point Registry
                cp.DataProvidersReference = item["ChargeDeviceId"].ToString();
                cp.DateLastStatusUpdate   = DateTime.UtcNow;
                cp.AddressInfo            = new AddressInfo();

                var locationDetails = item["ChargeDeviceLocation"];
                var addressDetails  = locationDetails["Address"];

                cp.AddressInfo.RelatedURL   = "";
                cp.DateLastStatusUpdate     = DateTime.UtcNow;
                cp.AddressInfo.AddressLine1 = (String.IsNullOrEmpty(addressDetails["Street"].ToString()) ? addressDetails["BuildingNumber"].ToString() + " " + addressDetails["Thoroughfare"].ToString() : addressDetails["Street"].ToString().Replace("<br>", ", ")).Trim();
                cp.AddressInfo.Title        = String.IsNullOrEmpty(locationDetails["LocationShortDescription"].ToString()) ? cp.AddressInfo.AddressLine1 : locationDetails["LocationShortDescription"].ToString();
                cp.AddressInfo.Title        = cp.AddressInfo.Title.Replace("&amp;", "&");
                cp.AddressInfo.Title        = cp.AddressInfo.Title.Replace("<br>", ", ").Trim();
                if (cp.AddressInfo.Title.Length > 100)
                {
                    cp.AddressInfo.Title = cp.AddressInfo.Title.Substring(0, 64) + "..";
                }
                cp.AddressInfo.Town = addressDetails["PostTown"].ToString();
                string dependantLocality = addressDetails["DependantLocality"].ToString();
                if (!String.IsNullOrEmpty(dependantLocality) && dependantLocality.ToLower() != cp.AddressInfo.Town.ToLower())
                {
                    //use depenendantLocality if provided and is not same as town
                    cp.AddressInfo.AddressLine2 = dependantLocality;
                }
                cp.AddressInfo.Postcode       = addressDetails["PostCode"].ToString();
                cp.AddressInfo.Latitude       = double.Parse(locationDetails["Latitude"].ToString());
                cp.AddressInfo.Longitude      = double.Parse(locationDetails["Longitude"].ToString());
                cp.AddressInfo.AccessComments = locationDetails["LocationLongDescription"].ToString().Replace("<br>", ", ").Replace("\r\n", ", ").Replace("\n", ", ");

                //if title is empty, attempt to add a suitable replacement
                if (String.IsNullOrEmpty(cp.AddressInfo.Title))
                {
                    if (!String.IsNullOrEmpty(cp.AddressInfo.AddressLine1))
                    {
                        cp.AddressInfo.Title = cp.AddressInfo.AddressLine1.Trim();
                    }
                    else
                    {
                        cp.AddressInfo.Title = cp.AddressInfo.Postcode;
                    }
                }

                if (cp.AddressInfo.Title == "NA" && cp.AddressInfo.AddressLine1 == "NA")
                {
                    // item needs an address resolved
                    cp.AddressInfo.Title       = "";
                    cp.AddressCleaningRequired = true;
                    cp.SubmissionStatusTypeID  = (int)StandardSubmissionStatusTypes.Imported_UnderReview;
                }

                if (cp.AddressInfo.Title.ToLower().StartsWith("asset no.") && cp.AddressInfo.AddressLine1.ToLower().StartsWith("asset no."))
                {
                    // item needs an address resolved
                    cp.AddressInfo.Title       = "";
                    cp.AddressCleaningRequired = true;
                    cp.SubmissionStatusTypeID  = (int)StandardSubmissionStatusTypes.Imported_UnderReview;
                }

                //cp.AddressInfo.ContactTelephone1 = item["phone"].ToString();

                if (!String.IsNullOrEmpty(addressDetails["Country"].ToString()))
                {
                    string country   = addressDetails["Country"].ToString();
                    int?   countryID = null;

                    var countryVal = coreRefData.Countries.FirstOrDefault(c => c.Title.ToLower() == country.Trim().ToLower());
                    if (countryVal == null)
                    {
                        country = country.ToUpper();
                        //match country
                        if (country == "GB" || country == "US" || country == "USA" || country == "U.S." || country == "U.S.A.")
                        {
                            countryID = 2;
                        }
                        if (country == "UK" || country == "GB" || country == "GREAT BRITAIN" || country == "UNITED KINGDOM")
                        {
                            countryID = 1;
                        }
                    }
                    else
                    {
                        countryID = countryVal.ID;
                    }

                    if (countryID == null)
                    {
                        this.Log("Country Not Matched, will require Geolocation:" + item["country"].ToString());
                    }
                    else
                    {
                        cp.AddressInfo.CountryID = countryID;
                    }
                }
                else
                {
                    //default to US if no country identified
                    //cp.AddressInfo.Country = cp.AddressInfo.Country = coreRefData.Countries.FirstOrDefault(cy => cy.ID == 2);
                }

                //operator from DeviceController
                var deviceController = item["DeviceController"];

                cp.AddressInfo.RelatedURL = deviceController["Website"].ToString();
                var deviceOperator = coreRefData.Operators.FirstOrDefault(devOp => devOp.Title.Contains(deviceController["OrganisationName"].ToString()));
                if (deviceOperator != null)
                {
                    cp.OperatorID = deviceOperator.ID;
                }
                else
                {
                    //operator from device owner
                    var devOwner = item["DeviceOwner"];
                    deviceOperator = coreRefData.Operators.FirstOrDefault(devOp => devOp.Title.Contains(devOwner["OrganisationName"].ToString()));
                    if (deviceOperator != null)
                    {
                        cp.OperatorID = deviceOperator.ID;
                    }
                }

                if (cp.OperatorID == null)
                {
                    string operatorName = deviceController["OrganisationName"]?.ToString() ?? item["DeviceOwner"]["OrganisationName"]?.ToString();

                    // match specific operators

                    switch (operatorName)
                    {
                    case "Chargemaster (POLAR)":
                        cp.OperatorID = 8;
                        break;

                    case "Ecotricity (Electric Highway)":
                        cp.OperatorID = 24;
                        break;

                    case "ecar NI":
                        cp.OperatorID = 91;
                        break;

                    case "eo Charging":
                        cp.OperatorID = 3298;
                        break;

                    case "Alfa Power":
                        cp.OperatorID = 3326;
                        break;

                    case "InCharge - an initiative by Vattenfall":
                        cp.OperatorID = 3343;
                        break;

                    case "APT":
                        cp.OperatorID = 3341;
                        break;
                    }

                    if (cp.OperatorID == null)
                    {
                        Log("Unknown Operator: " + deviceController["OrganisationName"]?.ToString() ?? item["DeviceOwner"]["OrganisationName"]?.ToString());
                    }
                }

                //determine most likely usage type
                cp.UsageTypeID = (int)StandardUsageTypes.Public;

                if (item["SubscriptionRequiredFlag"].ToString().ToUpper() == "TRUE")
                {
                    //membership required
                    cp.UsageTypeID = (int)StandardUsageTypes.Public_MembershipRequired;
                }
                else
                {
                    if (item["PaymentRequiredFlag"].ToString().ToUpper() == "TRUE")
                    {
                        //payment required
                        cp.UsageTypeID = (int)StandardUsageTypes.Public_PayAtLocation;
                    }
                    else
                    {
                        //accessible 24 hours, payment not required and membership not required, assume public
                        if (item["Accessible24Hours"].ToString().ToUpper() == "TRUE")
                        {
                            cp.UsageTypeID = (int)StandardUsageTypes.Public;
                        }
                    }
                }

                //special usage cases detected from text
                if (cp.AddressInfo.ToString().ToLower().Contains("no public access"))
                {
                    cp.UsageTypeID = (int)StandardUsageTypes.PrivateRestricted;
                }

                //add connections
                var connectorList = item["Connector"].ToArray();
                foreach (var conn in connectorList)
                {
                    ConnectionInfo cinfo = new ConnectionInfo()
                    {
                    };

                    if (conn["RatedOutputkW"] != null)
                    {
                        double tmpKw = 0;
                        if (double.TryParse(conn["RatedOutputkW"].ToString(), out tmpKw))
                        {
                            cinfo.PowerKW = tmpKw;
                        }
                    }

                    if (conn["RatedOutputVoltage"] != null)
                    {
                        int tmpV = 0;
                        if (int.TryParse(conn["RatedOutputVoltage"].ToString(), out tmpV))
                        {
                            cinfo.Voltage = tmpV;
                        }
                    }

                    if (conn["RatedOutputCurrent"] != null)
                    {
                        int tmpA = 0;
                        if (int.TryParse(conn["RatedOutputCurrent"].ToString(), out tmpA))
                        {
                            cinfo.Amps = tmpA;
                        }
                    }

                    string connectorType = conn["ConnectorType"].ToString();

                    if (!String.IsNullOrEmpty(connectorType))
                    {
                        cinfo.Reference = conn["ConnectorId"].ToString();

                        if (connectorType.ToUpper().Contains("BS 1363") || connectorType.ToUpper().Contains("3-PIN TYPE G (BS1363)"))
                        {
                            cinfo.ConnectionTypeID = (int)StandardConnectionTypes.BS1363TypeG; //UK 13 amp plug
                            cinfo.LevelID          = 2;                                        // default to level 2
                        }

                        if (connectorType.ToUpper() == "IEC 62196-2 TYPE 1 (SAE J1772)" || connectorType.ToUpper() == "TYPE 1 SAEJ1772 (IEC 62196)")
                        {
                            cinfo.ConnectionTypeID = (int)StandardConnectionTypes.J1772;
                            cinfo.LevelID          = 2; // default to level 2
                        }

                        if (connectorType.ToUpper() == "IEC 62196-2 TYPE 2" || connectorType.ToUpper().Contains("(IEC62196)"))
                        {
                            cinfo.ConnectionTypeID = (int)StandardConnectionTypes.MennekesType2;
                            cinfo.LevelID          = 2;

                            if (cinfo.Amps > 32)
                            {
                                // assume connector is tethered due to high current
                                cinfo.ConnectionTypeID = (int)StandardConnectionTypes.MennekesType2Tethered;
                            }

                            // handle Type 2 Tesla (IEC62196) DC which are Type 2 but tesla access only
                            if (connectorType.ToUpper() == "TYPE 2 TESLA (IEC62196) DC")
                            {
                                cinfo.Comments = "Tesla Only";
                            }
                        }

                        if (connectorType.ToUpper() == "JEVS G 105 (CHADEMO)" || connectorType.ToUpper() == "JEVS G105 (CHADEMO) DC")
                        {
                            cinfo.ConnectionTypeID = (int)StandardConnectionTypes.CHAdeMO;
                            cinfo.LevelID          = 3;
                        }

                        if (connectorType.ToUpper() == "IEC 62196-2 TYPE 3")
                        {
                            cinfo.ConnectionTypeID = 26; //IEC 62196-2 type 3
                            cinfo.LevelID          = 2;
                        }

                        if (connectorType.ToUpper() == "TYPE 2 COMBO (IEC62196) DC")
                        {
                            cinfo.ConnectionTypeID = (int)StandardConnectionTypes.CCSComboType2;
                            cinfo.LevelID          = 3;
                        }

                        if (connectorType.ToUpper() == "TYPE 2 COMBO (IEC62196) DC")
                        {
                            cinfo.ConnectionTypeID = (int)StandardConnectionTypes.CCSComboType2;
                            cinfo.LevelID          = 3;
                        }

                        if (conn["ChargePointStatus"] != null)
                        {
                            cinfo.StatusTypeID = (int)StandardStatusTypes.Operational;
                            if (conn["ChargePointStatus"].ToString() == "Out of service")
                            {
                                cinfo.StatusTypeID = (int)StandardStatusTypes.NotOperational;
                            }
                        }

                        if (conn["ChargeMethod"] != null && !String.IsNullOrEmpty(conn["ChargeMethod"].ToString()))
                        {
                            string method = conn["ChargeMethod"].ToString();
                            //Single Phase AC, Three Phase AC, DC
                            if (method == "Single Phase AC")
                            {
                                cinfo.CurrentTypeID = (int)StandardCurrentTypes.SinglePhaseAC;
                            }
                            if (method == "Three Phase AC")
                            {
                                cinfo.CurrentTypeID = (int)StandardCurrentTypes.ThreePhaseAC;
                            }
                            if (method == "DC")
                            {
                                cinfo.CurrentTypeID = (int)StandardCurrentTypes.DC;
                            }
                        }

                        if (cinfo.ConnectionTypeID == null)
                        {
                            if (!String.IsNullOrEmpty(connectorType))
                            {
                                Log("Unknown connector type:" + connectorType);
                            }
                        }

                        if (cp.Connections == null)
                        {
                            cp.Connections = new List <ConnectionInfo>();
                        }
                        if (!IsConnectionInfoBlank(cinfo))
                        {
                            //TODO: skip items with blank address info
                            cp.Connections.Add(cinfo);
                        }
                    }
                }

                //apply data attribution metadata
                if (cp.MetadataValues == null)
                {
                    cp.MetadataValues = new List <MetadataValue>();
                }
                cp.MetadataValues.Add(new MetadataValue {
                    MetadataFieldID = (int)StandardMetadataFields.Attribution, ItemValue = DataAttribution
                });

                if (cp.DataQualityLevel == null)
                {
                    cp.DataQualityLevel = 3;
                }

                if (cp.SubmissionStatusTypeID == null)
                {
                    cp.SubmissionStatusTypeID = (int)StandardSubmissionStatusTypes.Imported_Published;
                }

                if (!skipPOI)
                {
                    outputList.Add(new ChargePoint(cp));
                    itemCount++;
                }
            }

            return(outputList);
        }