public void query_gemini_records() { IDocumentStore store = new DocumentStore { Url = RavenUrl }.Initialize(); RavenUtility.WaitForIndexing(store); string peakDistrictBbox = BoundingBoxUtility.ToWkt(new BoundingBox { North = 53.6m, South = 53.0m, East = -1.52m, West = -2.14m }); Stopwatch watch = Stopwatch.StartNew(); using (IDocumentSession db = store.OpenSession()) { List <Record> results = db.Query <Record, RecordSpatialIndex>() .Customize(x => x.RelatesToShape(FieldNames.Spatial, peakDistrictBbox, SpatialRelation.Intersects)) .Where(i => i.Gemini.Title.StartsWith("GA")) //.Take(10) .ToList(); //results.Count().Should().Be(10); Console.WriteLine(results.Count); } Console.WriteLine(watch.ElapsedMilliseconds); }
public void load_gemini_records() { string dir = @"C:\Users\PETMON\Downloads\nbn-gemini2"; XNamespace gmd = "http://www.isotc211.org/2005/gmd"; var q = (from f in Directory.GetFiles(dir, "*.xml") where File.ReadLines(f).Any() let xml = XDocument.Load(f) let p = new { North = (decimal)xml.Descendants(gmd + "northBoundLatitude").Single(), South = (decimal)xml.Descendants(gmd + "southBoundLatitude").Single(), East = (decimal)xml.Descendants(gmd + "eastBoundLongitude").Single(), West = (decimal)xml.Descendants(gmd + "westBoundLongitude").Single(), } where p.North < 61 && p.South > 50 && p.East <2 && p.West> -12 // ignore bad data select new { File = Path.GetFileName(f), Wkt = BoundingBoxUtility.ToWkt(new BoundingBox { North = p.North, South = p.South, East = p.East, West = p.West, }) }) .ToList(); Console.WriteLine(q.Count()); q.ForEach(Console.WriteLine); IDocumentStore store = new DocumentStore { Url = RavenUrl }.Initialize(); using (IDocumentSession db = store.OpenSession()) { foreach (var x in q) { var item = new Record { Gemini = new Metadata { Title = x.File, }, Wkt = x.Wkt, }; db.Store(item); } db.SaveChanges(); } IndexCreation.CreateIndexes(typeof(Record).Assembly, store); }
private static void PerformDenormalizations(Record record) { // we store the bounding box as wkt so we can index it if (!BoundingBoxUtility.IsBlank(record.Gemini.BoundingBox)) { record.Wkt = BoundingBoxUtility.ToWkt(record.Gemini.BoundingBox); } }
void ValidateBoundingBox(Record record, ValidationResult <Record> result) { if (!BoundingBoxUtility.IsBlank(record.Gemini.BoundingBox)) { if (!BoundingBoxUtility.IsValid(record.Gemini.BoundingBox)) { result.Errors.Add("Invalid bounding box", r => r.Gemini.BoundingBox); } } }
public HttpResponseMessage AddOTBoundingBoxes() { var query = new RecordQueryInputModel { F = new FilterOptions { Keywords = new[] { "vocab.jncc.gov.uk/jncc-category/Overseas Territories" } }, P = 0, N = 1024, }; var records = _queryer.Query(query).ToList(); foreach (var record in records) { // note incorrect 's' in vocabs.jncc! var ots = record.Gemini.Keywords.Where(k => k.Vocab == "http://vocabs.jncc.gov.uk/overseas-territories").ToList(); if (ots.Any()) { var allBoxes = BoundingBoxes.Groups.Single(g => g.Name == "Overseas Territories").Boxes .Concat(new[] // currently don't have these so just use 0,0,0,0 { new KnownBoundingBox { Name = "Sovereign Base Areas Cyprus", Box = new BoundingBox() }, new KnownBoundingBox { Name = "British Antarctic Territory", Box = new BoundingBox() }, }); var boxes = ots.Select(ot => allBoxes.SingleOrDefault(b => b.Name == ot.Value)).ToList(); if (boxes.Any(b => b == null)) { throw new Exception("Some box couldn't be looked up for record " + record.Id); } var box = BoundingBoxUtility.MinimumOf(boxes.Select(b => b.Box)); record.Gemini.BoundingBox = box; } } db.SaveChanges(); return(new HttpResponseMessage()); }
public void should_store_bounding_box_as_wkt() { var database = Mock.Of <IDocumentSession>(); var service = new RecordService(database, ValidatorStub()); var e = Library.Example(); var record = new Record { Gemini = e, Footer = new Footer() }; service.Update(record, TestUser); string expectedWkt = BoundingBoxUtility.ToWkt(e.BoundingBox); Mock.Get(database).Verify(db => db.Store(It.Is((Record r) => r.Wkt == expectedWkt))); }
void PerformGeminiValidation(Record record, ValidationResult <Record> result) { // structured to match the gemini doc // 1 title is validated at basic level // 2 alternative title not used as optional // 3 Dataset language, conditional - data resource contains textual information // lets assume all data resources contain text // data_type is enum so can't be null, will default to eng // 4 abstract is mandatory if (record.Gemini.Abstract.IsBlank()) { result.Errors.Add("Abstract must be provided" + GeminiSuffix, r => r.Gemini.Abstract); } // 5 topic_category_must_not_be_blank if (record.Gemini.TopicCategory.IsBlank()) { result.Errors.Add(String.Format("Topic Category must be provided" + GeminiSuffix), r => r.Gemini.TopicCategory); } // 6 keywords mandatory if (record.Gemini.Keywords.Count == 0) { result.Errors.Add("Keywords must be provided" + GeminiSuffix, r => r.Gemini.Keywords); } // 7 temporal extent is mandatory - at least Begin must be provided if (record.Gemini.TemporalExtent.Begin.IsBlank()) { result.Errors.Add("Temporal Extent must be provided" + GeminiSuffix, r => r.Gemini.TemporalExtent.Begin); } // 8 DatasetReferenceDate mandatory if (record.Gemini.DatasetReferenceDate.IsBlank()) { result.Errors.Add("Dataset Reference Date must be provided" + GeminiSuffix, r => r.Gemini.DatasetReferenceDate); } // 10 Lineage is mandatory if (record.Gemini.Lineage.IsBlank()) { result.Errors.Add("Lineage must be provided" + GeminiSuffix, r => r.Gemini.Lineage); } // 15 extent is optional and not used // 16 Vertical extent information is optional and not used // 17 Spatial reference system is optional // 18 Spatial resolution, where it can be specified it should - so its optional // 19 resource location, conditional // when online access is availble, should be a valid url // when do not yet perform a get request and get a 200 response, the only true way to validate a url if (record.Gemini.ResourceLocator.IsNotBlank()) { Uri url; if (Uri.TryCreate(record.Gemini.ResourceLocator, UriKind.Absolute, out url)) { if (url.Scheme != Uri.UriSchemeHttp) { result.Errors.Add("Resource locator must be an http url", r => r.Gemini.ResourceLocator); } } else { result.Errors.Add("Resource locator must be a valid url", r => r.Gemini.ResourceLocator); } } // 21 DataFormat optional // 23 reponsible Organisation if (record.Gemini.ResponsibleOrganisation.Email.IsBlank()) { result.Errors.Add("Email address for responsible organisation must be provided" + GeminiSuffix, r => r.Gemini.ResponsibleOrganisation.Email); } if (record.Gemini.ResponsibleOrganisation.Name.IsBlank()) { result.Errors.Add("Name of responsible organisation must be provided" + GeminiSuffix, r => r.Gemini.ResponsibleOrganisation.Name); } if (record.Gemini.ResponsibleOrganisation.Role.IsBlank()) { result.Errors.Add("Role of responsible organisation must be provided" + GeminiSuffix, r => r.Gemini.ResponsibleOrganisation.Role); } // 24 frequency of update is optional // 25 limitations on publci access is mandatory if (record.Gemini.LimitationsOnPublicAccess.IsBlank()) { result.Errors.Add("Limitations On Public Access must be provided" + GeminiSuffix, r => r.Gemini.LimitationsOnPublicAccess); } // 26 use constraints are mandatory if (record.Gemini.UseConstraints.IsBlank()) { result.Errors.Add("Use Constraints must be provided (if there are none, leave as 'no conditions apply')", r => r.Gemini.UseConstraints); } // 27 Additional information source is optional // 30 metadatadate is mandatory if (record.Gemini.MetadataDate.Equals(DateTime.MinValue)) { result.Errors.Add("A metadata reference date must be provided" + GeminiSuffix, r => r.Gemini.MetadataDate); } // 33 Metadatalanguage // 35 Point of contacts // org name and email contact mandatory if (record.Gemini.MetadataPointOfContact.Email.IsBlank()) { result.Errors.Add("A metadata point of contact email address must be provided" + GeminiSuffix, r => r.Gemini.MetadataPointOfContact.Email); } if (record.Gemini.MetadataPointOfContact.Name.IsBlank()) { result.Errors.Add("A metadata point of contact organisation name must be provided" + GeminiSuffix, r => r.Gemini.MetadataPointOfContact.Name); } if (record.Gemini.MetadataPointOfContact.Role != "pointOfContact") { result.Errors.Add("The metadata point of contact role must be 'pointOfContact'" + GeminiSuffix, r => r.Gemini.MetadataPointOfContact.Name); } // 36 Unique resource identifier // 39 resource type is mandatory if (record.Gemini.ResourceType.IsBlank()) { result.Errors.Add("A resource type must be provided" + GeminiSuffix, r => r.Gemini.ResourceType); } // 40 Keywords from controlled vocabularys must be defined, they cannot be added. //ValidateControlledKeywords(record, recordValidationResult<Record>); // Conformity, required if claiming conformity to INSPIRE // not yet implemented // Equivalent scale, optional // we're going to try to squash gemini and non-geographic iso metadata together in the same validation if (record.Gemini.ResourceType != "nonGeographicDataset") { // BoundingBox // mandatory // valid todo if (BoundingBoxUtility.IsBlank(record.Gemini.BoundingBox)) { result.Errors.Add("A bounding box must be supplied", r => r.Gemini.BoundingBox); } } }