public static List<OCM.API.Common.Model.ChargePoint> GetPOIList(APIRequestParams filter) { try { return new CacheProviderMongoDB().GetPOIList(filter); } catch (Exception) { return null; } }
public void ProcessRequest(HttpContext context) { if (dataSummaryManager == null) dataSummaryManager = new DataSummaryManager(); APIRequestParams filterSettings = new APIRequestParams(); filterSettings.ParseParameters(filterSettings,context); string action = "totals_per_country"; if (!String.IsNullOrEmpty(context.Request["action"])) { action = context.Request["action"].ToString(); } if (action == "totals_per_country") { context.Response.ContentType = "application/javascript"; context.Response.Write(dataSummaryManager.GetTotalsPerCountrySummary(true,"ocm_getdatasummary", filterSettings )); context.Response.Flush(); } if (action == "full_summary") { // Output JSON summary of: // - Current totals per country // - Total added (per country? based on date range, location/distance filter?) // - Total modified // - User Comments Count // - per month values, current month first? default last 12 months } if (action == "activity_summary") { // Based on date range, location and distance: // - list of recent comments, checkins, id & title etc of items added & modified var o = new JSONOutputProvider(); context.Response.ContentType = o.ContentType; var summary = dataSummaryManager.GetActivitySummary(filterSettings); o.PerformSerialisationV2(context.Response.OutputStream, summary, filterSettings.Callback); context.Response.Flush(); } }
public async Task <CoreReferenceData> GetCoreReferenceDataAsync(APIRequestParams filter = null) { if (filter == null) { filter = new APIRequestParams { } } ; CoreReferenceData data = null; if (filter.AllowMirrorDB) { // TODO: implement country filters for cached ref data data = await OCM.Core.Data.CacheManager.GetCoreReferenceData(filter); if (data != null) { return(data); } } if (!filter.AllowDataStoreDB) { return(null); } //can't get cached data, get fresh from database data = new CoreReferenceData(); //list of Levels (ChargerTypes) data.ChargerTypes = new List <Model.ChargerType>(); await dataModel.ChargerTypes.ForEachAsync(cg => data.ChargerTypes.Add(Model.Extensions.ChargerType.FromDataModel(cg))); //list of connection types data.ConnectionTypes = new List <Model.ConnectionType>(); if (filter.CountryIDs?.Any() == true) { // fetch connection types used in the list of given countries, with count of usage in the set var usedConnectionTypes = dataModel.ConnectionTypes .Distinct() .Where(c => c.ConnectionInfos.Any(ci => filter.CountryIDs.Contains(ci.ChargePoint.AddressInfo.CountryId) && (ci.ChargePoint.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Imported_Published || ci.ChargePoint.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Submitted_Published))) .Select(s => new { connectionType = s, count = s.ConnectionInfos.Where(ci => filter.CountryIDs.Contains(ci.ChargePoint.AddressInfo.CountryId) && (ci.ChargePoint.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Imported_Published || ci.ChargePoint.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Submitted_Published)).Count() }); await usedConnectionTypes .Where(d => d.count > MINFILTER_CONNECTIONTYPE_INSTANCES) .OrderBy(d => d.connectionType.Title). ForEachAsync(ct => data.ConnectionTypes.Add(Model.Extensions.ConnectionType.FromDataModel(ct.connectionType))); } else { await dataModel.ConnectionTypes .OrderBy(d => d.Title) .ForEachAsync(ct => data.ConnectionTypes.Add(Model.Extensions.ConnectionType.FromDataModel(ct))); } //list of power source types (AC/DC etc) data.CurrentTypes = new List <Model.CurrentType>(); await dataModel.CurrentTypes.ForEachAsync(ct => data.CurrentTypes.Add(Model.Extensions.CurrentType.FromDataModel(ct))); //list of countries data.Countries = new List <Model.Country>(); await dataModel.Countries.ForEachAsync(country => data.Countries.Add(Model.Extensions.Country.FromDataModel(country))); //list of Data Providers data.DataProviders = new List <Model.DataProvider>(); await dataModel.DataProviders.Include(d => d.DataProviderStatusType).ForEachAsync(provider => data.DataProviders.Add(Model.Extensions.DataProvider.FromDataModel(provider))); //list of Operators data.Operators = new List <Model.OperatorInfo>(); if (filter.CountryIDs?.Any() == true) { // fetch connection types used in the list of given countries, with count of usage in the set var usedNetworks = dataModel.Operators.Include(o => o.AddressInfo) .Distinct() .Where(c => c.ChargePoints .Where(cp => cp.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Imported_Published || cp.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Submitted_Published) .Any(poi => filter.CountryIDs.Contains(poi.AddressInfo.CountryId)) ) .Select(o => new { operatorInfo = o, count = o.ChargePoints.Where(poi => filter.CountryIDs.Contains(poi.AddressInfo.CountryId) && (poi.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Imported_Published || poi.SubmissionStatusTypeId == (int)StandardSubmissionStatusTypes.Submitted_Published) ) .Count() }); await usedNetworks .Where(d => d.count > MINFILTER_OPERATOR_INSTANCES) .OrderBy(d => d.operatorInfo.Title.Trim()) .ForEachAsync(ct => data.Operators.Add(Model.Extensions.OperatorInfo.FromDataModel(ct.operatorInfo))); } else { await dataModel.Operators.Include(o => o.AddressInfo).OrderBy(o => o.Title.Trim()).ForEachAsync(source => data.Operators.Add(Model.Extensions.OperatorInfo.FromDataModel(source))); } //list of Status Types data.StatusTypes = new List <Model.StatusType>(); await dataModel.StatusTypes.ForEachAsync(status => data.StatusTypes.Add(Model.Extensions.StatusType.FromDataModel(status))); //list of Usage Types (public etc) data.UsageTypes = new List <Model.UsageType>(); await dataModel.UsageTypes.OrderBy(u => u.Title).ForEachAsync(usage => data.UsageTypes.Add(Model.Extensions.UsageType.FromDataModel(usage))); //list of user comment types data.UserCommentTypes = new List <Model.UserCommentType>(); await dataModel.UserCommentTypes.ForEachAsync(commentType => data.UserCommentTypes.Add(Model.Extensions.UserCommentType.FromDataModel(commentType))); //list of user comment types data.CheckinStatusTypes = new List <Model.CheckinStatusType>(); await dataModel.CheckinStatusTypes.ForEachAsync(checkinType => data.CheckinStatusTypes.Add(Model.Extensions.CheckinStatusType.FromDataModel(checkinType))); data.SubmissionStatusTypes = new List <Model.SubmissionStatusType>(); await dataModel.SubmissionStatusTypes.ForEachAsync(s => data.SubmissionStatusTypes.Add(Model.Extensions.SubmissionStatusType.FromDataModel(s))); data.MetadataGroups = new List <Model.MetadataGroup>(); var groups = dataModel.MetadataGroups .Include(m => m.MetadataFields) .ThenInclude(f => f.DataType) .Include(m => m.MetadataFields) .ThenInclude(f => f.MetadataFieldOptions); await groups.ForEachAsync(g => data.MetadataGroups.Add(Model.Extensions.MetadataGroup.FromDataModel(g))); data.DataTypes = new List <Model.DataType>(); await dataModel.DataTypes.ForEachAsync(d => data.DataTypes.Add(Model.Extensions.DataType.FromDataModel(d))); data.ChargePoint = new ChargePoint() { AddressInfo = new Model.AddressInfo(), #pragma warning disable 612 //suppress obsolete warning Chargers = new List <Model.ChargerInfo> { new Model.ChargerInfo() }, #pragma warning restore 612 Connections = new List <Model.ConnectionInfo> { new Model.ConnectionInfo() }, DateCreated = DateTime.UtcNow, DateLastConfirmed = DateTime.UtcNow, DateLastStatusUpdate = DateTime.UtcNow, GeneralComments = "", DatePlanned = null, ID = -1, NumberOfPoints = 1, StatusType = new Model.StatusType(), OperatorInfo = new Model.OperatorInfo(), DataProvider = new Model.DataProvider(), UsageType = new Model.UsageType(), UUID = Guid.NewGuid().ToString(), DataQualityLevel = 1 }; data.UserComment = new Model.UserComment { ChargePointID = 0, Comment = "", CommentType = data.UserCommentTypes[0], DateCreated = DateTime.UtcNow, ID = 0, CheckinStatusType = data.CheckinStatusTypes[0] }; return(data); } }
public CoreReferenceData GetCoreReferenceData(APIRequestParams filter = null) { return(GetCoreReferenceDataAsync(filter).Result); }
private void OutputGeocodingResult(IOutputProvider outputProvider, HttpContext context, APIRequestParams filter) { GeocodingResult result = null; //get or get and cache result if (HttpContext.Current.Cache["Geocoding_" + filter.HashKey] != null && filter.EnableCaching) { result = (GeocodingResult)HttpContext.Current.Cache["Geocoding_" + filter.HashKey]; } else { var geocoder = new GeocodingHelper(); geocoder.IncludeExtendedData = true; //result = geocoder.GeolocateAddressInfo_OSM(filter.Address); result = geocoder.GeolocateAddressInfo_Google(filter.Address); HttpContext.Current.Cache.Add("Geocoding_" + filter.HashKey, result, null, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0), CacheItemPriority.Normal, null); } //send API response if (filter.IsEnvelopedResponse) { var responseEnvelope = new APIResponseEnvelope(); responseEnvelope.Data = result; outputProvider.GetOutput(context.Response.OutputStream, responseEnvelope, filter); } else { outputProvider.GetOutput(context.Response.OutputStream, result, filter); } }
private void OutputAvailabilityResult(IOutputProvider outputProvider, HttpContext context, APIRequestParams filter) { //TODO: provider specific availability check with result caching var results = new List<object>(); foreach (var poiId in filter.ChargePointIDs) { results.Add(new { id = filter.ChargePointIDs, status = StandardStatusTypes.Unknown, timestamp = DateTime.UtcNow }); } //send API response if (filter.IsEnvelopedResponse) { var responseEnvelope = new APIResponseEnvelope(); responseEnvelope.Data = results; outputProvider.GetOutput(context.Response.OutputStream, responseEnvelope, filter); } else { outputProvider.GetOutput(context.Response.OutputStream, results, filter); } }
/// <summary> /// Output Core Reference Data (lookup lists, default objects) /// </summary> /// <param name="outputProvider"></param> /// <param name="context"></param> /// <param name="filter"></param> private void OutputCoreReferenceData(IOutputProvider outputProvider, HttpContext context, APIRequestParams filter) { //get core reference data var refDataManager = new ReferenceDataManager(); CoreReferenceData data = null; //cache result if (HttpContext.Current.Cache["CoreRefData"] != null && filter.EnableCaching) { data = (CoreReferenceData)HttpContext.Current.Cache["CoreRefData"]; } else { data = refDataManager.GetCoreReferenceData(); HttpContext.Current.Cache.Add("CoreRefData", data, null, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0), CacheItemPriority.Normal, null); } //populate non-cached fragments (user profile) data.UserProfile = new InputProviderBase().GetUserFromAPICall(context); //send response outputProvider.GetOutput(context.Response.OutputStream, data, filter); }
/// <summary> /// Output compact (id's only for reference data) POI list /// </summary> /// <param name="context"></param> /// <param name="filter"></param> private void OutputCompactPOIList(HttpContext context, APIRequestParams filter) { //get list of charge points as compact POISearchResult List for output: List<OCM.API.Common.Model.ChargePoint> dataList = new POIManager().GetChargePoints(filter); int numResults = dataList.Count; List<POISearchResult> poiList = new List<POISearchResult>(); foreach (var c in dataList) { var poi = new POISearchResult { ID = c.ID, Title = c.AddressInfo.Title, Address = c.AddressInfo.AddressLine1, Distance = c.AddressInfo.Distance, Latitude = (double)c.AddressInfo.Latitude, Longitude = (double)c.AddressInfo.Longitude, Postcode = c.AddressInfo.Postcode, UsageTypeID = c.UsageType != null ? c.UsageType.ID : 0, StatusTypeID = c.StatusType != null ? c.StatusType.ID : 0 }; poiList.Add(poi); } var o = new JSONOutputProvider(); string description = "Compact POI List: id=ID, t= Title, u= UsageTypeID, s= StatusTypeID, a=Address, p=Postcode, lt=Latitude, lg=Longitude, d= Distance"; o.PerformSerialisationV2(context.Response.OutputStream, new { status = "OK", description = description, count = poiList.Count, results = poiList }, filter.Callback); }
public void ParseParameters(APIRequestParams settings, HttpContext context) { //get parameter values if any if (!String.IsNullOrEmpty(context.Request["v"])) settings.APIVersion = ParseInt(context.Request["v"]); if (settings.APIVersion > MAX_API_VERSION) settings.APIVersion = MAX_API_VERSION; if (!String.IsNullOrEmpty(context.Request["action"])) settings.Action = ParseString(context.Request["action"]); if (!String.IsNullOrEmpty(context.Request["apikey"])) settings.APIKey = ParseString(context.Request["apikey"]); if (!String.IsNullOrEmpty(context.Request["chargepointid"])) settings.ChargePointIDs = ParseIntList(context.Request["chargepointid"]); if (!String.IsNullOrEmpty(context.Request["operatorname"])) settings.OperatorName = ParseString(context.Request["operatorname"]); if (!String.IsNullOrEmpty(context.Request["operatorid"])) settings.OperatorIDs = ParseIntList(context.Request["operatorid"]); if (!String.IsNullOrEmpty(context.Request["connectiontypeid"])) settings.ConnectionTypeIDs = ParseIntList(context.Request["connectiontypeid"]); if (!String.IsNullOrEmpty(context.Request["countryid"])) settings.CountryIDs = ParseIntList(context.Request["countryid"]); if (!String.IsNullOrEmpty(context.Request["levelid"])) settings.LevelIDs = ParseIntList(context.Request["levelid"]); if (!String.IsNullOrEmpty(context.Request["usagetypeid"])) settings.UsageTypeIDs = ParseIntList(context.Request["usagetypeid"]); if (!String.IsNullOrEmpty(context.Request["statustypeid"])) settings.StatusTypeIDs = ParseIntList(context.Request["statustypeid"]); if (!String.IsNullOrEmpty(context.Request["dataproviderid"])) settings.DataProviderIDs = ParseIntList(context.Request["dataproviderid"]); if (!String.IsNullOrEmpty(context.Request["opendata"])) settings.IsOpenData = ParseBoolNullable(context.Request["opendata"]); if (!String.IsNullOrEmpty(context.Request["minpowerkw"])) settings.MinPowerKW = ParseDouble(context.Request["minpowerkw"]); if (!String.IsNullOrEmpty(context.Request["dataprovidername"])) settings.DataProviderName = ParseString(context.Request["dataprovidername"]); if (!String.IsNullOrEmpty(context.Request["locationtitle"])) settings.LocationTitle = ParseString(context.Request["locationtitle"]); if (!String.IsNullOrEmpty(context.Request["address"])) settings.Address = ParseString(context.Request["address"]); if (!String.IsNullOrEmpty(context.Request["countrycode"])) settings.CountryCode = ParseString(context.Request["countrycode"]); if (!String.IsNullOrEmpty(context.Request["latitude"])) { settings.Latitude = ParseDouble(context.Request["latitude"]); if (settings.Latitude < -90 || settings.Latitude > 90) settings.Latitude = null; } if (!String.IsNullOrEmpty(context.Request["longitude"])) { settings.Longitude = ParseDouble(context.Request["longitude"]); if (settings.Longitude < -180 || settings.Longitude > 180) settings.Longitude = null; } if (!String.IsNullOrEmpty(context.Request["distance"])) settings.Distance = ParseDouble(context.Request["distance"]); if (!String.IsNullOrEmpty(context.Request["distanceunit"])) settings.DistanceUnit = ParseDistanceUnit(context.Request["distanceunit"]); if (!String.IsNullOrEmpty(context.Request["polyline"])) settings.Polyline = ParsePolyline(context.Request["polyline"]); //settings.Polyline = ParsePolyline("_p~iF~ps|U_ulLnnqC_mqNvxq`@"); //settings.Polyline = ParsePolyline("(38.5, -120.2), (40.7, -120.95), (43.252, -126.453)"); if (!String.IsNullOrEmpty(context.Request["connectiontype"])) settings.ConnectionType = ParseString(context.Request["connectiontype"]); if (!String.IsNullOrEmpty(context.Request["submissionstatustypeid"])) settings.SubmissionStatusTypeID = ParseInt(context.Request["submissionstatustypeid"]); if (!String.IsNullOrEmpty(context.Request["modifiedsince"])) settings.ChangesFromDate = ParseDate(context.Request["modifiedsince"]); if (!String.IsNullOrEmpty(context.Request["enablecaching"])) settings.EnableCaching = ParseBool(context.Request["enablecaching"], true); if (!String.IsNullOrEmpty(context.Request["allowmirror"])) settings.AllowMirrorDB = ParseBool(context.Request["allowmirror"], false); if (!String.IsNullOrEmpty(context.Request["includecomments"])) settings.IncludeComments = ParseBool(context.Request["includecomments"], false); if (!String.IsNullOrEmpty(context.Request["verbose"])) settings.IsVerboseOutput = ParseBool(context.Request["verbose"], false); if (!String.IsNullOrEmpty(context.Request["compact"])) settings.IsCompactOutput = ParseBool(context.Request["compact"], false); if (!String.IsNullOrEmpty(context.Request["camelcase"])) settings.IsCamelCaseOutput = ParseBool(context.Request["camelcase"], false); if (!String.IsNullOrEmpty(context.Request["callback"])) settings.Callback = ParseString(context.Request["callback"]); if (!String.IsNullOrEmpty(context.Request["maxresults"])) { try { settings.MaxResults = int.Parse(context.Request["maxresults"]); } catch (Exception) { settings.MaxResults = 100; } } //default action if (String.IsNullOrEmpty(settings.Action)) { settings.Action = "getchargepoints"; } //handle deprecated items if (settings.APIVersion == null || settings.APIVersion == 1) { if (!String.IsNullOrEmpty(context.Request["fastchargeonly"])) settings.FastChargeOnly = ParseBool(context.Request["fastchargeonly"], false); } }
/// <summary> /// Handle output from API /// </summary> /// <param name="context"></param> private async void PerformOutput(HttpContext context) { HttpContext.Current.Server.ScriptTimeout = 120; //max script execution time is 2 minutes System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); //decide correct reponse type IOutputProvider outputProvider = null; var filter = new APIRequestParams(); //set defaults string outputType = "xml"; filter.DistanceUnit = DistanceUnit.Miles; filter.MaxResults = 100; filter.EnableCaching = true; filter.ParseParameters(context); //override ?v=2 etc if called via /api/v2/ or /api/v1 if (APIBehaviourVersion > 0) filter.APIVersion = APIBehaviourVersion; if (APIBehaviourVersion >= 2) filter.Action = DefaultAction; if (context.Request.Url.Host.ToLower().StartsWith("api") && filter.APIVersion == null) { //API version is mandatory for api V2 onwards via api.openchargemap.* hostname OutputBadRequestMessage(context, "mandatory API Version not specified in request"); return; } if (!String.IsNullOrEmpty(context.Request["output"])) { outputType = ParseString(context.Request["output"]); } else { //new default after API V2 is json instead of XML if (filter.APIVersion >= 2) { outputType = "json"; } } //change defaults and override settings for deprecated api features if (filter.APIVersion >= 2) { //the following output types are deprecated and will default as JSON if (outputType == "carwings" || outputType == "rss") { OutputBadRequestMessage(context, "specified output type not supported in this API version"); return; } } if (IsRequestByRobot) { OutputBadRequestMessage(context, "API requests by robots are temporarily disabled.", statusCode: 503); return; } //determine output provider switch (outputType) { case "xml": outputProvider = new XMLOutputProvider(); break; case "carwings": case "rss": outputProvider = new RSSOutputProvider(); if (outputType == "carwings") ((RSSOutputProvider)outputProvider).EnableCarwingsMode = true; break; case "json": outputProvider = new JSONOutputProvider(); break; case "geojson": outputProvider = new GeoJSONOutputProvider(); break; case "csv": outputProvider = new CSVOutputProvider(); break; case "kml": outputProvider = new KMLOutputProvider(KMLOutputProvider.KMLVersion.V2); break; case "png": outputProvider = new ImageOutputProvider(); break; default: outputProvider = new XMLOutputProvider(); break; } if (outputProvider != null) { context.Response.ContentEncoding = Encoding.Default; context.Response.ContentType = outputProvider.ContentType; if (!(filter.Action == "getcorereferencedata" && String.IsNullOrEmpty(context.Request["SessionToken"]))) { //by default output is cacheable for 24 hrs, unless requested by a specific user. context.Response.Cache.SetExpires(DateTime.Now.AddDays(1)); context.Response.Cache.SetCacheability(HttpCacheability.Public); context.Response.Cache.SetValidUntilExpires(true); } if (ConfigurationManager.AppSettings["EnableOutputCompression"] == "true") { //apply compression if accepted string encodings = context.Request.Headers.Get("Accept-Encoding"); if (encodings != null) { encodings = encodings.ToLower(); if (encodings.ToLower().Contains("gzip")) { context.Response.Filter = new GZipStream(context.Response.Filter, CompressionLevel.Optimal, false); context.Response.AppendHeader("Content-Encoding", "gzip"); //context.Trace.Warn("GZIP Compression on"); } else { context.Response.Filter = new DeflateStream(context.Response.Filter, CompressionMode.Compress); context.Response.AppendHeader("Content-Encoding", "deflate"); //context.Trace.Warn("Deflate Compression on"); } } } if (filter.Action == "getchargepoints" || filter.Action == "getpoilist") { OutputPOIList(outputProvider, context, filter); } if (filter.Action == "getcompactpoilist") { //experimental:: OutputCompactPOIList(context, filter); } if (filter.Action == "getcorereferencedata") { OutputCoreReferenceData(outputProvider, context, filter); } if (filter.Action == "geocode") { this.OutputGeocodingResult(outputProvider, context, filter); } if (filter.Action == "availability") { this.OutputAvailabilityResult(outputProvider, context, filter); } if (filter.Action == "refreshmirror") { try { var itemsUpdated = await OCM.Core.Data.CacheManager.RefreshCachedData(); new JSONOutputProvider().GetOutput(context.Response.OutputStream, new { POICount = itemsUpdated, Status = "OK" }, filter); } catch (Exception exp) { new JSONOutputProvider().GetOutput(context.Response.OutputStream, new { Status = "Error", Message = exp.ToString() }, filter); } } stopwatch.Stop(); System.Diagnostics.Debug.WriteLine("Total output time: " + stopwatch.Elapsed.ToString()); } }
/** * Generic Import Process Provider Properties Import Method Import URL/Path Import Frequency IsMaster Fetch Latest Data For each item Check If Exists or Strong Duplicate, Get ID If New, Add if Exists Then Prepare update, if provider supports live status, set that What if item updated manually on OCM? Send Update End Loop Log Exceptions Log Count of Items Added or Modified Way to remove item (or log items) which no longer exist in data source? * */ public async Task<List<ChargePoint>> DeDuplicateList(List<ChargePoint> cpList, bool updateDuplicate, CoreReferenceData coreRefData, ImportReport report, bool allowDupeWithDifferentOperator = false) { var stopWatch = new Stopwatch(); stopWatch.Start(); //get list of all current POIs (in relevant countries) including most delisted ones int[] countryIds = (from poi in cpList where poi.AddressInfo.Country != null select poi.AddressInfo.Country.ID).Distinct().ToArray(); APIRequestParams filters = new APIRequestParams { CountryIDs = countryIds, MaxResults = 1000000, EnableCaching = false, SubmissionStatusTypeID = 0 }; //List<ChargePoint> masterList = await new OCMClient(IsSandboxedAPIMode).GetLocations(filters); //new OCMClient().FindSimilar(null, 10000); //fetch all charge points regardless of status var poiManager = new POIManager(); List<ChargePoint> masterListCollection = poiManager.GetChargePoints(filters); //new OCMClient().FindSimilar(null, 10000); //fetch all charge points regardless of status var spec = new i4o.IndexSpecification<ChargePoint>() .Add(i => i.DataProviderID) .Add(i => i.DataProvidersReference) ; var masterList = new i4o.IndexSet<ChargePoint>(masterListCollection, spec); List<ChargePoint> masterListCopy = new List<ChargePoint>(); foreach (var tmp in masterList) { //fully copy of master list item so we have before/after masterListCopy.Add(JsonConvert.DeserializeObject<ChargePoint>(JsonConvert.SerializeObject(tmp))); } //if we failed to get a master list, quit with no result if (masterListCollection.Count == 0) return new List<ChargePoint>(); List<ChargePoint> duplicateList = new List<ChargePoint>(); List<ChargePoint> updateList = new List<ChargePoint>(); ChargePoint previousCP = null; //for each item to be imported, deduplicate by adding to updateList only the items which we don't already haves var cpListSortedByPos = cpList.OrderBy(c => c.AddressInfo.Latitude).ThenBy(c => c.AddressInfo.Longitude); int poiProcessed = 0; int totalPOI = cpListSortedByPos.Count(); Stopwatch dupeIdentWatch = new Stopwatch(); dupeIdentWatch.Start(); foreach (var item in cpListSortedByPos) { var itemGeoPos = new System.Device.Location.GeoCoordinate(item.AddressInfo.Latitude, item.AddressInfo.Longitude); //item is duplicate if we already seem to have it based on Data Providers reference or approx position match var dupeList = masterList.Where(c => (c.DataProvider != null && c.DataProviderID == item.DataProviderID && c.DataProvidersReference == item.DataProvidersReference) || (c.AddressInfo.Title == item.AddressInfo.Title && c.AddressInfo.AddressLine1 == item.AddressInfo.AddressLine1 && c.AddressInfo.Postcode == item.AddressInfo.Postcode) || (GeoManager.IsClose(c.AddressInfo.Latitude, c.AddressInfo.Longitude, item.AddressInfo.Latitude, item.AddressInfo.Longitude) && new System.Device.Location.GeoCoordinate(c.AddressInfo.Latitude, c.AddressInfo.Longitude).GetDistanceTo(itemGeoPos) < DUPLICATE_DISTANCE_METERS) //meters distance apart ); if (dupeList.Any()) { if (updateDuplicate) { //if updating duplicates, get exact matching duplicate based on provider reference and update/merge with this item to update status/merge properties var updatedItem = dupeList.FirstOrDefault(d => d.DataProviderID == (item.DataProvider != null ? item.DataProvider.ID : item.DataProviderID) && d.DataProvidersReference == item.DataProvidersReference); if (updatedItem != null) { //only merge/update from live published items if (updatedItem.SubmissionStatus.IsLive == (bool?)true || updatedItem.SubmissionStatus.ID == (int)StandardSubmissionStatusTypes.Delisted_RemovedByDataProvider || updatedItem.SubmissionStatus.ID == (int)StandardSubmissionStatusTypes.Delisted_NotPublicInformation) { //item is an exact match from same data provider //overwrite existing with imported data (use import as master) //updatedItem = poiManager.PreviewPopulatedPOIFromModel(updatedItem); MergeItemChanges(item, updatedItem, false); updateList.Add(updatedItem); } } if (updatedItem == null) { //duplicates are not exact match //TODO: resolve whether imported data should change duplicate //merge new properties from imported item //if (item.StatusType != null) updatedItem.StatusType = item.StatusType; //updateList.Add(updatedItem); } } //item has one or more likely duplicates, add it to list of items to remove duplicateList.Add(item); } //mark item as duplicate if location/title exactly matches previous entry or lat/long is within DuplicateDistance meters if (previousCP != null) { //this branch is the most expensive part of dedupe: if (IsDuplicateLocation(item, previousCP, true)) { if (!duplicateList.Contains(item)) { if (allowDupeWithDifferentOperator && item.OperatorID != previousCP.OperatorID) { Log("Duplicated allowed due to different operator:" + item.AddressInfo.Title); } else { Log("Duplicated item removed:" + item.AddressInfo.Title); duplicateList.Add(item); } } } } previousCP = item; poiProcessed++; if (poiProcessed % 300 == 0) { System.Diagnostics.Debug.WriteLine("Deduplication: " + poiProcessed + " processed of " + totalPOI); } } dupeIdentWatch.Stop(); Log("De-dupe pass took " + dupeIdentWatch.Elapsed.TotalSeconds + " seconds. " + (dupeIdentWatch.Elapsed.TotalMilliseconds / cpList.Count) + "ms per item."); //remove duplicates from list to apply foreach (var dupe in duplicateList) { cpList.Remove(dupe); } Log("Duplicates removed from import:" + duplicateList.Count); //add updated items (replace duplicates with property changes) foreach (var updatedItem in updateList) { if (!cpList.Contains(updatedItem)) { cpList.Add(updatedItem); } } Log("Updated items to import:" + updateList.Count); //populate missing location info from geolocation cache if possible Stopwatch geoWatch = new Stopwatch(); geoWatch.Start(); PopulateLocationFromGeolocationCache(cpList, coreRefData); geoWatch.Stop(); Log("Populate Country from Lat/Long took " + geoWatch.Elapsed.TotalSeconds + " seconds. " + (geoWatch.Elapsed.TotalMilliseconds / cpList.Count) + "ms per item."); //final pass to catch duplicates present in data source, mark additional items as Delisted Duplicate so we have a record for them var submissionStatusDelistedDupe = coreRefData.SubmissionStatusTypes.First(s => s.ID == 1001); //delisted duplicate previousCP = null; //sort current cp list by position again cpListSortedByPos = cpList.OrderBy(c => c.AddressInfo.Latitude).ThenBy(c => c.AddressInfo.Longitude); //mark any duplicates in final list as delisted duplicates (submitted to api) foreach (var cp in cpListSortedByPos) { bool isDuplicate = false; if (previousCP != null) { isDuplicate = IsDuplicateLocation(cp, previousCP, false); if (isDuplicate) { cp.SubmissionStatus = submissionStatusDelistedDupe; cp.SubmissionStatusTypeID = submissionStatusDelistedDupe.ID; if (previousCP.ID > 0) { if (cp.GeneralComments == null) cp.GeneralComments = ""; cp.GeneralComments += " [Duplicate of OCM-" + previousCP.ID + "]"; cp.ParentChargePointID = previousCP.ID; } } } if (!isDuplicate) { previousCP = cp; } } report.Added = cpListSortedByPos.Where(cp => cp.ID == 0).ToList(); report.Updated = cpListSortedByPos.Where(cp => cp.ID > 0).ToList(); report.Duplicates = duplicateList; //TODO: add additional pass of duplicates from above //determine which POIs in our master list are no longer referenced in the import report.Delisted = masterList.Where(cp => cp.DataProviderID == report.ProviderDetails.DataProviderID && cp.SubmissionStatus != null && (cp.SubmissionStatus.IsLive == true || cp.SubmissionStatusTypeID == (int)StandardSubmissionStatusTypes.Imported_UnderReview) && !cpListSortedByPos.Any(master => master.ID == cp.ID) && !report.Duplicates.Any(master => master.ID == cp.ID) && cp.UserComments == null && cp.MediaItems == null).ToList(); //safety check to ensure we're not delisting items just because we have incomplete import data: if (cpList.Count < 50)// || (report.Delisted.Count > cpList.Count)) { report.Delisted = new List<ChargePoint>(); } //determine list of low quality POIs (incomplete address info etc) report.LowDataQuality = new List<ChargePoint>(); report.LowDataQuality.AddRange(GetLowDataQualityPOIs(report.Added)); report.LowDataQuality.AddRange(GetLowDataQualityPOIs(report.Updated)); Log("Removing " + report.LowDataQuality.Count + " low quality POIs from added/updated"); //remove references in added/updated to any low quality POIs foreach (var p in report.LowDataQuality) { report.Added.Remove(p); } foreach (var p in report.LowDataQuality) { report.Updated.Remove(p); } //remove updates which only change datelaststatusupdate var updatesToIgnore = new List<ChargePoint>(); foreach (var poi in report.Updated) { var origPOI = masterListCopy.FirstOrDefault(p => p.ID == poi.ID); var updatedPOI = poiManager.PreviewPopulatedPOIFromModel(poi); var differences = poiManager.CheckDifferences(origPOI, updatedPOI); differences.RemoveAll(d => d.Context == ".MetadataValues"); differences.RemoveAll(d => d.Context == ".DateLastStatusUpdate"); differences.RemoveAll(d => d.Context == ".UUID"); differences.RemoveAll(d => d.Context == ".DataProvider.DateLastImported"); differences.RemoveAll(d => d.Context == ".IsRecentlyVerified"); differences.RemoveAll(d => d.Context == ".DateLastVerified"); differences.RemoveAll(d => d.Context == ".UserComments"); differences.RemoveAll(d => d.Context == ".MediaItems"); if (!differences.Any()) { updatesToIgnore.Add(poi); } else { //differences exist CompareLogic compareLogic = new CompareLogic(); compareLogic.Config.MaxDifferences = 100; compareLogic.Config.IgnoreObjectTypes = false; compareLogic.Config.IgnoreUnknownObjectTypes = true; compareLogic.Config.CompareChildren = true; ComparisonResult result = compareLogic.Compare(origPOI, updatedPOI); var diffReport = new KellermanSoftware.CompareNetObjects.Reports.UserFriendlyReport(); result.Differences.RemoveAll(d => d.PropertyName == ".MetadataValues"); result.Differences.RemoveAll(d => d.PropertyName == ".DateLastStatusUpdate"); result.Differences.RemoveAll(d => d.PropertyName == ".UUID"); result.Differences.RemoveAll(d => d.PropertyName == ".DataProvider.DateLastImported"); result.Differences.RemoveAll(d => d.PropertyName == ".IsRecentlyVerified"); result.Differences.RemoveAll(d => d.PropertyName == ".DateLastVerified"); result.Differences.RemoveAll(d => d.PropertyName == ".UserComments"); result.Differences.RemoveAll(d => d.PropertyName == ".MediaItems"); System.Diagnostics.Debug.WriteLine("Difference:" + diffReport.OutputString(result.Differences)); if (!result.Differences.Any()) { updatesToIgnore.Add(poi); } } } foreach (var p in updatesToIgnore) { if (report.Unchanged == null) report.Unchanged = new List<ChargePoint>(); report.Unchanged.Add(p); report.Updated.Remove(p); } //TODO: if POi is a duplicate ensure imported data provider reference/URL is included as reference metadata in OCM's version of the POI stopWatch.Stop(); Log("Deduplicate List took " + stopWatch.Elapsed.TotalSeconds + " seconds"); //return final processed list ready for applying as insert/updates return cpListSortedByPos.ToList(); }
/// <summary> /// For given query/output settings, return list of charge points. May be a cached response. /// </summary> /// <param name="settings"></param> /// <returns></returns> public List<Model.ChargePoint> GetChargePoints(APIRequestParams settings) { var stopwatch = new Stopwatch(); stopwatch.Start(); bool cachingConfigEnabled = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["EnableInMemoryCaching"]); if (cachingConfigEnabled == false) settings.EnableCaching = false; string cacheKey = settings.HashKey; List<Model.ChargePoint> dataList = null; if ((HttpContext.Current != null && HttpContext.Current.Cache[cacheKey] == null) || settings.EnableCaching == false) { bool enableNoSQLCaching = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["EnableNoSQLCaching"]); if (enableNoSQLCaching && settings.AllowMirrorDB) { try { dataList = new CacheProviderMongoDB().GetPOIList(settings); } catch (Exception exp) { //failed to query mirror db, will now fallback to sql server if dataList is null //TODO: send error notification if (HttpContext.Current != null) AuditLogManager.ReportWebException(HttpContext.Current.Server, AuditEventType.SystemErrorAPI, "POI Cache query exception:"+exp.ToString()); } } //if dataList is null we didn't get any cache DB results, use SQL DB if (dataList == null) { int maxResults = settings.MaxResults; this.LoadUserComments = settings.IncludeComments; bool requiresDistance = false; if (settings.Latitude != null && settings.Longitude != null) { requiresDistance = true; //maxResults = 10000; //TODO find way to prefilter on distance. } dataList = new List<Model.ChargePoint>(); var dataModel = new OCMEntities(); dataModel.Configuration.LazyLoadingEnabled = true; dataModel.Configuration.AutoDetectChangesEnabled = false; ((IObjectContextAdapter)dataModel).ObjectContext.CommandTimeout = 180; //allow longer time for query to complete //if distance filter provided in miles, convert to KM before use if (settings.DistanceUnit == Model.DistanceUnit.Miles && settings.Distance != null) { settings.Distance = GeoManager.ConvertMilesToKM((double)settings.Distance); } bool filterByConnectionTypes = false; bool filterByLevels = false; bool filterByOperators = false; bool filterByCountries = false; bool filterByUsage = false; bool filterByStatus = false; bool filterByDataProvider = false; bool filterByChargePoints = false; if (settings.ConnectionTypeIDs != null) { filterByConnectionTypes = true; } else { settings.ConnectionTypeIDs = new int[] { -1 }; } if (settings.LevelIDs != null) { filterByLevels = true; } else { settings.LevelIDs = new int[] { -1 }; } if (settings.OperatorIDs != null) { filterByOperators = true; } else { settings.OperatorIDs = new int[] { -1 }; } if (settings.ChargePointIDs != null) { filterByChargePoints = true; } else { settings.ChargePointIDs = new int[] { -1 }; } //either filter by named country code or by country id list if (settings.CountryCode != null) { var filterCountry = dataModel.Countries.FirstOrDefault(c => c.ISOCode.ToUpper() == settings.CountryCode.ToUpper()); if (filterCountry != null) { filterByCountries = true; settings.CountryIDs = new int[] { filterCountry.ID }; } else { filterByCountries = false; settings.CountryIDs = new int[] { -1 }; } } else { if (settings.CountryIDs != null && settings.CountryIDs.Any()) { filterByCountries = true; } else { settings.CountryIDs = new int[] { -1 }; } } if (settings.UsageTypeIDs != null) { filterByUsage = true; } else { settings.UsageTypeIDs = new int[] { -1 }; } if (settings.StatusTypeIDs != null) { filterByStatus = true; } else { settings.StatusTypeIDs = new int[] { -1 }; } if (settings.DataProviderIDs != null) { filterByDataProvider = true; } else { settings.DataProviderIDs = new int[] { -1 }; } if (settings.SubmissionStatusTypeID == -1) settings.SubmissionStatusTypeID = null; //compile initial list of locations var chargePointList = from c in dataModel.ChargePoints.AsNoTracking() where (c.AddressInfo != null && c.AddressInfo.Latitude != null && c.AddressInfo.Longitude != null && c.AddressInfo.CountryID != null) && ((settings.SubmissionStatusTypeID == null && (c.SubmissionStatusTypeID == null || c.SubmissionStatusTypeID == (int)StandardSubmissionStatusTypes.Imported_Published || c.SubmissionStatusTypeID == (int)StandardSubmissionStatusTypes.Submitted_Published)) || (settings.SubmissionStatusTypeID == 0) //return all regardless of status || (settings.SubmissionStatusTypeID != null && c.SubmissionStatusTypeID == settings.SubmissionStatusTypeID) ) //by default return live cps only, otherwise use specific submission statusid && (c.SubmissionStatusTypeID != (int)StandardSubmissionStatusTypes.Delisted_NotPublicInformation) && (settings.OperatorName == null || c.Operator.Title == settings.OperatorName) && (settings.IsOpenData == null || (settings.IsOpenData != null && ((settings.IsOpenData == true && c.DataProvider.IsOpenDataLicensed == true) || (settings.IsOpenData == false && c.DataProvider.IsOpenDataLicensed != true)))) && (settings.DataProviderName == null || c.DataProvider.Title == settings.DataProviderName) && (settings.LocationTitle == null || c.AddressInfo.Title.Contains(settings.LocationTitle)) && (filterByCountries == false || (filterByCountries == true && settings.CountryIDs.Contains((int)c.AddressInfo.CountryID))) && (filterByOperators == false || (filterByOperators == true && settings.OperatorIDs.Contains((int)c.OperatorID))) && (filterByChargePoints == false || (filterByChargePoints == true && settings.ChargePointIDs.Contains((int)c.ID))) && (filterByUsage == false || (filterByUsage == true && settings.UsageTypeIDs.Contains((int)c.UsageTypeID))) && (filterByStatus == false || (filterByStatus == true && settings.StatusTypeIDs.Contains((int)c.StatusTypeID))) && (filterByDataProvider == false || (filterByDataProvider == true && settings.DataProviderIDs.Contains((int)c.DataProviderID))) select c; if (settings.ChangesFromDate != null) { chargePointList = chargePointList.Where(c => c.DateLastStatusUpdate >= settings.ChangesFromDate.Value); } if (settings.CreatedFromDate != null) { chargePointList = chargePointList.Where(c => c.DateCreated >= settings.CreatedFromDate.Value); } //apply connectionInfo filters, all filters must match a distinct connection within the charge point, rather than any filter matching any connectioninfo chargePointList = from c in chargePointList where c.Connections.Any(conn => (settings.ConnectionType == null || (settings.ConnectionType != null && conn.ConnectionType.Title == settings.ConnectionType)) && (settings.MinPowerKW == null || (settings.MinPowerKW != null && conn.PowerKW >= settings.MinPowerKW)) && (filterByConnectionTypes == false || (filterByConnectionTypes == true && settings.ConnectionTypeIDs.Contains(conn.ConnectionType.ID))) && (filterByLevels == false || (filterByLevels == true && settings.LevelIDs.Contains((int)conn.ChargerType.ID))) ) select c; System.Data.Entity.Spatial.DbGeography searchPos = null; if (requiresDistance && settings.Latitude != null && settings.Longitude != null) searchPos = System.Data.Entity.Spatial.DbGeography.PointFromText("POINT(" + settings.Longitude + " " + settings.Latitude + ")", 4326); //compute/filter by distance (if required) var filteredList = from c in chargePointList where (requiresDistance == false) || ( (requiresDistance == true && (c.AddressInfo.Latitude != null && c.AddressInfo.Longitude != null) && (settings.Latitude != null && settings.Longitude != null) && (settings.Distance == null || (settings.Distance != null && // GetDistanceFromLatLonKM(settings.Latitude, settings.Longitude, c.AddressInfo.Latitude, c.AddressInfo.Longitude) <= settings.Distance c.AddressInfo.SpatialPosition.Distance(searchPos) / 1000 < settings.Distance ) ) ) ) select new { c, // DistanceKM = GetDistanceFromLatLonKM(settings.Latitude, settings.Longitude, c.AddressInfo.Latitude, c.AddressInfo.Longitude) DistanceKM = c.AddressInfo.SpatialPosition.Distance(searchPos) / 1000 }; if (requiresDistance) { //if distance was a required output, sort results by distance filteredList = filteredList.OrderBy(d => d.DistanceKM).Take(settings.MaxResults); } else { filteredList = filteredList.OrderByDescending(p => p.c.DateCreated); } //query is of type IQueryable #if DEBUG string sql = filteredList.ToString(); //writes to output window System.Diagnostics.Debug.WriteLine(sql); #endif var additionalFilteredList = filteredList.Take(maxResults).ToList(); stopwatch.Stop(); System.Diagnostics.Debug.WriteLine("Total query time: " + stopwatch.Elapsed.ToString()); stopwatch.Restart(); foreach (var item in additionalFilteredList) //.ToList { //note: if include comments is enabled, media items and metadata values are also included Model.ChargePoint c = Model.Extensions.ChargePoint.FromDataModel(item.c, settings.IncludeComments, settings.IncludeComments, settings.IncludeComments, !settings.IsCompactOutput); if (requiresDistance && c.AddressInfo != null) { c.AddressInfo.Distance = item.DistanceKM; if (settings.DistanceUnit == Model.DistanceUnit.Miles && c.AddressInfo.Distance != null) c.AddressInfo.Distance = GeoManager.ConvertKMToMiles(c.AddressInfo.Distance); c.AddressInfo.DistanceUnit = settings.DistanceUnit; } if (settings.IsLegacyAPICall && !(settings.APIVersion >= 2)) { //for legacy callers, produce artificial list of Charger items #pragma warning disable 612 //suppress obsolete warning if (c.Chargers == null || c.Chargers.Count == 0) { if (c.Connections != null) { var chargerList = new List<Common.Model.ChargerInfo>(); foreach (var con in c.Connections) { if (con.Level != null) { if (!chargerList.Exists(l => l.ChargerType == con.Level)) { chargerList.Add(new Common.Model.ChargerInfo() { ChargerType = con.Level }); } } } chargerList = chargerList.Distinct().ToList(); c.Chargers = chargerList; } } } #pragma warning restore 612 if (c != null) { dataList.Add(c); } } //cache results (if caching enabled) if (settings.EnableCaching == true && HttpContext.Current != null) { HttpContext.Current.Cache.Add(cacheKey, dataList, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 30, 0), System.Web.Caching.CacheItemPriority.AboveNormal, null); } } } else { //TODO: pass caching context instead of trying to access HttpContext.Current as not available during async if (HttpContext.Current != null) { dataList = (List<Model.ChargePoint>)HttpContext.Current.Cache[cacheKey]; } } System.Diagnostics.Debug.WriteLine("POI List Conversion to simple data model: " + stopwatch.Elapsed.ToString()); return dataList.Take(settings.MaxResults).ToList(); }
public void GetOutput(Stream outputStream, List<Common.Model.ChargePoint> dataList, APIRequestParams settings) { XmlTextWriter xml = new XmlTextWriter(outputStream, Encoding.UTF8); //start xml document xml.WriteStartDocument(); //output rss tags xml.WriteStartElement("rss"); xml.WriteAttributeString("version", "2.0"); if (EnableCarwingsMode) xml.WriteAttributeString("xmlns", "carwings", "http://www.w3.org/2000/xmlns/", "http://www.nissan.co.jp/dtd/carwings.dtd"); if (EnableGeoRSS) xml.WriteAttributeString("xmlns", "georss", "http://www.w3.org/2000/xmlns/", "http://www.georss.org/georss/10"); //output feed details xml.WriteStartElement("channel"); xml.WriteElementString("title", "OpenChargeMap Charge Points"); xml.WriteElementString("link", "http://openchargemap.org"); xml.WriteElementString("description", "Charge Point data contributed by OpenChargeMap community"); xml.WriteElementString("copyright", "openchargemap.org"); //output feed items foreach (var item in dataList) { if (item.AddressInfo != null) { xml.WriteStartElement("item"); xml.WriteStartElement("guid"); xml.WriteAttributeString("isPermaLink","false"); xml.WriteString(item.UUID); xml.WriteEndElement(); xml.WriteElementString("title", item.AddressInfo.Title); if (EnableCarwingsMode) { xml.WriteElementString("carwings:readtitle", item.AddressInfo.Title); } string description = item.GetSummaryDescription(true); string address = item.GetAddressSummary(true); xml.WriteElementString("description", description); if (item.AddressInfo.RelatedURL != null) { xml.WriteElementString("link", item.AddressInfo.RelatedURL); } if (EnableCarwingsMode) { if (address != "") xml.WriteElementString("carwings:address", address); if (item.AddressInfo.ContactTelephone1 != null) xml.WriteElementString("carwings:tel", item.AddressInfo.ContactTelephone1); xml.WriteElementString("carwings:lat", item.AddressInfo.Latitude.ToString()); xml.WriteElementString("carwings:lon", item.AddressInfo.Longitude.ToString()); } if (EnableGeoRSS) { xml.WriteElementString("georss:point", item.AddressInfo.Latitude.ToString()+" "+item.AddressInfo.Longitude.ToString()); } xml.WriteEndElement(); } } xml.WriteEndElement(); //end channel xml.WriteEndElement(); //end rss xml.WriteEndDocument(); //end xml xml.Flush(); //xml.Close(); #region example rss /* <?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:carwings="http://www.nissan.co.jp/dtd/carwings.dtd"> <channel> <title> WEB site update: NISSAN Topics </ title> <link> http://rss.nissan.co.jp/ </ link> <description> Nissan will deliver the latest information. </ Description> <language>en</ language> <copyright> Copyright NISSAN MOTOR CO., LTD. 2005 All Rights Reserved. </ copyright> <lastBuildDate> Wed, 25 Oct 2006 12:18:36 +0900 </ lastBuildDate> <docs> http://blogs.law.harvard.edu/tech/rss </ docs> <item> <title>update information</ title> <carwings:readtitle> Trail Jam update information </ carwings: readtitle> <description> X-TRAIL JAM IN TOKYO DOME general tickets on sale! ! </ Description> <carwings:readtext> Trail Jam Tokyo Dome tickets, general sale.</ Carwings: readtext> <Carwings:itemimage> http://eplus.jp/sys/web/irg/2006x-trail/images/topmain.jpg </ Carwings: Itemimage> <Carwings:data> <! [CDATA [ TRAIL <body> <br> <img src="http://lab.nissan-carwings.com/CWC/images/x-trail.jpg"> </ body> ]]> </ Carwings: data> <carwings:lat> 35.70568 </ carwings: lat> <carwings:lon> 139.75187 </ carwings: lon> <link> http://blog.nissan.co.jp/X-TRAIL/?rss </ link> <guid> http://blog.nissan.co.jp/X-TRAIL/?rss </ guid> <Carwings:link> Http://Www.nissan.co.jp/Event/....../Coupon.html </ Carwings: Link> <category> content </ category> <pubDate> Mon, 16 Oct 2006 20:15:02 +0900 </ pubDate> </item> </channel> </rss> * */ #endregion }
public void GetOutput(Stream outputStream, Object data, APIRequestParams settings) { throw new NotImplementedException(); }
public void GetOutput(Stream outputStream, Common.Model.CoreReferenceData data, APIRequestParams settings) { throw new NotImplementedException(); }
public SubscriptionMatchGroup GetSubscriptionMatches(OCM.Core.Data.OCMEntities dataModel, POIManager poiManager, OCM.Core.Data.UserSubscription subscription, DateTime?dateFrom = null) { SubscriptionMatchGroup subscriptionMatchGroup = new SubscriptionMatchGroup(); var checkFromDate = DateTime.UtcNow.AddMinutes(-CHECK_INTERVAL_MINS); //check from last 5 mins etc if (subscription.DateLastNotified != null) { checkFromDate = subscription.DateLastNotified.Value; //check from date last notified } else { checkFromDate = subscription.DateCreated; } if (dateFrom != null) { checkFromDate = dateFrom.Value; } subscriptionMatchGroup.DateFrom = checkFromDate; System.Data.Entity.Spatial.DbGeography searchPos = null; UserSubscriptionFilter filter = null; if (subscription.FilterSettings != null) { try { filter = JsonConvert.DeserializeObject <UserSubscriptionFilter>(subscription.FilterSettings); } catch (Exception) { //failed to parse subscription filter } } if (subscription.Latitude != null && subscription.Longitude != null) { searchPos = System.Data.Entity.Spatial.DbGeography.PointFromText("POINT(" + subscription.Longitude + " " + subscription.Latitude + ")", 4326); } if (subscription.NotifyEmergencyChargingRequests) { var emergencyCharging = dataModel.UserChargingRequests.Where(c => c.DateCreated >= checkFromDate && c.IsActive == true && c.IsEmergency == true); var subscriptionMatch = new SubscriptionMatch { Category = SubscriptionMatchCategory.ChargingRequestEmergency, Description = "New Emergency Charging Requests" }; foreach (var chargingRequest in emergencyCharging) { //filter on location if (searchPos != null) { if (GeoManager.CalcDistance(chargingRequest.Latitude, chargingRequest.Longitude, (double)searchPos.Latitude, (double)searchPos.Longitude, DistanceUnit.KM) < subscription.DistanceKM) { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = chargingRequest }); } } else { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = chargingRequest }); } } if (subscriptionMatch.ItemList.Any()) { subscriptionMatchGroup.SubscriptionMatches.Add(subscriptionMatch); } } if (subscription.NotifyGeneralChargingRequests) { //TODO: subscription not filtered on lat/long will return global charging requests var generalCharging = dataModel.UserChargingRequests.Where(c => c.DateCreated >= checkFromDate && c.IsActive == true && c.IsEmergency == false); var subscriptionMatch = new SubscriptionMatch { Category = SubscriptionMatchCategory.ChargingRequestGeneral, Description = "New Charging Requests" }; //filter on location foreach (var gc in generalCharging) { if (searchPos != null) { if (GeoManager.CalcDistance(gc.Latitude, gc.Longitude, (double)searchPos.Latitude, (double)searchPos.Longitude, DistanceUnit.KM) < subscription.DistanceKM) { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = gc }); } } else { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = gc }); } } if (subscriptionMatch.ItemList.Any()) { subscriptionMatchGroup.SubscriptionMatches.Add(subscriptionMatch); } } //check if any POI Edits (pending approval) match this subscription if (subscription.NotifyPOIEdits) { var poiEdits = dataModel.EditQueueItems.Where(c => c.DateSubmitted >= checkFromDate && c.PreviousData != null && c.IsProcessed == false); if (poiEdits.Any()) { var subscriptionMatch = new SubscriptionMatch { Category = SubscriptionMatchCategory.EditedPOI, Description = "Proposed POI Edits" }; foreach (var p in poiEdits) { try { var updatedPOI = JsonConvert.DeserializeObject <ChargePoint>(p.EditData); if (IsPOISubscriptionFilterMatch(updatedPOI, filter, subscription)) { if (searchPos != null) { if (GeoManager.CalcDistance(updatedPOI.AddressInfo.Latitude, updatedPOI.AddressInfo.Longitude, (double)searchPos.Latitude, (double)searchPos.Longitude, DistanceUnit.KM) < subscription.DistanceKM) { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = p, POI = updatedPOI }); } } else { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = p, POI = updatedPOI }); } } } catch (Exception) { ;; } } if (subscriptionMatch.ItemList.Any()) { subscriptionMatchGroup.SubscriptionMatches.Add(subscriptionMatch); } } } //check if any new POIs if (subscription.NotifyPOIAdditions) { /* var newPOIs = dataModel.ChargePoints.Where(c => c.DateCreated >= checkFromDate && c.SubmissionStatusType.IsLive == true && * (searchPos == null || * (searchPos != null && * c.AddressInfo.SpatialPosition.Distance(searchPos) / 1000 < subscription.DistanceKM * )) * ).ToList();*/ var filterParams = new APIRequestParams { CreatedFromDate = checkFromDate, AllowMirrorDB = true }; if (searchPos != null) { filterParams.DistanceUnit = DistanceUnit.KM; filterParams.Distance = subscription.DistanceKM; filterParams.Latitude = searchPos.Latitude; filterParams.Longitude = searchPos.Longitude; } if (subscription.CountryID != null) { filterParams.CountryIDs = new int[] { (int)subscription.CountryID }; } var poiCollection = poiManager.GetChargePoints(filterParams); if (poiCollection.Any()) { var subscriptionMatch = new SubscriptionMatch { Category = SubscriptionMatchCategory.NewPOI, Description = "New POIs Added" }; foreach (var p in poiCollection) { //var poi = OCM.API.Common.Model.Extensions.ChargePoint.FromDataModel(p); if (IsPOISubscriptionFilterMatch(p, filter, subscription)) { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { POI = p }); } } if (subscriptionMatch.ItemList.Any()) { subscriptionMatchGroup.SubscriptionMatches.Add(subscriptionMatch); } } } //check if any POI Updates match this subscription if (subscription.NotifyPOIUpdates) { var poiUpdates = dataModel.EditQueueItems.Where(c => c.DateProcessed >= checkFromDate && c.IsProcessed == true && c.PreviousData != null); if (poiUpdates.Any()) { var subscriptionMatch = new SubscriptionMatch { Category = SubscriptionMatchCategory.UpdatedPOI, Description = "POIs Updated" }; foreach (var p in poiUpdates) { try { var updatedPOI = JsonConvert.DeserializeObject <ChargePoint>(p.EditData); if (IsPOISubscriptionFilterMatch(updatedPOI, filter, subscription)) { if (searchPos != null) { if (GeoManager.CalcDistance(updatedPOI.AddressInfo.Latitude, updatedPOI.AddressInfo.Longitude, (double)searchPos.Latitude, (double)searchPos.Longitude, DistanceUnit.KM) < subscription.DistanceKM) { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = p, POI = updatedPOI }); } } else { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = p, POI = updatedPOI }); } } } catch (Exception) { ;; } } if (subscriptionMatch.ItemList.Any()) { subscriptionMatchGroup.SubscriptionMatches.Add(subscriptionMatch); } } } //check if any new comments match this subscription if (subscription.NotifyComments) { var newComments = dataModel.UserComments.Where(c => c.DateCreated >= checkFromDate && (searchPos == null || (searchPos != null && c.ChargePoint.AddressInfo.SpatialPosition.Distance(searchPos) / 1000 < subscription.DistanceKM )) ); if (newComments.Any()) { var subscriptionMatch = new SubscriptionMatch { Category = SubscriptionMatchCategory.NewComment, Description = "New Comments Added" }; foreach (var c in newComments) { var poi = OCM.API.Common.Model.Extensions.ChargePoint.FromDataModel(c.ChargePoint); if (IsPOISubscriptionFilterMatch(poi, filter, subscription)) { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = OCM.API.Common.Model.Extensions.UserComment.FromDataModel(c, true), POI = poi }); } } if (subscriptionMatch.ItemList.Any()) { subscriptionMatchGroup.SubscriptionMatches.Add(subscriptionMatch); } } } //check if any new Media uploads match this subscription if (subscription.NotifyMedia) { var newMedia = dataModel.MediaItems.Where(c => c.DateCreated >= checkFromDate && (searchPos == null || (searchPos != null && c.ChargePoint.AddressInfo.SpatialPosition.Distance(searchPos) / 1000 < subscription.DistanceKM )) ); if (newMedia.Any()) { var subscriptionMatch = new SubscriptionMatch { Category = SubscriptionMatchCategory.NewMediaUpload, Description = "New Photos Added" }; foreach (var c in newMedia) { var poi = OCM.API.Common.Model.Extensions.ChargePoint.FromDataModel(c.ChargePoint); if (IsPOISubscriptionFilterMatch(poi, filter, subscription)) { subscriptionMatch.ItemList.Add(new SubscriptionMatchItem { Item = OCM.API.Common.Model.Extensions.MediaItem.FromDataModel(c), POI = poi }); } } if (subscriptionMatch.ItemList.Any()) { subscriptionMatchGroup.SubscriptionMatches.Add(subscriptionMatch); } } } return(subscriptionMatchGroup); }
public void ParseParameters(APIRequestParams settings, HttpContext context) { //get parameter values if any if (!String.IsNullOrEmpty(context.Request["v"])) { settings.APIVersion = ParseInt(context.Request["v"]); } if (settings.APIVersion > MAX_API_VERSION) { settings.APIVersion = MAX_API_VERSION; } if (!String.IsNullOrEmpty(context.Request["action"])) { settings.Action = ParseString(context.Request["action"]); } if (!String.IsNullOrEmpty(context.Request["apikey"])) { settings.APIKey = ParseString(context.Request["apikey"]); } if (!String.IsNullOrEmpty(context.Request["chargepointid"])) { settings.ChargePointIDs = ParseIntList(context.Request["chargepointid"]); } if (!String.IsNullOrEmpty(context.Request["operatorname"])) { settings.OperatorName = ParseString(context.Request["operatorname"]); } if (!String.IsNullOrEmpty(context.Request["operatorid"])) { settings.OperatorIDs = ParseIntList(context.Request["operatorid"]); } if (!String.IsNullOrEmpty(context.Request["connectiontypeid"])) { settings.ConnectionTypeIDs = ParseIntList(context.Request["connectiontypeid"]); } if (!String.IsNullOrEmpty(context.Request["countryid"])) { settings.CountryIDs = ParseIntList(context.Request["countryid"]); } if (!String.IsNullOrEmpty(context.Request["levelid"])) { settings.LevelIDs = ParseIntList(context.Request["levelid"]); } if (!String.IsNullOrEmpty(context.Request["usagetypeid"])) { settings.UsageTypeIDs = ParseIntList(context.Request["usagetypeid"]); } if (!String.IsNullOrEmpty(context.Request["statustypeid"])) { settings.StatusTypeIDs = ParseIntList(context.Request["statustypeid"]); } if (!String.IsNullOrEmpty(context.Request["dataproviderid"])) { settings.DataProviderIDs = ParseIntList(context.Request["dataproviderid"]); } if (!String.IsNullOrEmpty(context.Request["opendata"])) { settings.IsOpenData = ParseBoolNullable(context.Request["opendata"]); } if (!String.IsNullOrEmpty(context.Request["minpowerkw"])) { settings.MinPowerKW = ParseDouble(context.Request["minpowerkw"]); } if (!String.IsNullOrEmpty(context.Request["dataprovidername"])) { settings.DataProviderName = ParseString(context.Request["dataprovidername"]); } if (!String.IsNullOrEmpty(context.Request["locationtitle"])) { settings.LocationTitle = ParseString(context.Request["locationtitle"]); } if (!String.IsNullOrEmpty(context.Request["address"])) { settings.Address = ParseString(context.Request["address"]); } if (!String.IsNullOrEmpty(context.Request["countrycode"])) { settings.CountryCode = ParseString(context.Request["countrycode"]); } if (!String.IsNullOrEmpty(context.Request["latitude"])) { settings.Latitude = ParseDouble(context.Request["latitude"]); if (settings.Latitude < -90 || settings.Latitude > 90) { settings.Latitude = null; } } if (!String.IsNullOrEmpty(context.Request["longitude"])) { settings.Longitude = ParseDouble(context.Request["longitude"]); if (settings.Longitude < -180 || settings.Longitude > 180) { settings.Longitude = null; } } if (!String.IsNullOrEmpty(context.Request["distance"])) { settings.Distance = ParseDouble(context.Request["distance"]); } if (!String.IsNullOrEmpty(context.Request["distanceunit"])) { settings.DistanceUnit = ParseDistanceUnit(context.Request["distanceunit"]); } if (!String.IsNullOrEmpty(context.Request["polyline"])) { settings.Polyline = ParsePolyline(context.Request["polyline"]); } //e.g. |k~aEm|bbUewBx}C_kEnyCi}Edn@d\ssFb\kyN //settings.Polyline = ParsePolyline("_p~iF~ps|U_ulLnnqC_mqNvxq`@"); //settings.Polyline = ParsePolyline("(38.5, -120.2), (40.7, -120.95), (43.252, -126.453)"); if (!String.IsNullOrEmpty(context.Request["boundingbox"])) { settings.BoundingBox = ParseBoundingBox(context.Request["boundingbox"]); //e.g. (-31.947017,115.803974),(-31.956672,115.819968) } if (!String.IsNullOrEmpty(context.Request["polygon"])) { settings.Polygon = ParsePolygon(context.Request["polygon"], true); } if (!String.IsNullOrEmpty(context.Request["connectiontype"])) { settings.ConnectionType = ParseString(context.Request["connectiontype"]); } if (!String.IsNullOrEmpty(context.Request["submissionstatustypeid"])) { settings.SubmissionStatusTypeID = ParseInt(context.Request["submissionstatustypeid"]); } if (!String.IsNullOrEmpty(context.Request["modifiedsince"])) { settings.ChangesFromDate = ParseDate(context.Request["modifiedsince"]); } if (!String.IsNullOrEmpty(context.Request["levelofdetail"])) { settings.LevelOfDetail = ParseInt(context.Request["levelofdetail"]); } if (!String.IsNullOrEmpty(context.Request["enablecaching"])) { settings.EnableCaching = ParseBool(context.Request["enablecaching"], true); } if (!String.IsNullOrEmpty(context.Request["allowmirror"])) { settings.AllowMirrorDB = ParseBool(context.Request["allowmirror"], false); } if (!String.IsNullOrEmpty(context.Request["includecomments"])) { settings.IncludeComments = ParseBool(context.Request["includecomments"], false); } if (!String.IsNullOrEmpty(context.Request["verbose"])) { settings.IsVerboseOutput = ParseBool(context.Request["verbose"], false); } if (!String.IsNullOrEmpty(context.Request["compact"])) { settings.IsCompactOutput = ParseBool(context.Request["compact"], false); } if (!String.IsNullOrEmpty(context.Request["camelcase"])) { settings.IsCamelCaseOutput = ParseBool(context.Request["camelcase"], false); } if (!String.IsNullOrEmpty(context.Request["callback"])) { settings.Callback = ParseString(context.Request["callback"]); } if (!String.IsNullOrEmpty(context.Request["maxresults"])) { try { settings.MaxResults = int.Parse(context.Request["maxresults"]); } catch (Exception) { settings.MaxResults = 100; } } //default action if (String.IsNullOrEmpty(settings.Action)) { settings.Action = "getchargepoints"; } //handle deprecated items if (settings.APIVersion == null || settings.APIVersion == 1) { if (!String.IsNullOrEmpty(context.Request["fastchargeonly"])) { settings.FastChargeOnly = ParseBool(context.Request["fastchargeonly"], false); } } }
/// <summary> /// Output standard POI List results /// </summary> /// <param name="outputProvider"></param> /// <param name="context"></param> /// <param name="filter"></param> private void OutputPOIList(IOutputProvider outputProvider, HttpContext context, APIRequestParams filter) { List<OCM.API.Common.Model.ChargePoint> dataList = null; //get list of charge points for output: dataList = new POIManager().GetChargePoints(filter); int numResults = dataList.Count; //send response outputProvider.GetOutput(context.Response.OutputStream, dataList, filter); }