Adding New Modeled ClassAll modeled classes will be defined in Models section of ModelConfiguration.xml file. If there are relations for that modeled class to be defined, then Relations section should also be updated. For a new modeled class, following needs to be defined:
In order to make the modifications effective, first generate the model and then restart the application. Extending A Modeled ClassAdding New PropertiesEach property for a modeled class is to be defined in the Property subsection within the appropriate Model/Properties section of a modeled class to which the property belongs. Property section supports the following attributes :
Federated Properties
In Datasources section of Model, datasources which will be used in federation are defined. Each datasource has Definition, Name, NameProperty attributes and a set of Key nested tags which specify the key properties for that datasource to uniquely identify the object while retrieving the federated property value.
<RsModel>
<Models>
<Model Name="RsEvent" StorageType="FileAndMemory">
<Properties>
<Property Name='name' Type='string' IsKey="true"/>
<Property Name='creationClassName' Type='string' DatasourceProperty="dsDefinition" NameInDatasource="CreationClassName"/>
<Property Name='severity' Type='number' Datasource="ds1" NameInDatasource="Severity" Default="5"/>
<Property Name='rsDatasource' Type='string'/>
<Property Name='dsDefinition' Type='string'/>
</Properties>
<Datasources>
<Datasource Definition="ds1" Name="sam1">
<Keys>
<Key Name="name" NameInDatasource="Name"></Key>
</Keys>
</Datasource>
<Datasource Definition="ds2" NameProperty="rsDatasource">
<Keys>
<Key Name="name" NameInDatasource="Name"></Key>
<Key Name="creationClassName" NameInDatasource="CreationClassName"></Key>
</Keys>
</Datasource>
</Datasources>
</Model>
</Models>
</RsModel>
Notes
def event = RsEvent.get(name:"event1"); //assume that when accessing severity property a connection exception occurs, the default value of the severity will be returned assert event.severity == 5 //after accessing federated property users can use hasErrors method to check that any errors occurred assert event.hasErrors() == true assert event.hasErrors("severity") == true
In order to make the modifications effective, first generate the model and then restart the application. Adding New RelationsRelations between Models will be defined in the Relations tag. Each Relation tag should provide the following attributes:
<RsModel>
<Model Name="RsSmartsObject">
<Properties>
<Property Name='name' Type='string' IsKey="true"/>
</Properties>
</Model>
<Model Name="RsEvent" StorageType="FileAndMemory">
<Properties>
<Property Name='name' Type='string' IsKey="true"/>
<Property Name='creationClassName' Type='string' />
<Property Name='severity' Type='number' Datasource="sam1" NameInDatasource="Severity"/>
</Properties>
<Datasources>
<Datasource Name="sam1">
<Keys>
<Key Name="name" NameInDatasource="Name"></Key>
</Keys>
</Datasource>
</Datasources>
</Model>
</Models>
<Relations>
<Relation From ="RsSmartsObject" To="RsEvent" Name="events" ReverseName="device" Type="OneToMany" ></Relation>
</Relations>
</RsModel>
In order to make the modifications effective, first generate the model and then reload the application. Removing Properties, Relations, or Modeled ClassesRemoving is as easy as deleting the related lines that define property/relation/model from the ModelConfiguration.xml file.
In order to make the modifications effective, first generate the model and then restart the application. Activating Modeling ChangesGenerating ModelsAfter making the necessary changes to the ModelConfiguration.xml, new modeled classes must be generated. Go to the Scripts tab in the admin UI and run modelCreator script. After the script is executed successfully, new domain classes will have been generated in the temporary location: RS_HOME/RapidSuite/generatedModels/grails-app/domain. Application has to be restarted to finalize the deployment. Restarting ApplicationIn order to generate rest of the modeling artifacts (model operations) and correcting the data according to the model changes, the application must be restarted. These artifacts are groovy files generated under RS_HOME/RapidSuite/operations folder. Model OperationsImplementing Model OperationsDuring model generation, some operations including basic CRUD operations are automatically generated. You can learn more about these basic operations here. If model requires additional operations, they have to be manually implemented in a separate groovy script. Static operations are supported. After the model generation, another file named <ModelName>Operations.groovy is saved under RS_HOME/RapidSuite/operations folder. This file can be edited to have the additional operations required for the model. For example, a sample operation for a Ticket model could be: def assign(username){
owner = username;
writeToJournal("Ticket is assigned to $owner");
}
Note that if there is a modification to the operations file, the model operation file has to be reloaded. Refer to Reload Model Operations section. Description AnnotationDescriptions for the operations can be supplied by using Description annotation. These descriptions will be displayed in the Repository Browser along with the browsed instance's properties and relations. import com.ifountain.annotations.*; class RsEventOperations { ... @Description("This is the description for this operation") String operations1() { ... } @Description(""" <span><b>Users can define html description for operations by using Description tag</b></span> """) def operations2(String param1){ ... } } onLoadA special onLoad method can be defined in the operations file. onLoad will be executed to initialize the model instance when it is retrieved from the repository through the get operation or search. Following example shows the onLoad method for HypericDatasourceOperations: def onLoad(){
this.adapter = new HypericAdapter(getProperty("connection").name, reconnectInterval*1000, Logger.getRootLogger());
}
Actions Before and After Repository UpdatesAdd, delete, and update operations can be intercepted and actions can be executed just before or right after these operations. In order to enable these, one or more of the following operations must be implemented in the operations file for the corresponding modeled class:
beforeInsert, beforeUpdate, and beforeDelete operations are called before the object is actually added, updated, or deleted. Validation is performed after the before operations and there is always the possibility that the operation may fail. Before operations are good places to filter the properties of the object being added/updated. Since the operation is not yet finished successfully, other instances of any class should not be updated in before methods. beforeDelete is not used in processors since property filtering on an object does not make much sense. Sample usage : InMaintenanceCalculator changes the event property inMaintenance if there is a related device which is in maintenance : class InMaintenanceCalculator {
static def eventInBeforeInsert(event){
def inMaintenance=RsInMaintenance.isEventInMaintenance(event);
event.setProperty("inMaintenance",inMaintenance);
}
...
}
afterInsert/afterUpdate/afterDelete operations are called after the add / update / delete operations are successfully completed. After operations are good places to update other objects. The object which is processed should not be updated in after operations ( may cause recursion and performance decrease). setPropertyWithoutUpdate is also not effective since the object is already inserted / added. Sample usage: State calculator changes the related devices state after an event is added class StateCalculator {
...
static def eventIsAdded(event){
def objects=getObjectsOfEvent(event);
objects.each{ object ->
setObjectState(object,event.severity,Constants.NOTSET);
}
}
...
}
Accessing the Current User in OperationsYou may want to process the current user (who has triggered the invocation) in your operations. In order to access the user in the current execution context, use RsUser.getCurrentUserName(): static def record(String param, value) { def t = Date.now() def user = auth.RsUser.getCurrentUserName() Statistics.add([timestamp: t, user: user, parameter: param, value: value]) } if operation is invoked from a gsp, controller or a user invoked script, such as an on-demand script, the current user will be returned. However, some actions are triggered not by any particular user but by the system, such as the execution of a scheduled script. In this case "system" will be returned as the current user. Logging from OperationsSee Writing Log Messages From Model Operation Scripts. Reloading Model OperationsThere are several ways to reload the changes in an operation file:
Views and ControllersViews and controllers are used to manage the Web UI for modeled classes. By implementing the methods in controllers, you can define the operations on a modeled class that can be called from Web UI. list, show, add, update, and delete methods, along with any other method required can be implemented in the model's controller file depending on your needs. Using views, it is possible to set which properties to be displayed and how, in certain UI pages for the model. You can create views for those methods you implement in the model's controller. The views are located in RS_HOME/RapidSuite/grails-app/views folder under individual folders with model names whereas all model controller files are in RS_HOME/RapidSuite/grails-app/controllers folder. When you modify the views or controllers, you need to reload them for the changes to be effective. |
Add Comment