public XDocument GetSchematronSchema([NotNull] TranslationSettings translationSettings) { XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", null)); XElement schSchema = doc.SchematronSchema(); XComment comment = new XComment(string.Format(" Generated by eXolutio on {0} {1} from {2}/{3}. ", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), PSMSchema.Project.Name, PSMSchema.Caption)); schSchema.Add(comment); Dictionary <PSMClass, List <PatternInfo> > patterns = new Dictionary <PSMClass, List <PatternInfo> >(); foreach (OCLScript oclScript in PSMSchema.OCLScripts) { // creates patterns, some patterns will be declared abstract TranslateScript(schSchema, oclScript, translationSettings, ref patterns); } #region create instance patterns foreach (PSMClass contextClass in PSMSchema.PSMClasses) { foreach (PSMClass ancestorClass in ModelIterator.GetGeneralizationsWithSelf(contextClass)) { if (patterns.ContainsKey(ancestorClass) && (ancestorClass != contextClass || ancestorClass.GeneralizationsAsGeneral.Count > 0)) { foreach (PatternInfo pattern in patterns[ancestorClass]) { if (ancestorClass != contextClass) { schSchema.Add(new XComment(string.Format("instance pattern for {0}'s ancestor {1}", contextClass, ancestorClass.Name))); } else { schSchema.Add(new XComment(string.Format("instance pattern for {0}", contextClass))); } XElement instancePattern = schSchema.SchematronPattern(); string instancePatternId = string.Format("{0}-as-{1}", contextClass.Name, pattern.PatternName); instancePattern.AddAttributeWithValue("id", instancePatternId); instancePattern.AddAttributeWithValue("is-a", pattern.PatternName); instancePattern.SchematronParam(pattern.ContextVariableName, contextClass.GetXPathFull(false).ToString()); } } } } #endregion PostprocessLogMessages(); return(doc); }
private void TranslateScript(XElement schSchema, OCLScript oclScript, TranslationSettings translationSettings, ref Dictionary <PSMClass, List <PatternInfo> > patterns) { OclCompilerResult compilerResult = oclScript.CompileToAst(); compilerResult.CompileExpressionsInMessages(); if (!compilerResult.Errors.HasError) { XComment comment = new XComment(string.Format("Below follow constraints from OCL script '{0}'. ", oclScript.Name)); schSchema.Add(comment); foreach (ClassifierConstraintBlock classifierConstraintBlock in compilerResult.Constraints.ClassifierConstraintBlocks) { PSMClass contextClass = (PSMClass)classifierConstraintBlock.Context.Tag; patterns.CreateSubCollectionIfNeeded(contextClass); string patternName = NameSuggestor <PatternInfo> .SuggestUniqueName(patterns[contextClass], contextClass.Name, p => p.PatternName, true, false); PatternInfo patternInfo = new PatternInfo { PatternName = patternName }; XElement patternElement = schSchema.SchematronPattern(patternInfo.PatternName); patterns[contextClass].Add(patternInfo); bool abstractPattern = !contextClass.GeneralizationsAsGeneral.IsEmpty(); if (abstractPattern) { patternElement.AddAttributeWithValue("abstract", "true"); } string context = !abstractPattern?contextClass.GetXPathFull(true).ToString() : "$" + classifierConstraintBlock.Self.Name; XElement ruleElement = patternElement.SchematronRule(context); patternInfo.ContextVariableName = classifierConstraintBlock.Self.Name; if (!abstractPattern) { ruleElement.SchematronLet(patternInfo.ContextVariableName, @"."); } TranslateInvariantsToXPath(classifierConstraintBlock, ruleElement, (PSMBridge)compilerResult.Bridge, translationSettings); } } else { XComment comment = new XComment(string.Format("OCL script '{0}' contains errors and thus can not be translated. ", oclScript.Name)); schSchema.Add(comment); } }
private string TranslateInvariantToXPath(ClassifierConstraintBlock constraintBlock, IBridgeToOCL bridge, OclExpression invariant, TranslationSettings translationSettings, bool forceTranslation = false) { invariant.IsInvariant = true; invariant.ConstraintContext = constraintBlock; PSMOCLtoXPathConverter xpathConverter; if (translationSettings.Functional) { xpathConverter = new PSMOCLtoXPathConverterFunctional(); } else { xpathConverter = new PSMOCLtoXPathConverterDynamic(); } xpathConverter.Bridge = (PSMBridge)bridge; xpathConverter.OclContext = constraintBlock; xpathConverter.Log = Log; xpathConverter.Settings = translationSettings; if (forceTranslation || !translationSettings.Retranslation) { try { string invariantStr = xpathConverter.TranslateExpression(invariant); translationSettings.SubexpressionTranslations.XPathContextVariableReplacementMode = xpathConverter.ContextVariableReplacementMode; translationSettings.SubexpressionTranslations.Merge(xpathConverter.SubexpressionTranslations); return(invariantStr); } catch (ExpressionNotSupportedInXPath e) { Log.AddError(e.Message, e.Expression); } catch { Log.AddError("Unable to translate invariant. ", invariant); } } else { try { // this must stay here because of the string comparison - translation renames some variables xpathConverter.TranslateExpression(invariant); foreach (OclExpression translatedExp in translationSettings.SubexpressionTranslations.Translations.Keys) { if (translatedExp.ToString() == invariant.ToString()) { translationSettings.SubexpressionTranslations.SelfVariableDeclaration = translatedExp.ConstraintContext.Self; return(translationSettings.SubexpressionTranslations.GetSubexpressionTranslation(translatedExp).GetString(true)); } } } catch (ExpressionNotSupportedInXPath e) { Log.AddError(e.Message, e.Expression); } catch { Log.AddError("Unable to translate invariant. ", invariant); } } return("### ERROR"); }
private void TranslateInvariantsToXPath(ClassifierConstraintBlock constraintBlock, XElement ruleElement, PSMBridge psmBridge, TranslationSettings translationSettings) { foreach (InvariantWithMessage invariant in constraintBlock.Invariants) { string xpath = TranslateInvariantToXPath(constraintBlock, psmBridge, invariant.Constraint, translationSettings); try { ruleElement.Add(new XComment(invariant.ToString())); XElement assertElement = ruleElement.SchematronAssert(xpath); #region process user error message and subexpressions in the message if (invariant.MessageIsString) { if (invariant.MessageSubExpressions.Count > 0) { foreach (SubExpressionInfo messagePart in invariant.MessageSubExpressions) { if (messagePart.SubExpression == null) { XText messageTextElement = new XText(messagePart.PartAsString); assertElement.Add(messageTextElement); } else { if (messagePart.Parsed) { string subExpressionTranslation = TranslateInvariantToXPath(constraintBlock, psmBridge, messagePart.SubExpression, translationSettings, true); assertElement.SchematronValueOf(subExpressionTranslation); } else { Log.AddWarning(string.Format("Failed to integrate subexpression `{0}` into the schema. ", messagePart.PartAsString), messagePart.SubExpression); } } } } else { XText messageTextElement = new XText(((StringLiteralExp)invariant.Message).Value); assertElement.Add(messageTextElement); } } #endregion } catch { ruleElement.Add(new XComment("Translation of the constraint failed. ")); } } }