public XElement Process(Stream stream, int regulatorCode) { Regulator contextRegulator = Repository.Regulators.GetByEDTIdentityKey(regulatorCode); if (contextRegulator == null) { throw new ArgumentException("RegulatorCode does not contain a valid number.", "regulatorCode"); } //Connect the regulator after we verified it exists. TransactionScope.Connect(contextRegulator); //this endpoint supports multiple versions of the schema simultaneously. IXmlSchemaMetadata inputSchemaMetadata = null; IXmlSchemaMetadata outputSchemaMetadata = null; string version = null; RegulatorFacilityCreateResponseXmlSerializer responseSerializer = new RegulatorFacilityCreateResponseXmlSerializer(Repository); //lets default to Trial mode in case the XML is so messed up we can't parse it, and this is obviously less danagerous than //a Commit. RegulatorFacilityCreateMode mode = RegulatorFacilityCreateMode.Trial; //declare the package to be use to inflate the XML. RegulatorXmlObjectPacket <RegulatorFacilityCreateMode, FacilityCreatePackage> package = null; XmlSchemaValidationResult schemaValidationResult = null; var rfcXml = ConvertStreamToXDocument(stream); if (rfcXml != null) { string xml = rfcXml.ToString(); TransactionScope.SaveXml(xml, EDTTransactionXmlDirection.Inbound); TransactionScope.WriteActivity("XML Document is validating..."); //get the root element of the doc (should be named RegulatorFacilityCreate). var rootElement = rfcXml.Root; //try and obtain the targetNamespace var targetNamespace = rootElement.GetDefaultNamespace(); if (string.IsNullOrWhiteSpace(targetNamespace.NamespaceName)) { //couldn't obtain the schema we need because the root node didn't have a default non-prefixed xmlns attribute. //lets see of the document is using prefixes and look for the xmlns:cers="" attribute. targetNamespace = rootElement.GetNamespaceOfPrefix("cers"); } //if we have no targetNamespace then we should not proceed any further. if (targetNamespace == null || targetNamespace.NamespaceName == string.Empty) { TransactionScope.WriteMessage("Unable to resolve the targetNamespace of the received XML data.", EDTTransactionMessageType.Error); throw new Exception("Unable to resolve the targetNamespace of the received XML data."); } //find the metadata for the RegulatorFacilityCreate schema with the specified targetNamespace. inputSchemaMetadata = XmlSchemas.GetSchemaMetdataForNamespace(XmlSchema.RegulatorFacilityCreate, targetNamespace); //XmlSchemas.GetSchemaMetadata( XmlSchema.RegulatorFacilityCreate, version ); if (inputSchemaMetadata == null) { TransactionScope.WriteMessage("Unable to find a RegulatorFacilityCreate schema with the specified namespace: " + targetNamespace.NamespaceName, EDTTransactionMessageType.Error); throw new Exception("Unable to find a RegulatorFacilityCreate schema with the specified version: " + version); } //the outgoing schema version is dependant on the version specified in the input schema. //so parse the version and then look for the appropriate output (response schema). version = targetNamespace.ExtractVersion(); //now try and find the response schema with the version parsed from the targetSchema. outputSchemaMetadata = XmlSchemas.GetSchemaMetadata(XmlSchema.RegulatorFacilityCreateResponse, version); if (outputSchemaMetadata == null) { TransactionScope.WriteMessage("Unable to find a RegulatorFacilityCreateResponse schema with the specified version: " + version, EDTTransactionMessageType.Error); throw new Exception("Unable to find a RegulatorFacilityCreateResponse schema with the specified version: " + version); } schemaValidationResult = xml.IsValidAgainstSchema(inputSchemaMetadata); if (!schemaValidationResult.IsValid) { //make a new package so we have a storage area for the errors to be shipped back in the response xml. package = new RegulatorXmlObjectPacket <RegulatorFacilityCreateMode, FacilityCreatePackage>(); //package is invalid due to schema validation errors, update the transaction status, and write some diagnostic information. //Merge in the schema validation error messages and associate them with the transaction. TransactionScope.WriteActivity("XML Document is not valid against the schema."); package.Packet.Workspace.Messages.Add("XML Document is not valid against the schema.", FacilityOperationMessageType.Error); foreach (var error in schemaValidationResult.Errors) { TransactionScope.WriteMessage("Schema Validation Error: " + error, EDTTransactionMessageType.Error); package.Packet.Workspace.Messages.Add("Schema Validation Error: " + error, FacilityOperationMessageType.Error); } TransactionScope.WriteMessage("XML document does not validate against the schema.", EDTTransactionMessageType.Error); TransactionScope.Complete(EDTTransactionStatus.Rejected); } else { TransactionScope.WriteActivity("XML Document is valid against the schema."); //deserialize the data into the object structure. RegulatorFacilityCreateXmlSerializer serializer = new RegulatorFacilityCreateXmlSerializer(Repository); package = serializer.Deserialize(rfcXml); package.Packet.Version = version; //add in the version 4/1/2014. mode = package.Mode; // error if DataCollectionDate is less than 1970 and greater than today at 11:59 if (package.Packet.CERSPoint != null && package.Packet.CERSPoint.DataCollectionDate != null && (package.Packet.CERSPoint.DataCollectionDate < new DateTime(1970, 1, 1) || package.Packet.CERSPoint.DataCollectionDate > DateTime.Now.AddDays(1).AddTicks(-1))) { package.Packet.Workspace.Messages.Add("DataCollectionDate is out of range.", FacilityOperationMessageType.Error); } if (!package.Packet.HasErrors()) { ServiceManager.Facilities.Create(package.Packet, regulatorCode, mode, true); if (mode == RegulatorFacilityCreateMode.Commit && package.Packet.Workspace.FacilityCreated) { TransactionScope.Connect(package.Packet.Workspace.Facility); } } //if the package had errors, set rejected, otherwise set accepted. if (package.Packet.HasErrors()) { TransactionScope.Complete(EDTTransactionStatus.Rejected); } else { TransactionScope.Complete(EDTTransactionStatus.Accepted); } } } //prepare our output response XML. XElement responseXml = responseSerializer.PreparePackage(TransactionScope.Transaction, outputSchemaMetadata); responseSerializer.AddTransaction(responseXml, TransactionScope.Transaction, mode); //we should always have a package (unless schema validation failed). if (package != null) { //add the result hive to the root node if we created a facility (or virtually did in trial mode) responseSerializer.AddResult(responseXml, package.Packet, mode); //if using the 1/06 schema version... if (!string.IsNullOrWhiteSpace(package.Packet.Version) && (package.Packet.Version.IndexOf("1/06") > -1)) { responseSerializer.AddPotentialDuplicates(responseXml, package.Packet); } } //add the messages generated during the process. responseSerializer.AddMessages(responseXml, package.Packet); TransactionScope.SaveXml(responseXml, EDTTransactionXmlDirection.Outbound); return(responseXml); }
/// <summary> /// Performs the main work of the CMESubmittalEDTProcessor. Accepts an XDocument /// conforming to the CMESubmittal XML Schema Definition, and returns an XElement /// conforming to the CMESubmittalResponse XML Schema Definition. /// </summary> /// <param name="xDocument"></param> /// <returns></returns> public XElement Process(XDocument xDocument) { TransactionScope.SaveXml(xDocument, EDTTransactionXmlDirection.Inbound); XElement cmeSubmittalResponse = null; // Set up CMESubmittal XML Deserializer and initialize CMEPackage CMESubmittalXmlDeserializer cmeSubmittalXmlDeserializer = new CMESubmittalXmlDeserializer(Repository); CMEPackage cmePackage = new CMEPackage(); // Retrieve CME Submittal Schema Definition IXmlSchemaMetadata schema = XmlSchemas.GetSchemaMetadata(XmlSchema.RegulatorCMESubmit); cmePackage.IsValidXMLAgainstSchema = false; // Default to false, until validation proves otherwise cmeSubmittalXmlDeserializer.InitializeCMEPackage(cmePackage, accountID: Repository.ContextAccountID, edtTransaction: TransactionScope.Transaction, xDocument: xDocument); if (xDocument == null) { var entityGuidanceMessage = EntityGuidanceMessage.Create(GuidanceMessageCode.XMLSchemaValidationError, null, null, GuidanceLevel.Required, null, "XML Document Not Found"); cmePackage.GuidanceMessages.Add(entityGuidanceMessage.ToGuidanceMessage()); } else { // Validate XDocument: var validationGuidance = xDocument.ValidateCMESubmittal(schema); cmePackage.GuidanceMessages.AddRange(validationGuidance); } // Set CME Package's "IsValidAgainstXMLSchema" bool based on return Guidance Messages cmePackage.IsValidXMLAgainstSchema = !cmePackage.GuidanceMessages.Any(gm => gm.LevelID == (int)GuidanceLevel.Required && !gm.Voided); // If serialized document is valid, proceed with Deserializing and Validating the individual CME Entities: if (cmePackage.IsValidXMLAgainstSchema) { cmePackage = cmeSubmittalXmlDeserializer.DeserializeCMESubmittalPackage(xDocument, cmePackage, Repository.ContextAccountID, schema: schema); // Call PreSave Methods for all CME Entities (Insp, Vio, Enf, EnfVio): cmeSubmittalXmlDeserializer.CallPreSaveMethods(cmePackage, Repository); var permissionRoleMatrixCollection = ServiceManager.Security.GetRolesForAccount(Repository.ContextAccount); // Perform Standard Validation on the CMEPackage: cmePackage.Validate(Repository, callerContext: TransactionScope.CallerContext, permissions: permissionRoleMatrixCollection); } // Determine a list of Regulator IDs for the affected CME Data Entities: List <int> regulatorIDList = GenerateDistinctAffectedRegulatorIDs(cmePackage); // If CME Package is NOT valid (meaning one or more Required Guidance Messages were created, // we need to remove the CME Entities from the model: if (!cmePackage.IsValid) { cmeSubmittalXmlDeserializer.DetachEntitiesFromTransaction(cmePackage, Repository); } // Update GuidanceMessage Common fields, and link all to EDTTransaction Entity cmePackage.GuidanceMessages.SetCommonFields(Repository.ContextAccountID, creating: true); foreach (var gm in cmePackage.GuidanceMessages) { gm.EDTTransaction = cmePackage.EDTTransaction; } // Populate EDT Transaction Messages PopulateEDTTranactionMessages(cmePackage); PopulateCMEBatchMetaData(cmePackage); // Persist the changes to the DB by calling Complete on the EDTTransactionScope if (cmePackage.IsValid) { TransactionScope.Complete(EDTTransactionStatus.Accepted); } else { TransactionScope.Complete(EDTTransactionStatus.Rejected); } // Populate RegulatorEDTTransactions Based Upon CMEBatch CME Data Entities GenerateRegulatorEDTTransactions(regulatorIDList); // Retrieve the EDT Transaction Key: Guid edtTransactionKey = cmePackage.EDTTransaction.Key; // Build a CMEPackage Object from an EDT Transaction Key CMEPackage cmePackageResponse = EDTTransactionToCMEPackage.BuildCMEPackageFromEDTTransaction(Repository, edtTransactionKey: edtTransactionKey); // Generate a CMESubmittalResponse from an EDT Transaction Key CMESubmittalResponseXmlSerializer cmeSubmittalResponseXmlSerializer = new CMESubmittalResponseXmlSerializer(Repository); cmeSubmittalResponse = cmeSubmittalResponseXmlSerializer.GenerateCMESubmittalResponsePackage(cmePackageResponse); TransactionScope.SaveXml(cmeSubmittalResponse, EDTTransactionXmlDirection.Outbound); return(cmeSubmittalResponse); }