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); } } }
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); } } }