updated article (Oct 2011)
(code refactored)
Hi All,
One other missing feature of MDS is Import / Export / Copy Business rules from a model to another (or copy business rules to the same model)
my code is still in beta, but it is already (partially) working.
you can find it on my “MDS Manager” tool on codeplex:
http://mdsmanager.codeplex.com
Get business rules from modelId, quite easy with service client method “business rules get”, returns a business rule set
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public BusinessRules GetBusinessRules(string fileName) { BusinessRules brs = null; Stream str = null; try { if (File.Exists(fileName)) { str = new FileStream(@fileName, FileMode.Open, FileAccess.Read, FileShare.Read); if (str == null) { throw new BusinessRulesException("error while opening file!"); } XmlSerializer xs = new XmlSerializer(typeof(BusinessRules)); // Load the object saved above by using the Deserialize function brs = (BusinessRules)xs.Deserialize(str); } else { throw new BusinessRulesException("Cannot find specified file!"); } return brs; } catch (Exception ex) { throw ex; } finally { // Cleanup if (str != null) str.Close(); } } |
1 |
then we export business rules to a XML file |
1 |
note: |
1 |
//this is needed to avoid a serialization error (more info on <a title="http://www.johnsoer.com/blog/?p=125" href="http://www.johnsoer.com/blog/?p=125" target="_blank">http://www.johnsoer.com/blog/?p=125</a> ) : |
1 2 |
//XmlSerializer xs = new XmlSerializer(typeof(BusinessRules), new Type[] { typeof(BRAttributeValueArgument),typeof(BRBlankArgument) // ,typeof(BRDomainBasedAttributeArgument)}); |
1 |
here is the export method : |
1 2 3 4 5 |
public void ExportBusinessRules(string exportFileName, BusinessRules brs) { TextWriter WriteFileStream = null; try { |
//new type needed to avoir error because serialization of an inherited class XmlSerializer xs = new XmlSerializer(typeof(BusinessRules), new Type[] { typeof(Common.ServiceReference1.BRAttributeValueArgument) });
//update oct 2011!
//new type needed to avoir error because serialization of an inherited class
1 2 |
XmlSerializer xs = new XmlSerializer(typeof(BusinessRules), new Type[] { typeof(BRAttributeValueArgument),typeof(BRBlankArgument) ,typeof(BRDomainBasedAttributeArgument)}); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Create a new file stream to write the serialized object to a file WriteFileStream = new StreamWriter(@exportFileName); xs.Serialize(WriteFileStream, brs); //custom exception class , but not required throw new BusinessRulesException("Business Rules successfully exported to file " + exportFileName); } catch (Exception exc) { throw exc; } finally { // Cleanup if (WriteFileStream != null) WriteFileStream.Close(); } } |
1 |
1 |
then we would like to import this XML file to another model: |
1 |
here is the method to get business rules set from a previously exported XML file : |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public BusinessRules GetBusinessRules(string fileName) { BusinessRules brs = null; Stream str = null; try { if (File.Exists(fileName)) { str = new FileStream(@fileName, FileMode.Open, FileAccess.Read, FileShare.Read); if (str == null) { throw new BusinessRulesException("error while opening file!"); } XmlSerializer xs = new XmlSerializer(typeof(BusinessRules)); // Load the object saved above by using the Deserialize function brs = (BusinessRules)xs.Deserialize(str); } else { throw new BusinessRulesException("Cannot find specified file!"); } return brs; } catch (Exception ex) { throw ex; } finally { // Cleanup if (str != null) str.Close(); } } |
1 |
1 |
<span style="color: #339966;">//then we can get the source modelID</span> |
1 |
sourceModelId =brs.BusinessRulesMember.First().Identifier.ModelId as Identifier; |
1 |
<span style="color: #339966;">// and then clone business rule set with updated modelId:</span> |
1 |
<span style="color: #339966;">//brs is the business rule set</span> |
1 |
<span style="color: #339966;">//sourceModelId is the source Model Identifier (taken above from the Rules set from the XML file)</span> |
1 |
<span style="color: #339966;">//target ModelId is the model Identifier for the model we want to import back the B. rules to</span> |
1 |
CloneBusinessRules(brs,sourceModelId, targetModelId)); |
1 |
Here is the CloneBusinessRules Method: |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
public string CloneBusinessRules(BusinessRules brs, Identifier SourceModelId, Identifier targetModelId) { OperationResult or = null; //instanciate new BR members try { int cptMissingEntity = 0; StringBuilder sb = new StringBuilder("these business rule related entities does not exists in target model:"); sb.AppendLine(); BusinessRules newBRS = new BusinessRules(); foreach (BusinessRule br in brs.BusinessRulesMember) { Identifier EntityId = null; //this is used to get the target entity Id with matching its name using (ServiceClient c = new ServiceClientWrapper().CreateServiceClient()) { EntityId = GetEntityIdFromName(c, c.Endpoint.Address.Uri.OriginalString, targetModelId, br.Identifier.EntityId.Name); } if (EntityId != null) { newBRS.BusinessRulesMember = new Collection<BusinessRule>(); //create a new business rule based on the source one, and applying on it the target identifiers and names BusinessRule newBR = BusinessRuleInstanciate(Guid.NewGuid(), br.Identifier.Name, targetModelId.Name, br.Identifier.EntityId.Name, br.Identifier.MemberType, br.Priority, br.BRActions, br.Identifier.InternalId, br.RuleActionText, br.RuleConditionText); //some required parameters to instanciate below: //instanciate BRActions newBRS.BRActions = BRActionsInstanciate(brs.BRActions, newBR.Identifier); //instanciate BRConditions newBRS.BRConditions = BRConditionsInstanciate(brs.BRConditions, newBR.Identifier); //instanciate BRConditionTreeNodes newBRS.BRConditionTreeNodes = BRConditionTreeNodesInstanciate(brs.BRConditionTreeNodes, newBR.Identifier); newBRS.BusinessRulesMember.Add(newBR); } else { sb.AppendLine(br.Identifier.EntityId.Name); cptMissingEntity++; //these business rule related entities do not exist in target model } //then we clone modified BRSet using (ServiceClient c = new ServiceClientWrapper().CreateServiceClient()) { or = c.BusinessRulesClone(new International(), newBRS); string err = Tools.HandleErrors(or); if (!string.IsNullOrEmpty(err)) { throw new Exception(err); } } if (cptMissingEntity == 0) { sb = new StringBuilder(); } } return sb.ToString(); } catch (Exception exc) { throw exc; } } |
update oct 2011 code for BRActionsInstanciate, BRConditionsInstanciate,BRConditionTreeNodesInstanciate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
private Collection<BRConditionTreeNode> BRConditionTreeNodesInstanciate(Collection<BRConditionTreeNode> BRConditionTreeNodes, MemberTypeContextIdentifier BRId) { try { //Add BRConditionTreeNode to BRConditionTreeNode Collection Collection<BRConditionTreeNode> newBRConditionTreeNodes = new Collection<BRConditionTreeNode>(); foreach (BRConditionTreeNode brctn in BRConditionTreeNodes) { BRConditionTreeNode BRConditionTreeNodeItem = new BRConditionTreeNode(); //Add Attribute and Action type to the collection BRConditionTreeNodeItem.BRConditions = BRConditionsInstanciate(brctn.BRConditions, BRId); BRConditionTreeNodeItem.BusinessRuleId = BRId; BRConditionTreeNodeItem.ConditionTreeChildNodes = brctn.ConditionTreeChildNodes; BRConditionTreeNodeItem.ConditionTreeParentNode = brctn.ConditionTreeParentNode; BRConditionTreeNodeItem.LogicalOperator = brctn.LogicalOperator; BRConditionTreeNodeItem.Identifier = new Identifier() { Name = brctn.Identifier.Name, Id = Guid.NewGuid() }; //All Action and Condition Items must have a sequence greater that zero BRConditionTreeNodeItem.Sequence = brctn.Sequence; newBRConditionTreeNodes.Add(BRConditionTreeNodeItem); } return newBRConditionTreeNodes; } catch (Exception exc) { throw exc; } } private Collection<BRAction> BRActionsInstanciate(Collection<BRAction> BRActions, MemberTypeContextIdentifier BRId) { try { //Add Action to Action Collection Collection<BRAction> newBRActions = new Collection<BRAction>(); foreach (BRAction bra in BRActions) { BRAction BRActionItem = new BRAction() { Identifier = new Identifier() { Id = Guid.NewGuid(), Name = bra.Identifier.Name }, BusinessRuleId = BRId }; //Add Attribute and Action type to the collection BRActionItem.PrefixArgument = new BRAttributeArgument(); BRActionItem.PrefixArgument.PropertyName = bra.PrefixArgument.PropertyName; BRActionItem.PrefixArgument.AttributeId = new Identifier(); BRActionItem.PrefixArgument.AttributeId.Id = Guid.NewGuid(); BRActionItem.PrefixArgument.AttributeId.Name = bra.PrefixArgument.AttributeId.Name; BRActionItem.Operator = bra.Operator; var colBRffa = new Collection<object>(); foreach (var brffa in bra.PostfixArguments) { BRBlankArgument BRba = brffa as BRBlankArgument; BRFreeformArgument BRffa = brffa as BRFreeformArgument; if (BRba != null) { colBRffa.Add(new BRBlankArgument() { Identifier = new Identifier() { Id = Guid.NewGuid(), Name = BRba.Identifier.Name }, PropertyName = BRba.PropertyName }); } else { if (BRffa != null) { colBRffa.Add(new BRFreeformArgument() { Identifier = new Identifier() { Id = Guid.NewGuid(), Name = BRffa.Identifier.Name }, Value = BRffa.Value, PropertyName = BRffa.PropertyName }); } } } BRActionItem.PostfixArguments = colBRffa; BRActionItem.Text = bra.Text; //All Action and Condition Items must have a sequence greater that zero BRActionItem.Sequence = bra.Sequence; newBRActions.Add(BRActionItem); } return newBRActions; } catch (Exception exc) { throw exc; } } public Collection<BRCondition> BRConditionsInstanciate(Collection<BRCondition> BRconditions, MemberTypeContextIdentifier BRId) { try { //Add Action to Action Collection Collection<BRCondition> newBRconditions = new Collection<BRCondition>(); BRCondition BRConditionItem = new BRCondition(); foreach (BRCondition brc in BRconditions) { //Add Attribute and Action type to the collection BRConditionItem.BusinessRuleId = BRId; BRConditionItem.ConditionTreeNodeId = new Identifier() { Name = brc.ConditionTreeNodeId.Name }; BRConditionItem.Identifier = new Identifier() { Id = Guid.NewGuid(), Name = brc.Identifier.Name }; BRConditionItem.Operator = brc.Operator; BRConditionItem.PrefixArgument = brc.PrefixArgument; BRConditionItem.PostfixArguments = brc.PostfixArguments; //All Action and Condition Items must have a sequence greater that zero BRConditionItem.Sequence = brc.Sequence; BRConditionItem.Text = brc.Text; newBRconditions.Add(BRConditionItem); } return newBRconditions; } catch (Exception exc) { throw exc; } } |