Skip to main content

Add dynamic constraints during model editing operations

preview released

This function and the API used in this function have been released in advance. We do not guarantee the quality at this time, so if you use it, please use it at your own risk. Also, please note that these specifications are subject to change without notice.

Overview

In addition to the multiplicity and path constraints that come standard with Next Design, you can add your own constraints based on model field values, etc.

Incorporating dynamic constraints requires the following implementation:

  • Implementing the dynamic constraint interface
  • Implementation of dynamic constraint registration process

Implementing the dynamic constraint interface

Implement the interface depending on the type of constraint.

Please refer to each API specification for details.

note
  • It is possible to implement multiple interfaces of the same dynamic constraint. For example, if you want to implement different availability constraints when associating models for each view, define a class for each view and implement IModelReferenceProvider .
  • Dynamic constraints of the same type are applied in the order in which they were registered.
  • If one dynamic constraint implementation returns null, the following dynamic constraint applies: In the absence of the following dynamic constraints, Next Design standard behavior applies.

Implementation of dynamic constraint registration process

Implement the dynamic constraint registration process in the Activate method, which is a public method of the main class that implements IExtention.


Sample: model addition and connector connection restrictions

As a sample of dynamic constraints during model editing operations, we will explain how to add constraints to model addition and connector connection. Below, I will explain from creating a new Visual Studio project to actually incorporating dynamic constraints.

Overall flow

  • Create a new Visual Studio project
  • Implementing the dynamic constraint interface
  • Implementation of dynamic constraint registration process

Public Sample

  • A set of sample source code created by the following procedure is available on GitHub.

    External link: EditingCapabilitySample

Goal Image

Screen capture or GIF animation Screen capture or GIF animation

  • Open the [Advanced driving system software development] project from the Next Design sample project.
  • Constraints are given to models that are currently being worked on (including "TBD" in the name).
    • Disables connector connection when "TBD" is included in the port name of the connection destination.

      • When connecting connectors from [System Functional Structure] in [System Logical Design] to [Functional Structure Diagram], the message "Cannot be associated with TBD" is displayed.
    • If "TBD" is included in the use case name, only "scenario" can be added as a model, and conditions cannot be added.

      • "Condition: Precondition" and "Condition: Postcondition" are not displayed when selecting a use case and adding a model from [Use case] in [System Requirements Development] to [Usecase Diagram].

Create a new Visual Studio project

Create a new Visual Studio project by referring to the following page.

Tutorials > Model Batch Verification

In addition, when adding dynamic constraints during model editing operations, the following definitions are not required in the manifest.

  • UI extension point definitions (ribbon tabs, groups, buttons)
  • command extension point definition

Implementation example

manifest.json

{
"name": "DensoCreate.NextDesign.Extensions.EditingCapabilitySample",
"version": "1.0.0",
"publisher": "DENSO CREATE Inc.",
"license": "According to the Next Design License Agreement. Copyright (C) 2021 DENSO CREATE INC. All rights reserved.",

"main": "EditingCapabilitySample.dll", //Specify the build result DLL file name as the entry point.
"lifecycle": "project", //Specify the project lifecycle as the lifecycle.
"baseprofile": "In-vehicle system software development" //Specify the profile name as a condition for the target project.
}

Implementing the Dynamic Constraint Interface

Add a class that implements a dynamic constraint and implement the following interfaces according to the type of constraint.

The class below implements the interface.

  • ModelReferenceProvider: Possibility restrictions when associating an editor model
  • ModelCreationProvider: Candidate constraints for entity types during model creation

Implementation example

Implement IModelReferenceProvider to restrict connections to models with TBD in their name.

ModelReferenceProvider.cs

using System.Linq;
using NextDesign.Core;
using NextDesign.Core.EditingCapabilities;
using NextDesign.Desktop;

