internal static IEnumerable <RuleFeedbackBase> CheckProblemOutput(MgaFCO child) { var result = new List <RuleFeedbackBase>(); var incomingConnections = child.PartOfConns.Cast <IMgaConnPoint>().Where(cp => cp.ConnRole == "dst").Select(cp => cp.Owner) .Cast <IMgaSimpleConnection>(); if (incomingConnections.Count() != 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = incomingConnections.Count() == 0 ? "ProblemOutput must have one incoming connection" : "ProblemOutput may not have more than one incoming connection" }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } if (isValidParamOrOutputName(child.Name) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Problem Output ({0}) has an invalid name. " + NAME_EXPLANATION, (object)child.Name) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } return(result); }
public static IEnumerable<RuleFeedbackBase> OneAndOnlyOneDriver(MgaFCO context) { var result = new List<RuleFeedbackBase>(); var pet = CyPhyClasses.ParametricExploration.Cast(context); var cnt = pet.Children.ParameterStudyCollection.Count() + pet.Children.PCCDriverCollection.Count() + pet.Children.OptimizerCollection.Count(); if (cnt < 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("No driver defined, please add either a PCCDriver, Parameter Study or Optimizer.") }; result.Add(feedback); } else if (cnt > 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The ParameterExploration-model has {0} drivers. There must only be one.", cnt) }; result.Add(feedback); } return result; }
public static IEnumerable<RuleFeedbackBase> CheckRule(MgaFCO context) { var result = new List<RuleFeedbackBase>(); CyPhyML.Component cyPhyMLComponent = ISIS.GME.Common.Utils.CreateObject<CyPhyMLClasses.Component>(context as MgaObject); Dictionary<string, List<CyPhyML.HasDescriptionAndGUID>> namePPMListMap = new Dictionary<string, List<CyPhyML.HasDescriptionAndGUID> >(); List<object> objectList = cyPhyMLComponent.AllChildren.ToList<object>(); foreach( CyPhyML.HasDescriptionAndGUID cyPhyMLHasDescriptionAndGUID in cyPhyMLComponent.AllChildren. Where(x => x.GetType().UnderlyingSystemType == typeof(CyPhyMLClasses.Parameter) || x.GetType().UnderlyingSystemType == typeof(CyPhyMLClasses.Property) || x.GetType().UnderlyingSystemType == typeof(CyPhyMLClasses.Metric)) ) { Type type = cyPhyMLHasDescriptionAndGUID.GetType(); string name = cyPhyMLHasDescriptionAndGUID.Name; if (!namePPMListMap.ContainsKey(name)) { namePPMListMap[name] = new List<CyPhyML.HasDescriptionAndGUID>(); } namePPMListMap[name].Add(cyPhyMLHasDescriptionAndGUID); } foreach (string name in namePPMListMap.Keys) { List<CyPhyML.HasDescriptionAndGUID> ppmList = namePPMListMap[name]; if (ppmList.Count > 1) { var genericRuleFeedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = "Name \"" + name + "\" not unique between Parameter, Property, and Metric children of Component \"" + cyPhyMLComponent.Name + "\"" }; result.Add(genericRuleFeedback); } } return result; }
public static IEnumerable<RuleFeedbackBase> CheckTLSUT(MgaFCO context) { var result = new List<RuleFeedbackBase>(); var tsults = context.ChildObjects.OfType<MgaReference>().Where(x => x.Meta.Name == "TopLevelSystemUnderTest"); var count = tsults.Count(); if (count == 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = "There is no top level system under test object." }; result.Add(feedback); } else if (count == 1) { var referred = tsults.FirstOrDefault().Referred; if (referred == null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = "Top level system under test reference cannot be null." }; result.Add(feedback); } else if (referred.Meta.Name != "DesignContainer") { var feedback = new GenericRuleFeedback { FeedbackType = FeedbackTypes.Warning, Message = "Top level system under test reference MUST point to a Design Container." }; result.Add(feedback); } } else { var feedback = new GenericRuleFeedback { FeedbackType = FeedbackTypes.Error, Message = "There is more than one top level system under test object." }; result.Add(feedback); } return result; }
private static IEnumerable <RuleFeedbackBase> checkPccOutputAttributes(CyPhy.PCCOutput output) { var attributeCheckResults = new List <RuleFeedbackBase>(); double maxValue = 0; double minValue = 0; double pccTarget = output.Attributes.TargetPCCValue; bool compareValues = double.TryParse(output.Attributes.MaxValue.Trim(), out maxValue) && double.TryParse(output.Attributes.MinValue.Trim(), out minValue); bool pccTargetValid = (0 <= pccTarget) && (pccTarget <= 1); if (compareValues) { if (minValue > maxValue) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC Output ({0}) MaxValue must be greater than MinValue", output.Name) }; feedback.InvolvedObjectsByRole.Add(output.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC Output ({0}): Could not parse MinValue and/or MaxValue; please make sure both Attributes have decimal values.", output.Name) }; feedback.InvolvedObjectsByRole.Add(output.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } if (!pccTargetValid) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC Output ({0}) TargetPCCValue must be within [0, 1]", output.Name) }; feedback.InvolvedObjectsByRole.Add(output.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } return(attributeCheckResults); }
public static IEnumerable <RuleFeedbackBase> CheckTLSUT(MgaFCO context) { var result = new List <RuleFeedbackBase>(); var tsults = context.ChildObjects.OfType <MgaReference>().Where(x => x.Meta.Name == "TopLevelSystemUnderTest"); var count = tsults.Count(); if (count == 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = "There is no top level system under test object." }; result.Add(feedback); } else if (count == 1) { var referred = tsults.FirstOrDefault().Referred; if (referred == null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = "Top level system under test reference cannot be null." }; result.Add(feedback); } else if (referred.Meta.Name != "DesignContainer") { var feedback = new GenericRuleFeedback { FeedbackType = FeedbackTypes.Warning, Message = "Top level system under test reference MUST point to a Design Container." }; result.Add(feedback); } } else { var feedback = new GenericRuleFeedback { FeedbackType = FeedbackTypes.Error, Message = "There is more than one top level system under test object." }; result.Add(feedback); } return(result); }
internal static IEnumerable <RuleFeedbackBase> CheckProblemInput(MgaFCO child) { var result = new List <RuleFeedbackBase>(); var incomingConnections = Enumerable.Cast <IMgaConnPoint>(child.PartOfConns).Where(cp => cp.ConnRole == "dst").Select(cp => cp.Owner) .Cast <IMgaSimpleConnection>(); if (incomingConnections.Where(conn => conn.ParentModel.ID == child.ParentModel.ID).Count() > 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("ProblemInput may have only one incoming connection at the same level of hierarchy") }; feedback.InvolvedObjectsByRole.Add((IMgaFCO)child); result.Add(feedback); } if (incomingConnections.Where(conn => conn.ParentModel.ID != child.ParentModel.ID).Count() > 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("ProblemInput may have only one incoming connection from the parent ParametricExploration") }; feedback.InvolvedObjectsByRole.Add((IMgaFCO)child); result.Add(feedback); } if (incomingConnections.Where(conn => conn.ParentModel.ID == child.ParentModel.ID).Count() == 1 && incomingConnections.Where(conn => conn.ParentModel.ID == child.ParentModel.ID).First().Src.Meta.Name != typeof(CyPhy.DesignVariable).Name && incomingConnections.Where(conn => conn.ParentModel.ID != child.ParentModel.ID).Count() == 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("ProblemInput must be connected to a Design Variable") // TODO: if it is connected one hierarchy level up }; feedback.InvolvedObjectsByRole.Add((IMgaFCO)child); result.Add(feedback); } if (isValidParamOrOutputName(child.Name) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Problem Input ({0}) has an invalid name. " + NAME_EXPLANATION, (object)child.Name) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } return(result); }
public static IEnumerable <RuleFeedbackBase> SoTObjectsValid(MgaFCO context) { try { var result = new List <RuleFeedbackBase>(); // check for unsupported object types var unsupportedKinds = new List <string>(); unsupportedKinds.AddRange(new string[] { typeof(CyPhy.TopLevelSystemUnderTest).Name }); var fcos = (context as MgaModel) .ChildObjects .Cast <MgaFCO>() .Where(x => unsupportedKinds.Contains(x.Meta.Name)); foreach (var item in fcos) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Context: {0} - {1}[{2}] is not supported", context.Name, item.Name, item.Meta.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } return(result); } catch (Exception ex) { var result = new List <RuleFeedbackBase>(); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Context: {0} - Exception: {1} {2}", context.Name, ex.Message, ex.StackTrace) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); return(result); } }
public static IEnumerable<RuleFeedbackBase> SoTObjectsValid(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); // check for unsupported object types var unsupportedKinds = new List<string>(); unsupportedKinds.AddRange(new string[] { typeof(CyPhy.TopLevelSystemUnderTest).Name }); var fcos = (context as MgaModel) .ChildObjects .Cast<MgaFCO>() .Where(x => unsupportedKinds.Contains(x.Meta.Name)); foreach (var item in fcos) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Context: {0} - {1}[{2}] is not supported", context.Name, item.Name, item.Meta.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } return result; } catch (Exception ex) { var result = new List<RuleFeedbackBase>(); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Context: {0} - Exception: {1} {2}", context.Name, ex.Message, ex.StackTrace) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); return result; } }
private static IEnumerable <RuleFeedbackBase> checkRulesWorkFlow(CyPhy.TestBench testBench) { var result = new List <RuleFeedbackBase>(); if (testBench.Children.WorkflowRefCollection.Count() != 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Test-bench must have exactly one workflow {0}.", testBench.Name) }; feedback.InvolvedObjectsByRole.Add(testBench.Impl as IMgaFCO); result.Add(feedback); } else { var workflowRef = testBench.Children.WorkflowRefCollection.FirstOrDefault(); if (workflowRef != null && workflowRef.Referred.Workflow == null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Workflow reference is null: {0}.", workflowRef.Name) }; feedback.InvolvedObjectsByRole.Add(workflowRef.Impl as IMgaFCO); result.Add(feedback); } else { var workflow = workflowRef.Referred.Workflow; if (workflow.Children.TaskCollection.Count() < 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Workflow must have at least one task: {0}.", workflow.Name) }; feedback.InvolvedObjectsByRole.Add(workflow.Impl as IMgaFCO); result.Add(feedback); } } } return(result); }
public static IEnumerable <RuleFeedbackBase> CheckComponentName(MgaFCO context) { var result = new List <RuleFeedbackBase>(); if (namecheck_rgx.Match(context.Name).Success == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = NAME_EXPLANATION }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } return(result); }
public static IEnumerable <RuleFeedbackBase> UniqueNames(IEnumerable <FCO> components) { var result = new List <RuleFeedbackBase>(); var dupNames = components.GroupBy(tb => tb.Name).Where(group => group.Count() > 1) .Select(group => group.Key); if (dupNames.Count() > 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PET requires unique names. Duplicate names: {0}", String.Join(",", dupNames.ToArray())) }; result.Add(feedback); } return(result); }
private static IEnumerable <RuleFeedbackBase> checkOptimizerConstraintAttributes(CyPhy.OptimizerConstraint optConstraint) { var attributeCheckResults = new List <RuleFeedbackBase>(); double minValue = Double.NegativeInfinity; double maxValue = Double.PositiveInfinity; bool canGetMinAndMax = (optConstraint.Attributes.MinValue == "" || double.TryParse(optConstraint.Attributes.MinValue.Trim(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out minValue)) && (optConstraint.Attributes.MaxValue == "" || double.TryParse(optConstraint.Attributes.MaxValue.Trim(), NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out maxValue)); if (canGetMinAndMax) { if (minValue > maxValue) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, //FeedbackType = FeedbackTypes.Error: Seems like it should be an Error, but I don't want to block anybody Message = string.Format("OptimizerConstraint ({0}) Range Attribute: Min greater than Max", optConstraint.Name) }; feedback.InvolvedObjectsByRole.Add(optConstraint.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("OptimizerConstraint ({0}) Attributes: MinValue and/or MaxValue are not decimals", optConstraint.Name) }; feedback.InvolvedObjectsByRole.Add(optConstraint.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } return(attributeCheckResults); }
public static IEnumerable <RuleFeedbackBase> CheckRule(MgaFCO context) { var result = new List <RuleFeedbackBase>(); CyPhyML.Component cyPhyMLComponent = ISIS.GME.Common.Utils.CreateObject <CyPhyMLClasses.Component>(context as MgaObject); Dictionary <string, List <CyPhyML.HasDescriptionAndGUID> > namePPMListMap = new Dictionary <string, List <CyPhyML.HasDescriptionAndGUID> >(); List <object> objectList = cyPhyMLComponent.AllChildren.ToList <object>(); foreach (CyPhyML.HasDescriptionAndGUID cyPhyMLHasDescriptionAndGUID in cyPhyMLComponent.AllChildren. Where(x => x.GetType().UnderlyingSystemType == typeof(CyPhyMLClasses.Parameter) || x.GetType().UnderlyingSystemType == typeof(CyPhyMLClasses.Property) || x.GetType().UnderlyingSystemType == typeof(CyPhyMLClasses.Metric)) ) { Type type = cyPhyMLHasDescriptionAndGUID.GetType(); string name = cyPhyMLHasDescriptionAndGUID.Name; if (!namePPMListMap.ContainsKey(name)) { namePPMListMap[name] = new List <CyPhyML.HasDescriptionAndGUID>(); } namePPMListMap[name].Add(cyPhyMLHasDescriptionAndGUID); } foreach (string name in namePPMListMap.Keys) { List <CyPhyML.HasDescriptionAndGUID> ppmList = namePPMListMap[name]; if (ppmList.Count > 1) { var genericRuleFeedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = "Name \"" + name + "\" not unique between Parameter, Property, and Metric children of Component \"" + cyPhyMLComponent.Name + "\"" }; result.Add(genericRuleFeedback); } } return(result); }
public static IEnumerable <RuleFeedbackBase> OneAndOnlyOneDriver(MgaFCO context) { var result = new List <RuleFeedbackBase>(); var pet = CyPhyClasses.ParametricExploration.Cast(context); var cnt = pet.Children.ParameterStudyCollection.Count() + pet.Children.PCCDriverCollection.Count() + pet.Children.OptimizerCollection.Count(); if (cnt > 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The ParameterExploration-model has {0} drivers. There must only be one.", cnt) }; result.Add(feedback); } return(result); }
/// <summary> /// Assumption : A connector can only contain one redeclare. /// (If it cotains more a warning is printed that it won't be checked). /// </summary> /// <param name="startPoint"></param> /// <param name="mcEndpoint"></param> /// <param name="result"></param> private static void CheckRulesForConnectedRedeclares(CyPhy.ModelicaConnector startPoint, CyPhy.ModelicaConnector endPoint, List<RuleFeedbackBase> result) { var cntStartPoint = startPoint.Children.ModelicaRedeclareCollection.Count(); var cntEndPoint = endPoint.Children.ModelicaRedeclareCollection.Count(); if (cntEndPoint != cntStartPoint) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Connected {0} and {1}, do not contain the same number of ModelicaRedeclares, " + "they contain {2} and {3} respectively.", startPoint.Name, endPoint.Name, cntStartPoint, cntEndPoint) }; feedback.InvolvedObjectsByRole.Add(startPoint.Impl as IMgaFCO); feedback.InvolvedObjectsByRole.Add(endPoint.Impl as IMgaFCO); result.Add(feedback); } else if (cntStartPoint == 1) { var spRedeclare = startPoint.Children.ModelicaRedeclareCollection.FirstOrDefault(); var epRedeclare = endPoint.Children.ModelicaRedeclareCollection.FirstOrDefault(); CheckRulesForRedeclares(startPoint, spRedeclare, result); CheckRulesForRedeclares(endPoint, epRedeclare, result); if (spRedeclare.Attributes.Value != epRedeclare.Attributes.Value) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("{0} and {1} connected through {2} and {3}, do not have the same Values, " + "(elaborated) values are \"{4}\" and \"{5}\" respectively.", spRedeclare.Name, epRedeclare.Name, startPoint.Name, endPoint.Name, spRedeclare.Attributes.Value, epRedeclare.Attributes.Value) }; feedback.InvolvedObjectsByRole.Add(startPoint.Impl as IMgaFCO); feedback.InvolvedObjectsByRole.Add(endPoint.Impl as IMgaFCO); result.Add(feedback); } } else if (cntStartPoint > 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Connected {0} and {1}, contain more than one ({2}) ModelicaRedeclares. " + "The values of these will not be checked.", startPoint.Name, endPoint.Name, cntStartPoint) }; feedback.InvolvedObjectsByRole.Add(startPoint.Impl as IMgaFCO); feedback.InvolvedObjectsByRole.Add(endPoint.Impl as IMgaFCO); result.Add(feedback); } }
public static IEnumerable<RuleFeedbackBase> NoMoreThanOneModelicaConnectorWithinConnectors(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var connector = CyPhyClasses.Connector.Cast(context); var modelicaConnectors = connector.AllChildren.OfType<CyPhy.ModelicaConnector>(); if (modelicaConnectors.Count() > 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Not more than one ModelicaConnector allowed within Connector: {0}", connector.Name) }; feedback.InvolvedObjectsByRole.Add(connector.Impl as IMgaFCO); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ConnectorsMustHaveOneValidConnection(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); CyPhy.Connector connector = CyPhyClasses.Connector.Cast(context); if (connector.Children.ModelicaConnectorCollection.Any() == false) { // If there are no ModelicaConnectors inside no rules apply (Connector and connections will not be generated) return result; } var connParent = connector.ParentContainer; //List<CyPhy.ConnectorComposition> srcConns = new List<CyPhy.ConnectorComposition>(); //List<CyPhy.ConnectorComposition> dstConns = new List<CyPhy.ConnectorComposition>(); //List<CyPhy.ConnectorComposition> allConns = new List<CyPhy.ConnectorComposition>(); var srcConns = connector.SrcConnections.ConnectorCompositionCollection; var dstConns = connector.DstConnections.ConnectorCompositionCollection; var allConns = srcConns.Concat(dstConns); // Within ComponentAssemblies, every Connector must have at least one connection if (srcConns.Count() == 0 && dstConns.Count() == 0 && connParent is CyPhy.ComponentAssembly) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Connector with ModelicaConnectors must have at least 1 connection! {0}.", connector.Name) }; feedback.InvolvedObjectsByRole.Add(connector.Impl as IMgaFCO); result.Add(feedback); } foreach (var conn in allConns) { string srcID = conn.SrcEnd.ID; string dstID = conn.DstEnd.ID; var srcModelicaConnector = (conn.SrcEnd as CyPhy.Connector).Children.ModelicaConnectorCollection.FirstOrDefault(); var dstModelicaConnector = (conn.DstEnd as CyPhy.Connector).Children.ModelicaConnectorCollection.FirstOrDefault(); if (srcModelicaConnector == null || dstModelicaConnector == null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format( "Connection between Connectors with and without ModelicaConnectors will not be generated, ({0}.{1}<=>{2}.{3} within {4}).", conn.SrcEnd.ParentContainer.Name, conn.SrcEnd.Name, conn.DstEnd.ParentContainer.Name, conn.DstEnd.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } else if (srcModelicaConnector != null && dstModelicaConnector != null) { string srcClass = srcModelicaConnector.Attributes.Class; string dstClass = dstModelicaConnector.Attributes.Class; bool classesMatching = true; if (srcClass != dstClass) { // Sometimes the Class field is an empty string... Could be an Elaborator problem? if (srcClass != "" && dstClass != "") { string[] srcClassSplit = srcClass.Split('.'); int srcClassCount = srcClassSplit.Count(); string[] dstClassSplit = dstClass.Split('.'); int dstClassCount = dstClassSplit.Count(); // If the URI length is equal if (srcClassCount == dstClassCount) { int baseCount = srcClassCount - 1; string srcBaseClass = string.Join(".", srcClassSplit.Take(baseCount)); string dstBaseClass = string.Join(".", dstClassSplit.Take(baseCount)); if (srcBaseClass == dstBaseClass) { string srcLast = srcClassSplit.LastOrDefault(); string dstLast = dstClassSplit.LastOrDefault(); bool acceptableClassPair = srcLast.Contains("Real") && dstLast.Contains("Real") || srcLast.Contains("Boolean") && dstLast.Contains("Boolean") || srcLast.Contains("Integer") && dstLast.Contains("Integer") || srcLast.Contains("Frame") && dstLast.Contains("Frame") || srcLast.Contains("Flange") && dstLast.Contains("Flange") || srcLast.Contains("Pin") && dstLast.Contains("Pin") || srcLast.Contains("FWB") && dstLast.Contains("FWB") || srcLast.Contains("Hydraulic") && dstLast.Contains("Hydraulic") || srcLast.Contains("Fluid") && dstLast.Contains("Fluid") || srcLast.Contains("FlowPort") && dstLast.Contains("FlowPort"); if (acceptableClassPair == false) { classesMatching = false; } else // it might be an acceptable pair... { string badCharsInSrc = checkForInvalidCharacters(srcLast); string badCharsInDst = checkForInvalidCharacters(dstLast); if (badCharsInSrc != badCharsInDst) { classesMatching = false; } } } else { classesMatching = false; } } else { classesMatching = false; } } else { if (string.IsNullOrWhiteSpace(srcClass)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector '{0}' Class is empty.", conn.SrcEnd.Name) }; feedback.InvolvedObjectsByRole.Add(conn.SrcEnd.Impl as IMgaFCO); result.Add(feedback); } if (string.IsNullOrWhiteSpace(dstClass)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector '{0}' Class is empty.", conn.DstEnd.Name) }; feedback.InvolvedObjectsByRole.Add(conn.DstEnd.Impl as IMgaFCO); result.Add(feedback); } } } if (classesMatching == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector Classes do not match: {0}<=>{1} within {2}; Src Class: '{3}' Dst Class: '{4}'", conn.SrcEnd.Name, conn.DstEnd.Name, conn.ParentContainer.Name, srcClass, dstClass) }; feedback.InvolvedObjectsByRole.Add(conn.SrcEnd.Impl as IMgaFCO); feedback.InvolvedObjectsByRole.Add(conn.DstEnd.Impl as IMgaFCO); result.Add(feedback); } } // check for self-connections if (srcID == dstID) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Connector must not have a self-connection: {0}.{1} within {2}", connector.ParentContainer.Name, connector.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } // check for ports connected within the same container else if (conn.SrcEnd.ParentContainer.ID == conn.DstEnd.ParentContainer.ID) { // This narrows it down to connections where SrcEnd, DstEnd, & Conn all have the same parent (we don't want thi) if (conn.SrcEnd.ParentContainer.ID == conn.ParentContainer.ID) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Must not connect 2 Connectors within the same Container: {0}<=>{1} within {2}", conn.SrcEnd.Name, conn.DstEnd.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } } } bool hasOneValidConn = false; List<string> connectedPortIDs = new List<string>(); foreach (var conn in srcConns) { // check if this srcPort already has a connection to the port of interest if (connectedPortIDs.Contains(conn.SrcEnd.ID)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Redundant connection between {0}.{1}<=>{2}.{3} within {4}", connector.ParentContainer.Name, connector.Name, conn.SrcEnd.ParentContainer.Name, conn.SrcEnd.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } // add this srcPort to the list of connected ports connectedPortIDs.Add(conn.SrcEnd.ID); // Make a note of any valid connection; must have at least one to pass this check if (connParent is CyPhy.ComponentAssembly) { if (conn.SrcEnd.ParentContainer is CyPhy.ComponentAssembly || conn.SrcEnd.ParentContainer is CyPhy.Component) { hasOneValidConn = true; } } } foreach (var conn in dstConns) { // check if this dstPort already has a connection to the port of interest if (connectedPortIDs.Contains(conn.DstEnd.ID)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Redundant connection between {0}.{1}<=>{2}.{3} within {4}", connector.ParentContainer.Name, connector.Name, conn.DstEnd.ParentContainer.Name, conn.DstEnd.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } // add this dstPort to the list of connected ports connectedPortIDs.Add(conn.DstEnd.ID); // Make a note of any valid connection; must have at least one to pass this check if (connParent is CyPhy.ComponentAssembly) { if (conn.DstEnd.ParentContainer is CyPhy.ComponentAssembly || conn.DstEnd.ParentContainer is CyPhy.Component) { hasOneValidConn = true; } } } // if we have gone through all the connections and not specifically found a valid connection, FAIL if (connParent is CyPhy.ComponentAssembly && hasOneValidConn == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Could not find a valid connection for {0}", connector.Name) }; feedback.InvolvedObjectsByRole.Add(connector.Impl as IMgaFCO); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ConnectorWithinComponent(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var componentType = CyPhyClasses.ComponentType.Cast(context); var connectors = componentType.Children.ConnectorCollection; foreach (var connector in connectors) { // There should only be one ModelicaConnector within Connector var modelicaConnector = connector.Children.ModelicaConnectorCollection.FirstOrDefault(); if (modelicaConnector == null) { //var feedback = new GenericRuleFeedback() //{ // FeedbackType = FeedbackTypes.Warning, // Message = string.Format( // "Connector ({0}) contains no ModelicaConnector (within {1})", // connector.Name, // componentType.Name) //}; //feedback.InvolvedObjectsByRole.Add(connector.Impl as IMgaFCO); //feedback.InvolvedObjectsByRole.Add(componentType.Impl as IMgaFCO); //result.Add(feedback); continue; } List<CyPhy.PortComposition> srcConns = new List<CyPhy.PortComposition>(); List<CyPhy.PortComposition> dstConns = new List<CyPhy.PortComposition>(); List<CyPhy.PortComposition> allConns = new List<CyPhy.PortComposition>(); var srcConnPortCompCollection = modelicaConnector.SrcConnections.PortCompositionCollection; var dstConnPortCompCollection = modelicaConnector.DstConnections.PortCompositionCollection; if (srcConnPortCompCollection != null) { srcConns.AddRange(srcConnPortCompCollection); allConns.AddRange(srcConnPortCompCollection); } if (dstConnPortCompCollection != null) { dstConns.AddRange(dstConnPortCompCollection); allConns.AddRange(dstConnPortCompCollection); } foreach (var conn in allConns) { var mgaConn = conn.Impl as IMgaSimpleConnection; string srcID = mgaConn.Src.ID; string dstID = mgaConn.Dst.ID; MgaObject srcParent = null; GME.MGA.Meta.objtype_enum type; mgaConn.Src.GetParent(out srcParent, out type); MgaObject dstParent = null; GME.MGA.Meta.objtype_enum typeDst; mgaConn.Dst.GetParent(out dstParent, out typeDst); string srcParentID = srcParent.ID; string dstParentID = dstParent.ID; MgaFCO parentContainer = conn.ParentContainer.Impl as MgaFCO; // check for self-connections if (srcID == dstID) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector must not have a self-connection: {0} within {1}", modelicaConnector.Name, modelicaConnector.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(modelicaConnector.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } // check for ports connected within the same container else if (srcParentID == dstParentID) { // Narrow it down to cases where SrcEnd, DstEnd, & conn are all in the same container if (srcParentID == parentContainer.ID) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Must not connect 2 ModelicaConnectors within the same Container: {0}<=>{1} within {2}", conn.SrcEnd.Name, conn.DstEnd.Name, parentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(parentContainer as IMgaFCO); result.Add(feedback); } else if (parentContainer.MetaBase.Name == typeof(CyPhy.Component).Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Must not connect 2 ModelicaConnectors within the same Container: {0}<=>{1} within {2}", conn.SrcEnd.Name, conn.DstEnd.Name, parentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(parentContainer as IMgaFCO); result.Add(feedback); } } } bool hasOneValidConn = false; HashSet<string> connectedPortIDs = new HashSet<string>(); foreach (var conn in srcConns) { var mgaConn = conn.Impl as IMgaSimpleConnection; string srcID = mgaConn.Src.ID; // check if this srcPort already has a connection to the port of interest if (connectedPortIDs.Contains(srcID)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Redundant connection between {0}<=>{1} within {2}", modelicaConnector.Name, conn.SrcEnd.Name, context.Name) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } // add this srcPort to the list of connected ports connectedPortIDs.Add(srcID); // Make a note of any valid connection; must have at least one to pass this check if (conn.SrcEnd.ParentContainer is CyPhy.ModelicaModel || conn.SrcEnd.ParentContainer is CyPhy.CyberModel ) { hasOneValidConn = true; } } foreach (var conn in dstConns) { var mgaConn = conn.Impl as IMgaSimpleConnection; string dstID = mgaConn.Dst.ID; MgaObject dstParent = null; GME.MGA.Meta.objtype_enum typeDst; mgaConn.Dst.GetParent(out dstParent, out typeDst); // check if this dstPort already has a connection to the port of interest if (connectedPortIDs.Contains(dstID)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Redundant connection between {0}<=>{1} within {2}", modelicaConnector.Name, conn.DstEnd.Name, context.Name) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } // add this dstPort to the list of connected ports connectedPortIDs.Add(dstID); // Make a note of any valid connection; must have at least one to pass this check if (dstParent.MetaBase.Name == typeof(CyPhy.ModelicaModel).Name || dstParent.MetaBase.Name == typeof(CyPhy.CyberModel).Name ) { hasOneValidConn = true; } } // if we have gone through all the connections and not specifically found a valid connection, FAIL if (hasOneValidConn == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format( "Could not find a valid connection for {0}", modelicaConnector.Name) }; feedback.InvolvedObjectsByRole.Add(modelicaConnector.Impl as IMgaFCO); result.Add(feedback); } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable <RuleFeedbackBase> TestBenchCorrectlySetUp(MgaFCO context) { var result = new List <RuleFeedbackBase>(); var testBenchRef = CyPhyClasses.TestBenchRef.Cast(context); if (testBenchRef.AllReferred == null) { result.Add(new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBenchRef, '{0}', is a null reference; it must reference a TestBench.", testBenchRef) }); } else if (testBenchRef.AllReferred is CyPhy.TestBench) { result.AddRange(checkRulesWorkFlow(testBenchRef.AllReferred as CyPhy.TestBench)); } else if (testBenchRef.AllReferred is CyPhy.TestBenchType) { } else { // No language support of other test-bech types. throw new NotImplementedException("Ooops! No support for this test-bech type."); } // TODO: Maybe map the IDs into the python code and update py_modelica. In that case the check for // only connected parameters/metrics could suffice. if (testBenchRef.AllReferred != null) { var testBench = testBenchRef.AllReferred as CyPhy.TestBenchType; var parameters = testBench.Children.ParameterCollection; if (parameters.Count() != parameters.Select(p => p.Name).Distinct().Count()) { var names = String.Join(", ", parameters.Select(p => p.Name).GroupBy(p => p).Where(x => x.Count() > 1).Select(x => x.First()).ToArray()); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Duplicate parameter names '{0}'.", names) }; feedback.InvolvedObjectsByRole.Add(testBench.Impl as IMgaFCO); result.Add(feedback); } var metrics = testBench.Children.MetricCollection; if (metrics.Count() != metrics.Select(p => p.Name).Distinct().Count()) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Metrics in test-bench share common names.") }; feedback.InvolvedObjectsByRole.Add(testBench as IMgaFCO); result.Add(feedback); } } return(result); }
private static IEnumerable <RuleFeedbackBase> checkMdaoDriverChildren(MgaFCO context) { var checkResults = new List <RuleFeedbackBase>(); var mdaoDriver = CyPhyClasses.MDAODriver.Cast(context); // META-2995 bool allowDiscreteRanges = false; if (context.MetaBase.Name == typeof(CyPhy.ParameterStudy).Name) { var parameterStudy = CyPhyClasses.ParameterStudy.Cast(context); allowDiscreteRanges = parameterStudy.Attributes.SurrogateType == CyPhyClasses.ParameterStudy.AttributesClass.SurrogateType_enum.None; } // Get children, check for connections var designVariables = mdaoDriver.Children.DesignVariableCollection; var objectives = mdaoDriver.Children.ObjectiveCollection; if (objectives.Count() < 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("MDAO Driver {0} must have at least 1 Objective", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); checkResults.Add(feedback); } var tbParamsWithConnections = new HashSet <Tuple <ISIS.GME.Common.Interfaces.Reference, ISIS.GME.Common.Interfaces.FCO> >(); // Check for connections and names of parameters in the test-bench. foreach (var designVar in designVariables) { var varSweepCollection = designVar.DstConnections.VariableSweepCollection; if (varSweepCollection.Count() == 1) { CyPhy.VariableSweep varSweep = varSweepCollection.FirstOrDefault(); var tbParam = varSweep.DstEnds.Parameter; var tb = varSweep.GenericDstEndRef; if (tbParam != null) { var tbParamParent = tbParam.ParentContainer; if (tbParamParent != null && ((tbParamParent is CyPhy.TestBenchType) == false && (tbParamParent is CyPhy.ParametricTestBench) == false)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Driver DesignVariable ({0}) must have 1 connection to a Testbench Parameter.", designVar.Name) }; feedback.InvolvedObjectsByRole.Add(designVar.Impl as IMgaFCO); checkResults.Add(feedback); } else { if (isValidParamOrOutputName(tbParam.Name) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Connected Parameter ({0}) has an invalid name. " + NAME_EXPLANATION, tbParam.Name) }; feedback.InvolvedObjectsByRole.Add(tbParam.Impl as IMgaFCO); checkResults.Add(feedback); } var value = tbParam.Attributes.Value; double dummy; // TODO can we do type checking here? e.g. double connected to double } if (tbParamsWithConnections.Add( new Tuple <ISIS.GME.Common.Interfaces.Reference, ISIS.GME.Common.Interfaces.FCO>(tb, tbParam)) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBench Parameter ({0}) must have only 1 connection from a DesignVariable", tbParam.Name) }; feedback.InvolvedObjectsByRole.Add(tbParam.Impl as IMgaFCO); checkResults.Add(feedback); } } } else if (varSweepCollection != null && varSweepCollection.Count() == 0) { var problemInputs = designVar.DstConnections.ProblemInputFlowSourceConnectionCollection; if (problemInputs.Count() < 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Driver DesignVariable ({0}) must have at least 1 connection to a Testbench Parameter/Property", designVar.Name) }; feedback.InvolvedObjectsByRole.Add(designVar.Impl as IMgaFCO); checkResults.Add(feedback); } } } // Check for connections and names of metrics in the test-bench. foreach (var obj in objectives) { var objMappingCollection = obj.SrcConnections.ObjectiveMappingCollection; var fileFlowCollection = obj.SrcConnections.FileResultFlowCollection; var outputColection = obj.SrcConnections.ProblemOutputFlowTargetConnectionCollection; if (objMappingCollection.Count() + fileFlowCollection.Count() + outputColection.Count() == 1) { FCO tbMetric; if (objMappingCollection.Count() == 1) { CyPhy.ObjectiveMapping objMap = objMappingCollection.FirstOrDefault(); tbMetric = objMap.SrcEnd; } else if (outputColection.Count() == 1) { tbMetric = outputColection.First().SrcEnd; } else { var fileFlow = fileFlowCollection.First(); tbMetric = fileFlow.SrcEnd; } if (tbMetric != null) { var tbMetricParent = tbMetric.ParentContainer; if ((tbMetricParent is CyPhy.TestBenchType) == false && (tbMetricParent is CyPhy.ParametricTestBench) == false && (tbMetricParent is CyPhy.Constants) == false && (tbMetricParent is CyPhy.ParametricExploration) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Driver Objective ({0}) must have 1 connection from a Testbench Metric", obj.Name) }; feedback.InvolvedObjectsByRole.Add(obj.Impl as IMgaFCO); checkResults.Add(feedback); } else { if (isValidParamOrOutputName(tbMetric.Name) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Connected Metric ({0}) has an invalid name. " + NAME_EXPLANATION, tbMetric.Name) }; feedback.InvolvedObjectsByRole.Add(tbMetric.Impl as IMgaFCO); checkResults.Add(feedback); } } } } else { if (objMappingCollection.Count() + fileFlowCollection.Count() + outputColection.Count() > 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Driver Objective ({0}) must not have multiple incoming connections", obj.Name) }; feedback.InvolvedObjectsByRole.Add(obj.Impl as IMgaFCO); checkResults.Add(feedback); } else if (objMappingCollection.Count() + fileFlowCollection.Count() + outputColection.Count() == 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Driver Objective ({0}) does not have an incoming connection", obj.Name) }; feedback.InvolvedObjectsByRole.Add(obj.Impl as IMgaFCO); checkResults.Add(feedback); } } } return(checkResults); }
private static IEnumerable <RuleFeedbackBase> checkPccParamAttributes(CyPhy.PCCParameter param) { var attributeCheckResults = new List <RuleFeedbackBase>(); if (param is CyPhy.PCCParameterNormal) { var normalParam = param as CyPhy.PCCParameterNormal; double mean = normalParam.Attributes.Mean; double stdDev = normalParam.Attributes.StandardDeviation; if (stdDev <= 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC NormalParameter ({0}) StandardDeviation must be greater than 0.", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } } else if (param is CyPhy.PCCParameterUniform) { var uniformParam = param as CyPhy.PCCParameterUniform; double highLimit = uniformParam.Attributes.HighLimit; double lowLimit = uniformParam.Attributes.LowLimit; if (lowLimit >= highLimit) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC UniformParameter ({0}) HighLimit (b) must be greater than LowLimit (a).", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } } else if (param is CyPhy.PCCParameterLNormal) { var logNormalParam = param as CyPhy.PCCParameterLNormal; double logScale = logNormalParam.Attributes.LogScale; double shape = logNormalParam.Attributes.Shape; if (shape <= 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC LogNormalParameter ({0}) Shape must be greater than 0.", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } } else if (param is CyPhy.PCCParameterBeta) { var betaParam = param as CyPhy.PCCParameterBeta; double highLimit = betaParam.Attributes.HighLimit; double lowLimit = betaParam.Attributes.LowLimit; double shape1 = betaParam.Attributes.Shape1; double shape2 = betaParam.Attributes.Shape2; if (lowLimit >= highLimit) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC BetaParameter ({0}) HighLimit (b) must be greater than LowLimit (a).", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } if (shape1 <= 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC BetaParameter ({0}) Shape1 (alpha) must be greater than 0.", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } if (shape2 <= 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC BetaParameter ({0}) Shape2 (beta) must be greater than 0.", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Could not cast PCC parameter ({0}) as any known type.", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); attributeCheckResults.Add(feedback); } return(attributeCheckResults); }
public static IEnumerable<RuleFeedbackBase> SolverSettings(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var testBench = CyPhyClasses.TestBench.Cast(context); if (testBench.Children.SolverSettingsCollection.FirstOrDefault() == null) { var solverSettings = CyPhyClasses.SolverSettings.Create(testBench); solverSettings.Name = "DefaultSolverSettings"; var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Test bench ({0}) requires a SolverSettings block; please add one.", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } else if (testBench.Children.SolverSettingsCollection.Count() > 1) { var names = testBench.Children.SolverSettingsCollection.Select(x => x.Name); var involvedObjects = testBench.Children.SolverSettingsCollection.Select(x => x.Impl as IMgaFCO); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Test bench must have one solver settings object {0}. {1}", context.Name, string.Join(", ", names)) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); feedback.InvolvedObjectsByRole.AddRange(involvedObjects); result.Add(feedback); } else { // Check Attributes of an existing solversetting var ss = testBench.Children.SolverSettingsCollection.FirstOrDefault(); if (ss.Attributes.Tolerance < 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Tolerance must be greater, or equal which implies tool default, to 0. Given was '{0}'.", ss.Attributes.Tolerance) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); feedback.InvolvedObjectsByRole.Add(ss.Impl as MgaFCO); result.Add(feedback); } switch (ss.Attributes.IntervalMethod) { case CyPhyClasses.SolverSettings.AttributesClass.IntervalMethod_enum.Number_of_Intervals: if (ss.Attributes.NumberOfIntervals < 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Number of intervals must be greater, or equal which implies tool default, to 0. Given was '{0}'.", ss.Attributes.NumberOfIntervals) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); feedback.InvolvedObjectsByRole.Add(ss.Impl as MgaFCO); result.Add(feedback); } break; case CyPhyClasses.SolverSettings.AttributesClass.IntervalMethod_enum.Interval_Length: if (ss.Attributes.IntervalLength < 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Interval length must be greater, or equal which implies tool default, to 0. Given was '{0}'.", ss.Attributes.IntervalLength) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); feedback.InvolvedObjectsByRole.Add(ss.Impl as MgaFCO); result.Add(feedback); } break; } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ModelicaParametersHaveValues(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); // Skip ModelicaConnectors within Connectors if (context.ParentModel is CyPhy.Connector) { return result; } IEnumerable<CyPhy.ModelicaParameter> childParameters = null; if (context.Meta.Name == typeof(CyPhy.ModelicaModel).Name) { var modelicaModel = CyPhyClasses.ModelicaModel.Cast(context); childParameters = modelicaModel.Children.ModelicaParameterCollection; } else if (context.Meta.Name == typeof(CyPhy.ModelicaConnector).Name) { var modelicaConnector = CyPhyClasses.ModelicaConnector.Cast(context); childParameters = modelicaConnector.Children.ModelicaParameterCollection; } else if (context.Meta.Name == typeof(CyPhy.CyberModel).Name) { var cyberModel = CyPhyClasses.CyberModel.Cast(context); childParameters = cyberModel.Children.ModelicaParameterCollection; } if (childParameters == null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Component {0} has no parameters.", context.Name) }; result.Add(feedback); } else { foreach (var param in childParameters) { string value = param.Attributes.Value; if (value == null || value == "") { var valueFlowsIn = param.AllSrcConnections.Count(); var valueFlowsOut = param.AllDstConnections.Count(); if (valueFlowsIn == 0 && valueFlowsOut == 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("ModelicaParameter {0} has an empty 'Value' field and no connections", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); result.Add(feedback); } } // META-1615 ModelicaParameter must be connected to a Property or a Parameter var vfs = param.SrcConnections.ModelicaParameterPortMapCollection; if (vfs.Count() == 1) { var vf = vfs.FirstOrDefault(); var srcKind = (vf.Impl as MgaSimpleConnection).Src.MetaBase.Name; if (srcKind == typeof(CyPhy.Parameter).Name || srcKind == typeof(CyPhy.Property).Name) { // These are the only allowed flows into ModelicaParameters (Simple/CustomFormulas are not allowed) } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("ModelicaParameter {0} can only have incoming values from Properties or Parameters. " + "(If you want a formula value, place an intermediate Parameter or Property.)", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); result.Add(feedback); } } else if (vfs.Count() > 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("ModelicaParameter {0} has more than two incoming values! It may only have one.", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); result.Add(feedback); } } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ConnectorWithinComponentAssembly(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var compAssm = CyPhyClasses.ComponentAssembly.Cast(context); var connectors = compAssm.Children.ConnectorCollection; foreach (var conn in connectors) { // Should only be one ModelicaConnector; another rule checks for this condition var modelicaConnector = conn.Children.ModelicaConnectorCollection.FirstOrDefault(); if (modelicaConnector == null) { // This does not need to be printed every single time. //var feedback = new GenericRuleFeedback() //{ // FeedbackType = FeedbackTypes.Warning, // Message = string.Format( // "Connector ({0}) contains no ModelicaConnector (within {1})", // conn.Name, // compAssm.Name) //}; //feedback.InvolvedObjectsByRole.Add(conn.Impl as IMgaFCO); //feedback.InvolvedObjectsByRole.Add(compAssm.Impl as IMgaFCO); //result.Add(feedback); continue; } var src_PortCompositionCollection = modelicaConnector.SrcConnections.PortCompositionCollection; var dst_PortCompositionCollection = modelicaConnector.DstConnections.PortCompositionCollection; if (src_PortCompositionCollection.Count() != 0 || dst_PortCompositionCollection.Count() != 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector within Connector within ComponentAssembly should have zero connections: {0}.", modelicaConnector.Name) }; feedback.InvolvedObjectsByRole.Add(modelicaConnector.Impl as IMgaFCO); result.Add(feedback); } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> TestBenchNameMustBeValid(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var tbName = context.Name; string badCharacters = null; badCharacters = checkForInvalidCharacters(tbName); if (string.IsNullOrEmpty(badCharacters) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "The test-bench '{0}' contains invalid characters; '{1}'.", tbName, badCharacters) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } getExternalPackageNames(context); var protectedName = checkForInvalidName(tbName); if (string.IsNullOrEmpty(protectedName) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Test-bench name {0} is invalid; {1} is a reserved name.", tbName, protectedName) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } if (tbName.Length == 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Test-bench name {0} is empty, please give it a name.", tbName) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } else if(char.IsDigit(tbName[0])) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Test-bench name {0} is invalid; names must not begin with a digit.", tbName) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ModelicaConnectorsMustHaveOneValidConnection(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); CyPhy.ModelicaConnector modelicaConnector = CyPhyClasses.ModelicaConnector.Cast(context); var connParent = modelicaConnector.ParentContainer; // this rule should not apply to ModelicaConnectors within Connectors if (connParent is CyPhy.Connector) { return result; } //List<CyPhy.PortComposition> srcConns = new List<CyPhy.PortComposition>(); //List<CyPhy.PortComposition> dstConns = new List<CyPhy.PortComposition>(); List<CyPhy.PortComposition> allConns = new List<CyPhy.PortComposition>(); var srcConns = modelicaConnector.SrcConnections.PortCompositionCollection; var dstConns = modelicaConnector.DstConnections.PortCompositionCollection; // Within Components, TestComponents, and ComponentAssemblies, every ModelicaConnector must have at least one connection if (srcConns.Count() == 0 && dstConns.Count() == 0) { if (connParent is CyPhy.Component || connParent is CyPhy.TestComponent || connParent is CyPhy.ComponentAssembly) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector must have at least 1 connection! {0}.", modelicaConnector.Name) }; feedback.InvolvedObjectsByRole.Add(modelicaConnector.Impl as IMgaFCO); result.Add(feedback); } return result; } allConns.AddRange(srcConns); allConns.AddRange(dstConns); foreach (var conn in allConns) { var mgaConn = conn.Impl as IMgaSimpleConnection; var mgaSrc = mgaConn.Src; var mgaDst = mgaConn.Dst; // META-3186 if (mgaSrc.MetaBase.Name != typeof(CyPhy.ModelicaConnector).Name || mgaDst.MetaBase.Name != typeof(CyPhy.ModelicaConnector).Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "'{0}' connects a connector that is not a ModelicaConnector.", modelicaConnector.Name) }; feedback.InvolvedObjectsByRole.Add(mgaConn); feedback.InvolvedObjectsByRole.Add(mgaSrc); feedback.InvolvedObjectsByRole.Add(mgaDst); result.Add(feedback); return result; } string srcID = mgaSrc.ID; string dstID = mgaDst.ID; MgaObject srcParent = null; GME.MGA.Meta.objtype_enum type; mgaSrc.GetParent(out srcParent, out type); MgaObject dstParent = null; GME.MGA.Meta.objtype_enum typeDst; mgaDst.GetParent(out dstParent, out typeDst); MgaObject mgaParent = null; GME.MGA.Meta.objtype_enum typeParent; mgaDst.GetParent(out mgaParent, out typeParent); string srcParentID = srcParent.ID; string dstParentID = dstParent.ID; string parentID = mgaParent.ID; bool classesMatching = true; string srcClass = mgaSrc.GetStrAttrByNameDisp("Class"); string dstClass = mgaDst.GetStrAttrByNameDisp("Class"); if (srcClass != dstClass) { // Sometimes the Class field is an empty string... Could be an Elaborator problem? if (string.IsNullOrEmpty(srcClass) == false && string.IsNullOrEmpty(dstClass) == false) { string[] srcClassSplit = srcClass.Split('.'); int srcClassCount = srcClassSplit.Count(); string[] dstClassSplit = dstClass.Split('.'); int dstClassCount = dstClassSplit.Count(); // If the URI length is equal if (srcClassCount == dstClassCount) { int baseCount = srcClassCount - 1; string srcBaseClass = string.Join(".", srcClassSplit.Take(baseCount)); string dstBaseClass = string.Join(".", dstClassSplit.Take(baseCount)); if (srcBaseClass == dstBaseClass) { string srcLast = srcClassSplit.LastOrDefault(); string dstLast = dstClassSplit.LastOrDefault(); bool acceptableClassPair = srcLast.Contains("Real") && dstLast.Contains("Real") || srcLast.Contains("Boolean") && dstLast.Contains("Boolean") || srcLast.Contains("Integer") && dstLast.Contains("Integer") || srcLast.Contains("Frame") && dstLast.Contains("Frame") || srcLast.Contains("Flange") && dstLast.Contains("Flange") || srcLast.Contains("Pin") && dstLast.Contains("Pin") || srcLast.Contains("FWB") && dstLast.Contains("FWB") || srcLast.Contains("Hydraulic") && dstLast.Contains("Hydraulic") || srcLast.Contains("Fluid") && dstLast.Contains("Fluid") || srcLast.Contains("FlowPort") && dstLast.Contains("FlowPort"); if (acceptableClassPair == false) { classesMatching = false; } else // it might be an acceptable mismatch... { string badCharsInSrc = checkForInvalidCharacters(srcLast); string badCharsInDst = checkForInvalidCharacters(dstLast); if (badCharsInSrc != badCharsInDst) { classesMatching = false; } } } else { classesMatching = false; } } else { classesMatching = false; } } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector Classes are both empty: {0}.{1}<=>{2}.{3} within {4}", conn.SrcEnd.ParentContainer.Name, conn.SrcEnd.Name, conn.DstEnd.ParentContainer.Name, conn.DstEnd.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } } if (classesMatching == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector Classes do not match: {0}<=>{1} within {2}; Src Class: '{3}' Dst Class: '{4}'", conn.SrcEnd.Name, conn.DstEnd.Name, conn.ParentContainer.Name, srcClass, dstClass) }; feedback.InvolvedObjectsByRole.Add(conn.SrcEnd.Impl as IMgaFCO); feedback.InvolvedObjectsByRole.Add(conn.DstEnd.Impl as IMgaFCO); result.Add(feedback); }; // check for self-connections if (srcID == dstID) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "ModelicaConnector must not have a self-connection: {0} within {1}", modelicaConnector.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } // check for ports connected within the same container else if (srcParentID == dstParentID) { // Narrow it down to cases where SrcEnd, DstEnd, & conn are all in the same container if (srcParentID == parentID) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Must not connect 2 ModelicaConnectors within the same Container: {0}.{1}<=>{2}.{3} within {4}", conn.SrcEnd.ParentContainer.Name, conn.SrcEnd.Name, conn.DstEnd.ParentContainer.Name, conn.DstEnd.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(mgaParent as IMgaFCO); result.Add(feedback); } else if (mgaParent.MetaBase.Name == typeof(CyPhy.Component).Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Must not connect 2 ModelicaConnectors within the same Container: {0}<=>{1} within {2}", conn.SrcEnd.Name, conn.DstEnd.Name, conn.ParentContainer.Name) }; feedback.InvolvedObjectsByRole.Add(conn.ParentContainer.Impl as IMgaFCO); result.Add(feedback); } } } bool hasOneValidConn = false; List<string> connectedPortIDs = new List<string>(); foreach (var conn in srcConns) { var mgaConn = conn.Impl as IMgaSimpleConnection; var mgaSrc = mgaConn.Src; string srcID = mgaSrc.ID; // check if this srcPort already has a connection to the port of interest if (connectedPortIDs.Contains(srcID)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Redundant connection between {0}<=>{1} within {2}", modelicaConnector.Name, conn.SrcEnd.Name, connParent.Name) }; feedback.InvolvedObjectsByRole.Add(connParent.Impl as IMgaFCO); result.Add(feedback); } // add this srcPort to the list of connected ports connectedPortIDs.Add(srcID); // Make a note of any valid connection; must have at least one to pass this check if (connParent is CyPhy.Component || connParent is CyPhy.TestComponent) { if (conn.SrcEnd.ParentContainer is CyPhy.ModelicaModel || conn.SrcEnd.ParentContainer is CyPhy.CyberModel ) { hasOneValidConn = true; } } else if (connParent is CyPhy.ComponentAssembly) { if (conn.SrcEnd.ParentContainer is CyPhy.ComponentAssembly || conn.SrcEnd.ParentContainer is CyPhy.Component) { hasOneValidConn = true; } } } foreach (var conn in dstConns) { // check if this dstPort already has a connection to the port of interest if (connectedPortIDs.Contains(conn.DstEnd.ID)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Redundant connection between {0}<=>{1} within {2}", modelicaConnector.Name, conn.DstEnd.Name, connParent.Name) }; feedback.InvolvedObjectsByRole.Add(connParent.Impl as IMgaFCO); result.Add(feedback); } // add this dstPort to the list of connected ports connectedPortIDs.Add(conn.DstEnd.ID); // Make a note of any valid connection; must have at least one to pass this check if (connParent is CyPhy.Component || connParent is CyPhy.TestComponent) { if (conn.DstEnd.ParentContainer is CyPhy.ModelicaModel || conn.DstEnd.ParentContainer is CyPhy.CyberModel ) { hasOneValidConn = true; } } else if (connParent is CyPhy.ComponentAssembly) { if (conn.DstEnd.ParentContainer is CyPhy.ComponentAssembly || conn.DstEnd.ParentContainer is CyPhy.Component) { hasOneValidConn = true; } } } // if we have gone through all the connections and not specifically found a valid connection, FAIL if (connParent is CyPhy.Component || connParent is CyPhy.TestComponent || connParent is CyPhy.ComponentAssembly) { if (hasOneValidConn == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "Could not find a valid connection for {0}", modelicaConnector.Name) }; feedback.InvolvedObjectsByRole.Add(modelicaConnector.Impl as IMgaFCO); result.Add(feedback); } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ModelicaModelHasValidURI(MgaFCO context) { var result = new List<RuleFeedbackBase>(); try { // Check if it's a Component if (context.Meta.Name == typeof(CyPhy.Component).Name) { bool checkAllModelicaURIs = false; CyPhy.Component component = CyPhyClasses.Component.Cast(context); // If it has a single ModelicaModel, check the URI var nbrOfModelicaModels = (context as GME.MGA.IMgaModel).GetChildrenOfKind(typeof(CyPhy.ModelicaModel).Name).Count; if (nbrOfModelicaModels == 0) { return result; } else if (nbrOfModelicaModels == 1) { var modelicaModel = component.Children.ModelicaModelCollection.FirstOrDefault(); result.AddRange(checkModelicaModelURI(modelicaModel.Impl as MgaFCO)); } else // It has multiple ModelicaModels, check if we have 'Classifications' { string componentClass = component.Attributes.Classifications; if (string.IsNullOrWhiteSpace(componentClass)) { // No discernable Classifications, check all ModelicaModel URIs checkAllModelicaURIs = true; } else // Component's Classifications is 'legit' { var thisComponentFidelitySetting = new Dictionary<string, string>(); string modelicaModelName = null; // Get the Testbench's FidelitySettings Regeistry Node try { CyPhy.TestBench tb = CyPhyClasses.TestBench.Cast(GetTestbench(context)); var fidelitySettings = CodeGenMethods.GetFidelitySettingsFromTestBench(tb); fidelitySettings.TryGetValue(componentClass, out thisComponentFidelitySetting); thisComponentFidelitySetting.TryGetValue(typeof(CyPhy.ModelicaModel).Name, out modelicaModelName); } catch (Exception) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Problem getting FidelitySettings for {0}; checking all Modelica URIs", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); checkAllModelicaURIs = true; } if (modelicaModelName != null) { var modelicaModel = component.Children.ModelicaModelCollection.FirstOrDefault(x => x.Name == modelicaModelName); if (modelicaModel == null) { checkAllModelicaURIs = true; } else { // Actually found the correct model result.AddRange(checkModelicaModelURI(modelicaModel.Impl as MgaFCO)); } } else { checkAllModelicaURIs = true; } } if (checkAllModelicaURIs) { foreach (var mm in component.Children.ModelicaModelCollection) { result.AddRange(checkModelicaModelURI(mm.Impl as MgaFCO)); } } } } else if (context.Meta.Name == typeof(CyPhy.TestComponent).Name) { // This is a TestComponent CyPhy.ModelicaModel modelicaModel = (CyPhyClasses.TestComponent.Cast(context).Children.ModelicaModelCollection.FirstOrDefault()); if (modelicaModel == null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Test-component does not have a modelica-model, '{0}'.", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } else { result.AddRange(checkModelicaModelURI(modelicaModel.Impl as MgaFCO)); } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ParametersHaveValidIncomingFlowsAndRanges(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var parameter = CyPhyClasses.Parameter.Cast(context); if (parameter.ParentContainer is CyPhy.Component) { // TODO: Should check for IsDynamicComponent var component = parameter.ParentContainer as CyPhy.Component; if (component.Children.ModelicaModelCollection.Any() == false) { return result; } } // META-3622 if (parameter.ParentContainer is CyPhy.Component || parameter.ParentContainer is CyPhy.ComponentAssembly) { if (String.IsNullOrWhiteSpace(parameter.Attributes.Dimension) == false && parameter.Attributes.Dimension.Trim() != "1") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = "Parameter has Dimension != 1 - it will not be generated. This will break mapped value flow chains." }; feedback.InvolvedObjectsByRole.Add(parameter.Impl as IMgaFCO); result.Add(feedback); } } var range = parameter.Attributes.Range.Trim().TrimStart('[').TrimEnd(']').Trim(); if (string.IsNullOrWhiteSpace(range) == false && range != "-inf..inf") { var values = range.Split(CyPhy2Modelica_v2.Modelica.CodeGenerator.RangeDividers, StringSplitOptions.None); var rangeErrMsg = string.Format("Parameter {0} has an invalid range, '{1}'. " + "The range must two reals (or -inf/inf) separated by {2}. Optionally it can have surrounding brackets.", parameter.Name, parameter.Attributes.Range, String.Join(" or ", CyPhy2Modelica_v2.Modelica.CodeGenerator.RangeDividers.ToArray())); if (values.Length != 2) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = rangeErrMsg }; feedback.InvolvedObjectsByRole.Add(parameter.Impl as IMgaFCO); result.Add(feedback); } else { double dummyDouble; if (double.TryParse(values[0].Trim(), out dummyDouble) == false && values[0].Trim() != "-inf") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = rangeErrMsg }; feedback.InvolvedObjectsByRole.Add(parameter.Impl as IMgaFCO); result.Add(feedback); } if (double.TryParse(values[1].Trim(), out dummyDouble) == false && values[1].Trim() != "inf") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = rangeErrMsg }; feedback.InvolvedObjectsByRole.Add(parameter.Impl as IMgaFCO); result.Add(feedback); } } } var vf = parameter.SrcConnections.ValueFlowCollection.FirstOrDefault(); if (vf != null) { try { int iterDepth = 1; if (HasOccurrencesOfKindInValueFlow(new List<string>() { typeof(CyPhy.Metric).Name }, vf, ref iterDepth)) { string errMsg = string.Format("Parameter {0} is getting a value from a Metric. This is not allowed.", parameter.Name); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = errMsg }; feedback.InvolvedObjectsByRole.Add(parameter.Impl as IMgaFCO); result.Add(feedback); } iterDepth = 0; if (HasOccurrencesOfKindInValueFlow(new List<string>() { typeof(CyPhy.CustomFormula).Name }, vf, ref iterDepth, breakOnProperty: true)) { string warnMsg = string.Format("Parameter {0} is getting a value through a CustomFormula. " + "Only Properties should have such incoming value flows (since they are not generated in the Modelica code). " + "If you try to modify a parameter in the Modelica code you may get unexpected results.", parameter.Name); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = warnMsg }; feedback.InvolvedObjectsByRole.Add(parameter.Impl as IMgaFCO); result.Add(feedback); } } catch (NotFiniteNumberException) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Parameter '{0}' is part of a looped value flow chain. Please break this loop.", parameter.Name) }; feedback.InvolvedObjectsByRole.Add(parameter.Impl as IMgaFCO); result.Add(feedback); } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
private static IEnumerable <RuleFeedbackBase> checkPccDriverChildren(CyPhy.PCCDriver pccDriver) { // This function checks the PCCDriver's parameters: // -Ensure there is 1 connection to a TB for each one // -Ensure their Attributes are valid (max > min, non-zero StdDev, positive values where needed) var checkResults = new List <RuleFeedbackBase>(); //List<string> childNames = new List<string>(); // Get children, check for connections var parameters = pccDriver.Children.PCCParameterCollection; var outputs = pccDriver.Children.PCCOutputCollection; if (parameters.Count() < 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC Driver {0} must have at least 1 Parameter", pccDriver.Name) }; feedback.InvolvedObjectsByRole.Add(pccDriver.Impl as IMgaFCO); checkResults.Add(feedback); } if (outputs.Count() < 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PCC Driver {0} must have at least 1 Output", pccDriver.Name) }; feedback.InvolvedObjectsByRole.Add(pccDriver.Impl as IMgaFCO); checkResults.Add(feedback); } var tbParamsWithConnections = new HashSet <Tuple <ISIS.GME.Common.Interfaces.Reference, ISIS.GME.Common.Interfaces.FCO> >(); // Check for connections and names of parameters in the test-bench. foreach (var param in parameters) { var attributeCheckResults = checkPccParamAttributes(param); if (attributeCheckResults != null && attributeCheckResults.Count() != 0) { checkResults.AddRange(attributeCheckResults); } var driveParamCollection = param.DstConnections.DriveParameterCollection; var problemInputFlowSourceConnection = param.DstConnections.ProblemInputFlowSourceConnectionCollection; if (problemInputFlowSourceConnection.Count() + driveParamCollection.Count() > 0) { foreach (var driveParam in driveParamCollection.Concat <ISIS.GME.Common.Interfaces.Connection>(problemInputFlowSourceConnection)) { var source = driveParam.GenericDstEnd; var tb = driveParam.GenericDstEndRef; if (isValidParamOrOutputName(source.Name) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Connected Parameter ({0}) has an invalid name. " + NAME_EXPLANATION, source.Name) }; feedback.InvolvedObjectsByRole.Add(source.Impl as IMgaFCO); checkResults.Add(feedback); } if (source.Kind == typeof(CyPhy.Parameter).Name) { // FIXME: if source.Kind == ProblemInput, follow where it goes and perform this check var value = CyPhyClasses.Parameter.Cast(source.Impl).Attributes.Value; double dummy; if (value != "" && double.TryParse(value, out dummy) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Connected Parameter {0} has a value, '{1}', that is not real.", source.Name, value) }; feedback.InvolvedObjectsByRole.Add(source.Impl as IMgaFCO); checkResults.Add(feedback); } } if (tbParamsWithConnections.Add( new Tuple <ISIS.GME.Common.Interfaces.Reference, ISIS.GME.Common.Interfaces.FCO>(tb, source)) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Parameter ({0}) must have only 1 connection from a PCCDriverParameter", source.Name) }; feedback.InvolvedObjectsByRole.Add(source.Impl as IMgaFCO); checkResults.Add(feedback); } } } else if (driveParamCollection != null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Driver Parameter ({0}) must have at least 1 connection to a Testbench Parameter/Property", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); checkResults.Add(feedback); } } var tbMetricsWithConnections = new HashSet <Tuple <ISIS.GME.Common.Interfaces.Reference, ISIS.GME.Common.Interfaces.FCO> >(); // Check for connections and names of metrics in the test-bench. foreach (var output in outputs) { var attributeCheckResults = checkPccOutputAttributes(output); if (attributeCheckResults != null && attributeCheckResults.Count() != 0) { checkResults.AddRange(attributeCheckResults); } var pccOutputMappingCollection = output.SrcConnections.PCCOutputMappingCollection; var problemOutputFlowCollection = output.SrcConnections.ProblemOutputFlowTargetConnectionCollection; if (problemOutputFlowCollection.Count() + pccOutputMappingCollection.Count() == 1) { var pccOutputMap = (ISIS.GME.Common.Interfaces.Connection)pccOutputMappingCollection.FirstOrDefault() ?? problemOutputFlowCollection.FirstOrDefault(); var tbMetric = pccOutputMap.GenericSrcEnd; var tb = pccOutputMap.GenericSrcEndRef; if (tbMetric != null) { if (isValidParamOrOutputName(tbMetric.Name) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Connected Metric ({0}) has an invalid name. " + NAME_EXPLANATION, tbMetric.Name) }; feedback.InvolvedObjectsByRole.Add(tbMetric.Impl as IMgaFCO); checkResults.Add(feedback); } if (tbMetricsWithConnections.Add( new Tuple <ISIS.GME.Common.Interfaces.Reference, ISIS.GME.Common.Interfaces.FCO>(tb, tbMetric)) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBench Metric ({0}) must have only 1 connection to a PCCOutput", tbMetric.Name) }; feedback.InvolvedObjectsByRole.Add(tbMetric.Impl as IMgaFCO); checkResults.Add(feedback); } } } else if (problemOutputFlowCollection.Count() + pccOutputMappingCollection.Count() != 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Driver Output ({0}) must have exactly 1 connection from a Testbench Metric or Problem Output.", output.Name) }; feedback.InvolvedObjectsByRole.Add(output.Impl as IMgaFCO); checkResults.Add(feedback); } } return(checkResults); }
public static IEnumerable<RuleFeedbackBase> NamesMustBeValid(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var parentIsComponent = false; if (context.MetaBase.Name == typeof(CyPhy.Component).Name) { parentIsComponent = true; // TODO: Should check for IsDynamicComponent var component = CyPhyClasses.Component.Cast(context); if (component.Children.ModelicaModelCollection.Any() == false) { return result; } } List<string> TBtestCompBaseNames = new List<string>(); // we don't care what type of object it is for certain cases; children should always have unique names List<string> names = new List<string>(); var childFCOs = context.ChildObjects.OfType<MgaFCO>(); foreach (var child in childFCOs) { string childName = child.Name; string childKind = child.Meta.Name; // Only check names for defined Kinds if (NameCheckWhiteList.Contains(childKind) == false) { continue; } // Don't check connectors with no modelica-connectors if (child.Meta.Name == typeof(CyPhy.Connector).Name) { var connector = CyPhyClasses.Connector.Cast(child); if (connector.Children.ModelicaConnectorCollection.Count() == 0) { continue; } } // Don't check names of Properties inside Components if (parentIsComponent) { if (childKind == typeof(CyPhy.Property).Name) { continue; } } if (childName.Length < 1) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} (Kind: {1}) has no name (name length is 0)", child.Name, child.Meta.Name) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } string badCharacters = null; badCharacters = checkForInvalidCharacters(childName); // Check if name is valid if (string.IsNullOrEmpty(badCharacters) == false) { // ModelicaParameters are allowed to have '.' in the name: modifiers such as w.start, length.min bool isParameterWithDots = (child.Meta.Name == typeof(CyPhy.ModelicaParameter).Name && badCharacters == "."); bool isArrayModelicaConnector = child.Meta.Name == typeof(CyPhy.ModelicaConnector).Name && badCharacters == "[]"; if (isParameterWithDots == false && isArrayModelicaConnector == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} has an invalid name; it contains '{1}'", child.Name, badCharacters) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } } // get the list of packages attached from the CyPhy2Modelica form getExternalPackageNames(context); string protectedName = checkForInvalidName(childName); if (protectedName != null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} has an invalid name; {1} is a reserved name", child.Name, protectedName) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } if (childName.Length > 0 && char.IsDigit(childName[0])) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} has an invalid name; names must not begin with a digit", child.Name) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } if (names.Contains(childName)) { var conflictedFcos = childFCOs.Where(x => x.Name == childName); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "'{0}' ({1}) must have a unique name within '{2}' ({3})", childName, conflictedFcos.FirstOrDefault().Meta.Name, context.Name, context.Meta.Name) }; foreach (var fco in conflictedFcos) { feedback.InvolvedObjectsByRole.Add(fco as IMgaFCO); } feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } // TestComponent BaseType names must be unique else if (child is CyPhy.TestComponent) { // assume it has an archetype, because we should not ever encounter a root object when running CyPhy2Modelica... (?) string baseName = child.ArcheType.Name; if (TBtestCompBaseNames.Contains(baseName)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "The basetype of {0} has the same name as sibling TestComponent's basetype. Please change one of them.", child.Name) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } TBtestCompBaseNames.Add(baseName); } else if (child is CyPhy.ComponentAssembly && context is CyPhy.ComponentAssembly) { if (childName == context.Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} has the same name as its parent container; all ComponentAssemblies must have unique names", child.Name) }; feedback.InvolvedObjectsByRole.Add(child); result.Add(feedback); } } names.Add(childName); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable <RuleFeedbackBase> TestBenchRefsWorkflowsAreValid(MgaFCO context) { try { var result = new List <RuleFeedbackBase>(); // no TB null ref var tbRefs = (context as MgaModel) .ChildObjects .OfType <MgaReference>() .Where(x => x.Meta.Name == typeof(CyPhy.TestBenchRef).Name); List <string> tbRefNames = new List <string>(); List <string> tbIDs = new List <string>(); MgaFCO referredSUT = null; foreach (var tbRef in tbRefs) { // Unique names if (tbRefNames.Contains(tbRef.Name)) { var feedbackName = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBenchRef name must be unique: {0} (within {1})", tbRef.Name, context.Name) }; feedbackName.InvolvedObjectsByRole.Add(tbRef as IMgaFCO); result.Add(feedbackName); } else { tbRefNames.Add(tbRef.Name); } // Referred TB is not null if (tbRef.Referred == null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBenchRef cannot be null: {0} (within {1})", tbRef.Name, context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } else { // Can only use each TB once in an SoT if (tbIDs.Contains(tbRef.Referred.ID)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Multiple TestBenchRefs cannot refer to the same TestBench: {0} (within {1})", tbRef.Name, context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } else { tbIDs.Add(tbRef.Referred.ID); } CyPhy.TestBenchType referredTB = CyPhyClasses.TestBenchType.Cast(tbRef.Referred); if (referredTB.Children.TopLevelSystemUnderTestCollection.Count() != 0) { var tlsut = referredTB.Children.TopLevelSystemUnderTestCollection.FirstOrDefault(); if ((tlsut.AllReferred.Impl as MgaFCO) != null) { if (referredSUT == null) { referredSUT = tlsut.AllReferred.Impl as MgaFCO; } else if ((tlsut.AllReferred.Impl as MgaFCO).ID != referredSUT.ID) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("All TestBenches in {0} must use to the same SystemUnderTest", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } } } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBench {0} does not have a SystemUnderTest", tbRef.Name) }; feedback.InvolvedObjectsByRole.Add(tbRef as IMgaFCO); result.Add(feedback); } if (referredTB.Children.WorkflowRefCollection.Any()) { if (referredTB.Children.WorkflowRefCollection.Count() == 1) { // one workflow var workflowRef = referredTB.Children.WorkflowRefCollection.FirstOrDefault(); if (workflowRef.Referred.Workflow != null) { var workflow = workflowRef.Referred.Workflow; if (workflow.Children.TaskCollection.Any()) { // OK? } else { // no tasks var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBench {0} has a workflow with no tasks", tbRef.Name) }; feedback.InvolvedObjectsByRole.Add(tbRef as IMgaFCO); feedback.InvolvedObjectsByRole.Add(workflow.Impl as IMgaFCO); result.Add(feedback); } } else { // workflow ref is null var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBench {0} has a workflow which is a null reference", tbRef.Name) }; feedback.InvolvedObjectsByRole.Add(tbRef as IMgaFCO); feedback.InvolvedObjectsByRole.Add(workflowRef.Impl as IMgaFCO); result.Add(feedback); } } else { // more than one workflow var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBench {0} has more than one workflow element", tbRef.Name) }; feedback.InvolvedObjectsByRole.Add(tbRef as IMgaFCO); result.Add(feedback); } } else { // no workflow var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("TestBench {0} has no workflow element", tbRef.Name) }; feedback.InvolvedObjectsByRole.Add(tbRef as IMgaFCO); result.Add(feedback); } } } return(result); } catch (Exception ex) { var result = new List <RuleFeedbackBase>(); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Context: {0} - Exception: {1} {2}", context.Name, ex.Message, ex.StackTrace) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); return(result); } }
public static IEnumerable<RuleFeedbackBase> ModelicaConnectorHasValidURI(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); string[] splitURI = null; var modelicaConnector = CyPhyClasses.ModelicaConnector.Cast(context); // If the ModelicaConnector is in a Connector, the Class might be empty... if (modelicaConnector.ParentContainer is CyPhy.Connector && string.IsNullOrWhiteSpace(modelicaConnector.Attributes.Class)) { return result; } splitURI = modelicaConnector.Attributes.Class.Split('.'); int pathLength = splitURI.Length; // URI must have at least 2 classes, i.e., AttachedLib.Model, (3 might be better) if (splitURI.Length < 2) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("{0}: 'Class' attribute should refer to a model within the attached package (path is too short or empty)", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } getExternalPackageNames(context); if (externalPackageNames.Contains(splitURI[0]) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("{0}: the first element in the 'Class' attribute should refer to an attached Modelica package", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } string badCharacters = null; foreach (string name in splitURI) { string additionalBadChars = checkForInvalidCharacters(name); if (string.IsNullOrEmpty(additionalBadChars) == false) { badCharacters = badCharacters + additionalBadChars; } if (name.Length > 0 && char.IsDigit(name[0])) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} has an invalid Class; '{1}' must not begin with a digit", context.Name, name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } } if (badCharacters != null && badCharacters != "") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} - Class '{1}' contains invalid characters: '{2}'", context.Name, modelicaConnector.Attributes.Class, badCharacters) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
private static IEnumerable<RuleFeedbackBase> checkModelicaModelURI(GME.MGA.MgaFCO mgaModelicaModel) { var result = new List<RuleFeedbackBase>(); string[] splitURI = null; string modelicaClass = mgaModelicaModel.GetStrAttrByNameDisp("Class"); splitURI = modelicaClass.Split('.'); int pathLength = splitURI.Length; // URI must have at least 2 classes, i.e., AttachedLib.Model, (3 might be better) if (splitURI.Length < 2) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("{0}: 'Class' attribute {1} should refer to a model within the attached package (path is too short or empty)", mgaModelicaModel.Name, modelicaClass) }; feedback.InvolvedObjectsByRole.Add(mgaModelicaModel); result.Add(feedback); return result; } getExternalPackageNames(mgaModelicaModel); if (externalPackageNames.Contains(splitURI[0]) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("{0}: the first element in the 'Class' attribute {1} should refer to an attached package", mgaModelicaModel.Name, modelicaClass) }; feedback.InvolvedObjectsByRole.Add(mgaModelicaModel); result.Add(feedback); return result; } string badCharacters = null; foreach (string name in splitURI) { string additionalBadChars = checkForInvalidCharacters(name); if (string.IsNullOrEmpty(additionalBadChars) == false) { badCharacters = badCharacters + additionalBadChars; } if (name.Length > 0 && char.IsDigit(name[0])) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} has an invalid Class {1}; Classes must not begin with a digit", mgaModelicaModel.Name, modelicaClass) }; feedback.InvolvedObjectsByRole.Add(mgaModelicaModel); result.Add(feedback); return result; } } if (badCharacters != null && badCharacters != "") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format( "{0} - Class field contains invalid characters: {1}", mgaModelicaModel.Name, badCharacters) }; feedback.InvolvedObjectsByRole.Add(mgaModelicaModel); result.Add(feedback); } return result; }
public static IEnumerable<RuleFeedbackBase> ComponentTreeHasValidStructure(MgaFCO context) { try { getExternalPackageNames(context); var result = new List<RuleFeedbackBase>(); CyPhy.RootFolder projectRootFolder = CyPhyClasses.RootFolder.GetRootFolder(context.Project); var invalidChars = checkForInvalidCharacters(projectRootFolder.Name); var reservedName = checkForInvalidName(projectRootFolder.Name); if (string.IsNullOrEmpty(invalidChars) == false || string.IsNullOrEmpty(reservedName) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, }; if (string.IsNullOrEmpty(invalidChars) == false) { feedback.Message = string.Format("The project's RootFolder '{0}' contains invalid characters '{1}'.", projectRootFolder.Name, invalidChars); } else { feedback.Message = string.Format("The project's RootFolder '{0}' has a protected name.", projectRootFolder.Name); } result.Add(feedback); } else { var folderNames = new List<string>(); foreach (var componentsFolder in projectRootFolder.Children.ComponentsCollection) { // Check uniquness of names of components folder in root-folder if (folderNames.Contains(componentsFolder.Name)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The project's RootFolder '{0}' contains component-folders with non-unique names '{1}'.", projectRootFolder.Name, componentsFolder.Name) }; result.Add(feedback); } else { folderNames.Add(componentsFolder.Name); } // Check rules for folders if (FolderFilter.FolderHasModelicaComponents(componentsFolder)) { var folder = new FolderTreeNode(componentsFolder); FolderFilter.PopulateWithFilteredNodes(ref folder); result.AddRange(CheckFolderStructure(folder)); } } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
private static List<RuleFeedbackBase> GetExceptionRuleFeedBack(Exception ex, IMgaFCO context) { var result = new List<RuleFeedbackBase>(); var feedback = new GenericRuleFeedback<Exception>() { AdditionalInfo = ex, FeedbackType = FeedbackTypes.Error, Message = string.Format("Context: {0} - Exception: {1} {2}", context.Name, ex.Message, ex.StackTrace) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); return result; }
public static IEnumerable<RuleFeedbackBase> ConnectorsShouldHaveChildren(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var connector = CyPhyClasses.Connector.Cast(context); var children = connector.AllChildren; if (children.Count() == 0) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Connector has no child objects: {0}", connector.Name) }; feedback.InvolvedObjectsByRole.Add(connector.Impl as IMgaFCO); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ComponentIsDefinedInComponentFolder(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); getExternalPackageNames(context); var component = CyPhyClasses.Component.Cast(context); // TODO: Should check for IsDynamicComponent if (component.Children.ModelicaModelCollection.Any() == false) { return result; } var baseType = Modelica.Extentions.DerivedFrom(component); if (baseType != null) { if (baseType.ParentContainer.Kind != typeof(CyPhy.Components).Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Component {0} is defined in a {1}, please move it to a Component Folder (red).", component.Name, baseType.ParentContainer.Kind) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } (baseType.Impl as MgaFCO).RegistryValue["IsInDesign"] = "1"; //try //{ // TryToCallFormulaEvaluator(baseType.Impl as MgaFCO); //} //catch (Exception ex) //{ // var feedback = new GenericRuleFeedback() // { // FeedbackType = FeedbackTypes.Error, // Message = string.Format("Calling formula evaluator on Component {0} raised an exception. Make sure there are no loops or awkwardnesses in the components value flows. Exception : {0}", // component.Name, ex.ToString()) // }; // feedback.InvolvedObjectsByRole.Add(context); // result.Add(feedback); //} var invalidChars = checkForInvalidCharacters(baseType.Name); var reservedName = checkForInvalidName(baseType.Name); if (string.IsNullOrEmpty(invalidChars) == false || string.IsNullOrEmpty(reservedName) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, }; if (string.IsNullOrEmpty(invalidChars) == false) { feedback.Message = string.Format("The definition of component '{0}' contains invalid characters '{1}'.", baseType.Name, invalidChars); } else { feedback.Message = string.Format("The definition of component '{0}' has a protected name '{1}'.", baseType.Name, baseType.Name); } feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); result.Add(feedback); } if (string.IsNullOrEmpty(baseType.Name)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The definition of component '{0}' has an empty name.", baseType.Name) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); result.Add(feedback); } else if (char.IsDigit(baseType.Name.First())) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The definition of component '{0}' name starts with a digit.", baseType.Name) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); result.Add(feedback); } } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Component {0} is defined in the design, please move it to a Component Folder (red) and add it as a reference instea.", component.Name) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
private static List<RuleFeedbackBase> CheckFolderStructure(FolderTreeNode folder) { var result = new List<RuleFeedbackBase>(); var invalidChars = checkForInvalidCharacters(folder.Name); var reservedName = checkForInvalidName(folder.Name); if (string.IsNullOrEmpty(invalidChars) == false || string.IsNullOrEmpty(reservedName) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, }; if (string.IsNullOrEmpty(invalidChars) == false) { feedback.Message = string.Format("The component folder at '{0}' contains invalid characters '{1}'.", folder.Folder.Path, invalidChars); } else { feedback.Message = string.Format("The component folder at '{0}' has a protected name '{1}'.", folder.Folder.Path, folder.Name); } result.Add(feedback); } if (string.IsNullOrEmpty(folder.Name)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The component folder at '{0}' has an empty name.", folder.Folder.Path) }; result.Add(feedback); } else if (char.IsDigit(folder.Name.First())) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The component folder at '{0}' name starts with a digit.", folder.Folder.Path) }; result.Add(feedback); } var names = folder.Children.Select(c => c.Name).ToList(); var distinctNames = folder.Children.Select(c => c.Name).Distinct(); if (names.Count() != distinctNames.Count()) { foreach (var uniqueName in distinctNames) { if (names.Contains(uniqueName)) { names.Remove(uniqueName); } } var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("The component folder at '{0}' contains components/component-folders with non-unique names: {1}.", folder.Folder.Path, string.Join(", ", names)) }; result.Add(feedback); } foreach (var subFolder in folder.Children.Where(c => c is FolderTreeNode)) { result.AddRange(CheckFolderStructure(subFolder as FolderTreeNode)); } return result; }
public static IEnumerable<RuleFeedbackBase> OneCAInTestBench(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var testBench = CyPhyClasses.TestBench.Cast(context); var compAssmCollection = testBench.Children.ComponentAssemblyCollection; var componentCollection = testBench.Children.ComponentCollection; var TLSUTCollection = testBench.Children.TopLevelSystemUnderTestCollection; var SUTcount = compAssmCollection.Count() + componentCollection.Count() + TLSUTCollection.Count(); if (SUTcount != 1) { var names = testBench.Children.ComponentAssemblyCollection.Select(x => x.Name) .Concat(testBench.Children.ComponentCollection.Select(x => x.Name)); var involvedCompAssemblies = testBench.Children.ComponentAssemblyCollection.Select(x => x.Impl as MgaFCO); var involvedComponents = testBench.Children.ComponentCollection.Select(x => x.Impl as MgaFCO); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Testbench ({0}) must contain only one SystemUnderTest. {1}", context.Name, string.Join(", ", names)) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); feedback.InvolvedObjectsByRole.AddRange(involvedCompAssemblies); feedback.InvolvedObjectsByRole.AddRange(involvedComponents); result.Add(feedback); } else //SUTcount == 1 { if (componentCollection.FirstOrDefault() != null) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("SystemUnderTest ({0}) is a Component; CyPhy2Modelica requires a ComponentAssembly as the SystemUnderTest.", componentCollection.FirstOrDefault().Name) }; feedback.InvolvedObjectsByRole.Add(componentCollection.FirstOrDefault().Impl as MgaFCO); result.Add(feedback); } // if SUT is still 'TLSUT', it is probably a DesignContainer; check else if (TLSUTCollection.FirstOrDefault() != null) { var TLSUT = TLSUTCollection.FirstOrDefault(); var referredKind = TLSUT.AllReferred.Kind; if (referredKind == typeof(CyPhy.DesignContainer).Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("SystemUnderTest ({0}) refers to a DesignContainer; try the MasterInterpreter.", TLSUTCollection.FirstOrDefault().Name) }; feedback.InvolvedObjectsByRole.Add(TLSUTCollection.FirstOrDefault().Impl as IMgaFCO); result.Add(feedback); } else { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("SystemUnderTest ({0}) refers to a {1}; CyPhy2Modelica requires a ComponentAssembly as the SystemUnderTest.", TLSUTCollection.FirstOrDefault().Name, referredKind) }; feedback.InvolvedObjectsByRole.Add(TLSUTCollection.FirstOrDefault().Impl as IMgaFCO); result.Add(feedback); } } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ComponentParametersHaveValues(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); bool checkBasetypeParameters = false; bool isTestBench = false; IEnumerable<CyPhy.Parameter> childParameters = null; IEnumerable<CyPhy.Parameter> basetypeChildParameters = null; if (context.Meta.Name == typeof(CyPhy.Component).Name) { var component = CyPhyClasses.Component.Cast(context); // TODO: Should check for IsDynamicComponent if (component.Children.ModelicaModelCollection.Any() == false) { return result; } childParameters = component.Children.ParameterCollection; if (component.IsInstance) { var basetype = Modelica.Extentions.DerivedFrom(component); if (basetype != null) { checkBasetypeParameters = true; basetypeChildParameters = basetype.Children.ParameterCollection; } } } else if (context.Meta.Name == typeof(CyPhy.TestComponent).Name) { var testComponent = CyPhyClasses.TestComponent.Cast(context); childParameters = testComponent.Children.ParameterCollection; } else if (context.Meta.Name == typeof(CyPhy.ComponentAssembly).Name) { var componentAssembly = CyPhyClasses.ComponentAssembly.Cast(context); childParameters = componentAssembly.Children.ParameterCollection; } else if (context.Meta.Name == typeof(CyPhy.TestBench).Name) { var testBench = CyPhyClasses.TestBench.Cast(context); childParameters = testBench.Children.ParameterCollection; isTestBench = true; } foreach (var param in childParameters) { string value = param.Attributes.Value; if (string.IsNullOrWhiteSpace(value)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Parameter {0} has an empty 'Value' field. Zero, 0, will be used.", param.Name) }; if (isTestBench) { feedback.FeedbackType = FeedbackTypes.Error; feedback.Message = string.Format("Test-bench parameter {0} has an empty 'Value' field.", param.Name); } feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); result.Add(feedback); } } if (checkBasetypeParameters) { foreach (var param in basetypeChildParameters) { string value = param.Attributes.Value; if (value == null || value == "") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Parameter {0} in the tree component has no 'Value'. Zero, 0, will be used.", param.Name) }; feedback.InvolvedObjectsByRole.Add(param.Impl as IMgaFCO); result.Add(feedback); } } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ElaboratorMustNotLeaveRefsInComponentAssembly(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var componentAssembly = CyPhyClasses.ComponentAssembly.Cast(context); if (componentAssembly.Children.ComponentRefCollection.FirstOrDefault() != null) { var names = componentAssembly.Children.ComponentRefCollection.Select(x => x.Name); var involvedObjects = componentAssembly.Children.ComponentRefCollection.Select(x => x.Impl as IMgaFCO); var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Component references not elaborated within {0}: {1}", context.Name, string.Join(", ", names)) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); feedback.InvolvedObjectsByRole.AddRange(involvedObjects); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> PostProcessingPathIsValid(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var postProcessing = CyPhyClasses.PostProcessing.Cast(context); string scriptPath = postProcessing.Attributes.ScriptPath; if (scriptPath == null || scriptPath == "") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PostProcessing block {0} has an empty 'ScriptPath' field", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } else { string projectDir = GetProjectDir(context); string fullPath = System.IO.Path.Combine(projectDir, scriptPath); if (System.IO.File.Exists(fullPath) == false) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PostProcessing block {0} 'ScriptPath' points to a file that does not exist", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } else if (System.IO.Path.GetExtension(fullPath) != ".py") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("PostProcessing block {0} 'ScriptPath' points to a file that is invalid (not *.py)", context.Name) }; feedback.InvolvedObjectsByRole.Add(context as IMgaFCO); result.Add(feedback); } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
public static IEnumerable<RuleFeedbackBase> ComponentAssemblyCannotShareNameWithItsParent(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var componentAssembly = CyPhyClasses.ComponentAssembly.Cast(context); var parent = componentAssembly.ParentContainer; if (parent.Kind == typeof(CyPhy.ComponentAssembly).Name && parent.Name == componentAssembly.Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("ComponentAssemly {0} has the same name as its parent - this is not allowed.", context.Name) }; feedback.InvolvedObjectsByRole.Add(context); result.Add(feedback); } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }
/// <summary> /// Checks if the value is correct. Elaborates name-referenced values, e.g. Transported_Fluid. /// Assumption : A value is classified as a referred name if it does not contain a "." /// </summary> /// <param name="point">ModelicaConnector that containing the redeclare </param> /// <param name="redeclareParameter">Redeclare that will be propagated</param> /// <param name="result">FeedBackErrors/Warnings</param> private static void CheckRulesForRedeclares(CyPhy.ModelicaConnector point, CyPhy.ModelicaRedeclare redeclareParameter, List<RuleFeedbackBase> result) { // Make sure that Value isn't null or white-space if (string.IsNullOrWhiteSpace(redeclareParameter.Attributes.Value) && (point.ParentContainer.Kind == typeof(CyPhy.ModelicaModel).Name || point.ParentContainer.Kind == typeof(CyPhy.CyberModel).Name ) ) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Redeclare {0} {1} has an empty Value.", redeclareParameter.Attributes.ModelicaRedeclareType, redeclareParameter.Name) }; feedback.InvolvedObjectsByRole.Add(redeclareParameter.Impl as IMgaFCO); result.Add(feedback); } else if (redeclareParameter.Attributes.Value.Contains(".") == false) { NameReferenceDepth = 1; // TryToElaborateNamedReferencedRedeclare checks any found value for validity if (point.ParentContainer.Kind == typeof(CyPhy.ModelicaModel).Name) { var startModelicaModel = CyPhyClasses.ModelicaModel.Cast(point.ParentContainer.Impl as MgaFCO); redeclareParameter.Attributes.Value = TryToElaborateNamedReferencedRedeclare(startModelicaModel, redeclareParameter, result); } else if (point.ParentContainer.Kind == typeof(CyPhy.CyberModel).Name) { var startCyberModel = CyPhyClasses.CyberModel.Cast(point.ParentContainer.Impl as MgaFCO); redeclareParameter.Attributes.Value = TryToElaborateNamedReferencedRedeclare(startCyberModel, redeclareParameter, result); } } else if (redeclareParameter.Attributes.Value == "Modelica.Media.Interfaces.PartialMedium" && point.ParentContainer.Kind == typeof(CyPhy.ModelicaModel).Name) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Redeclare {0} {1} has a no specified fluid \"Modelica.Media.Interfaces.PartialMedium\".", redeclareParameter.Attributes.ModelicaRedeclareType, redeclareParameter.Name) }; feedback.InvolvedObjectsByRole.Add(redeclareParameter.Impl as IMgaFCO); result.Add(feedback); } }
public static IEnumerable<RuleFeedbackBase> PropertiesMustNotGetValuesFromParameters(MgaFCO context) { try { var result = new List<RuleFeedbackBase>(); var property = CyPhyClasses.Property.Cast(context); if (property.ParentContainer is CyPhy.Component) { // TODO: Should check for IsDynamicComponent var component = property.ParentContainer as CyPhy.Component; if (component.Children.ModelicaModelCollection.Any() == false) { return result; } } // META-3622 if (property.ParentContainer is CyPhy.ComponentAssembly) { if (String.IsNullOrWhiteSpace(property.Attributes.Dimension) == false && property.Attributes.Dimension.Trim() != "1") { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = "Property has Dimension != 1 - it will not be generated." }; feedback.InvolvedObjectsByRole.Add(property.Impl as IMgaFCO); result.Add(feedback); } } var vf = property.SrcConnections.ValueFlowCollection.FirstOrDefault(); if (vf != null) { try { int iterDepth = 1; if (HasOccurrencesOfKindInValueFlow(new List<string>() { typeof(CyPhy.Metric).Name }, vf, ref iterDepth)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Property {0} is getting a value from a Metric. Please remove connection." + "Metrics are evaluated after the analysis tool has run. ", property.Name) }; feedback.InvolvedObjectsByRole.Add(property.Impl as IMgaFCO); result.Add(feedback); } iterDepth = 1; if (HasOccurrencesOfKindInValueFlow(new List<string>() { typeof(CyPhy.Parameter).Name }, vf, ref iterDepth)) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Warning, Message = string.Format("Property '{0}' is getting a value from a Parameter. If the Parameter is connected up to the TestBench level " + "the Modelica code might not be valid w.r.t the value flow. Use only Parameters to map the value flow into the Modelica code.", property.Name) }; feedback.InvolvedObjectsByRole.Add(property.Impl as IMgaFCO); result.Add(feedback); } } catch (NotFiniteNumberException) { var feedback = new GenericRuleFeedback() { FeedbackType = FeedbackTypes.Error, Message = string.Format("Property '{0}' is part of a looped value flow chain. Please break this loop.", property.Name) }; feedback.InvolvedObjectsByRole.Add(property.Impl as IMgaFCO); result.Add(feedback); } } return result; } catch (Exception ex) { return GetExceptionRuleFeedBack(ex, context); } }