namespace Editing Capability
{
///<summary>
///A provider that customizes the model's association functionality
///</summary>
public class ModelReferenceProvider : IModelReferenceProvider
{
///<summary>
///Context.
///</summary>
private IContext m_Context;

#region construction/destruction

///<summary>
///Constructor.
///</summary>
///<param name="context">context</param>
public ModelReferenceProvider(IContext context)
{
m_Context = context;
}

#endregion

///<summary>
///Get the selection candidates when referencing the model
///</summary>
///<param name="referableParams">Parameters for determining selection candidates</param>
///<returns>Suggestion results</returns>
public ModelReferableResult GetReferences(ModelReferableParams referableParams)
{
var model = referableParams.Model;
var modelMetaClass = model.Metaclass;
var field = referableParams.Field;

//narrow down the connection destination port candidates
if (!IsPort(modelMetaClass))
{
//No need to judge anything other than the port
return null;
}

if (field.Name != "ToPorts")
{
//No need to judge anything other than the connection destination port
return null;
}

var result = CapabilityResults.Ignore;
var models = Enumerable.Empty<IModel>();

if (IsInputPort(modelMetaClass))
{
//if itself is an input port,
//Candidate the input port of the child component of its own parent (component) that does not contain TBD in the name
result = CapabilityResults.Success;
var metamodels = m_Context.App.Workspace.CurrentProject.Profile.Metamodels;
var subSystems = model.Owner.GetChildren().Where(c => c.Metaclass.IsClassOf(metamodels.GetClass("SubSystem")));
var inputPorts = subSystems.SelectMany(s => s.GetChildren().Where(c => (
IsInputPort(c.Metaclass)
&& (!c.Name.Contains("TBD"))
)));
models = inputPorts;
}
else if (IsOutputPort(modelMetaClass))
{
//if self is an output port,
//The input port and the child component (function only) of its own parent (component)
//Candidate the output port of the parent (component) of its own parent (component) that does not contain TBD in the name
result = CapabilityResults.Success;
var metamodels = m_Context.App.Workspace.CurrentProject.Profile.Metamodels;
var subSystems = model.Owner.Owner.GetChildren().Where(c => c.Metaclass.IsClassOf(metamodels.GetClass("SubSystem"))).ToList();
var inputPorts = subSystems.SelectMany(s => s.GetChildren().Where(c => (
IsInputPort(c.Metaclass)
&& (!c.Name.Contains("TBD"))
)));
var outputPorts = model.Owner.Owner.GetChildren().Where(c => (
IsOutputPort(c.Metaclass)
&& (!c.Name.Contains("TBD"))
));
models = inputPorts.Union(outputPorts);
}

var referenceResult = new ModelReferableResult
{
Result = result,
Models = models
};
return referenceResult;
}

///<summary>
///Determine whether model association is possible
///</summary>
///<param name="relateParams">Parameters for deciding whether to associate</param>
///<returns>Relationship result</returns>
public ModelRelateResult CanRelate(ModelRelateParams relateParams)
{
var model = relateParams.Model;
var opposite = relateParams.OppositeModel;
var modelMetaClass = model.Metaclass;
var oppositeMetaClass = opposite.Metaclass;

if (!IsPort(modelMetaClass) || !IsPort(oppositeMetaClass))
{
//Return null to keep Next Design standard except ports
return null;
}

var result = CapabilityResults.Ignore;
var canRelate = false;
string guideText = null;
//Restrict connections with ports that include "TBD" in their name.
if (opposite.Name.Contains("TBD"))
{
result = CapabilityResults.Success;
canRelate = false;
guideText = "Cannot be associated with TBD";
}
else
{
//Returns null to keep the Next Design standard pass/fail judgment except for TBD.
return null;
}
var relateResult = new ModelRelateResult
{
Result = result,
CanRelate = canRelate,
GuideText = guideText
};

return relateResult;
}

///<summary>
///Determine if the target class is a port
///</summary>
///<param name="targetClass">target class</param>
///<returns>true if port</returns>
private bool IsPort(IClass targetClass)
{
var metamodels = m_Context.App.Workspace.CurrentProject.Profile.Metamodels;
IClass systemStructurePortBase = metamodels.GetClass("SystemStructurePortBase");

return targetClass.IsClassOf(systemStructurePortBase);
}

///<summary>
///Determine if the target class is an input port
///</summary>
///<param name="targetClass">target class</param>
///<returns>true if port</returns>
private bool IsInputPort(IClass targetClass)
{
var metamodels = m_Context.App.Workspace.CurrentProject.Profile.Metamodels;
IClass inputPort = metamodels.GetClass("FunctionFlowInputPortInnerSystem");

return targetClass.IsClassOf(inputPort);
}

///<summary>
///Determine if the target class is an output port
///</summary>
///<param name="targetClass">target class</param>
///<returns>true if port</returns>
private bool IsOutputPort(IClass targetClass)
{
var metamodels = m_Context.App.Workspace.CurrentProject.Profile.Metamodels;
IClass outputPort = metamodels.GetClass("FunctionFlowOutputPortInnerSystem");

return targetClass.IsClassOf(outputPort);
}
}
}

Implement IModelCreationProvider to limit the models you add to use cases that contain TBD in their names.

ModelCreationProvider.cs

using System;
using System.Collections.Generic;
using System.Text;
using NextDesign.Core;
using NextDesign.Core.EditingCapabilities;
using NextDesign.Desktop;
using System.Linq;

namespace Editing Capability
{
class ModelCreationProvider : IModelCreationProvider
{
public ModelCreatableResult GetCreatableClasses(ModelCreatableParams creatableParams)
{
//Return null for non-use cases and leave it to the Next Design standard
var metaClass = creatableParams.Owner.Metaclass;
var metamodels = creatableParams.Project.Profile.Metamodels;
IClass requirementClass = metamodels.GetClass("UseCase");
if (requirementClass != null)
{
if (!metaClass.IsClassOf(requirementClass))
{
return null;
}
}
//Use cases without "TBD" in the name will return null as there are no special restrictions
if (!creatableParams.Owner.Name.Contains("TBD"))
{
return null;
}

//For use cases with "TBD" in the name, create a rule that only creates a scenario without any conditions
var creatableResult = new ModelCreatableResult
{
Result = CapabilityResults.Success
};

//Since there are default display candidates in DefaultTypes, only the necessary ones are stuffed into the return value
foreach (var type in creatableParams.DefaultTypes)
{
//Add only the other conditions because it is not necessary to create conditions
if (!type.Value.First().Name.Contains("Condition"))
{
creatableResult.AddCreatableClasses(type.Key.Name, type.Value);
}
}

return creatableResult;
}
}
}

Implementation of dynamic constraint registration process

Implement the dynamic constraint registration process in the Activate method, which is a public method of the main class that implements IExtention. No unregistration is required in the public method Deactviate of the main class.

Implementation example

Implements model addition and registration of connector connections.

EditingCapabilityEntryPoint.cs

using NextDesign.Core;
using NextDesign.Desktop;
using NextDesign.Extension;

namespace Editing Capability
{
///<summary>
///Extension entry point for dynamic constraints during model editing operations
///</summary>
public class EditingCapabilityEntryPoint : IExtension
{
///<summary>
///activate the extension
///</summary>
///<param name="context">execution context</param>
public void Activate(IContext context)
{
//Register dynamic constraints.
var registry = context.App.Workspace.CurrentProject.EditingCapabilityProviderRegistry;
registry.Register(new ModelReferenceProvider(context));
registry.Register(new ModelCreationProvider());
}

///<summary>
///deactivate the extension
///</summary>
///<param name="context">execution context</param>
public void Deactivate(IContext context)
{
//No constraint release required.
}
}
}