Overview
The form of the ARM classes follows a straightforward pattern. This chapter describes the pattern used for all classes so that you can quickly understand what functions will be available from the ARM model.
Two classes are defined for each ARM concept: an interface class and an implementation class. The name for the interface class has the first letter uppercase, the rest lowercase, and an "_IF" suffix. The name for the implementation class is the same, but without the suffix.
For a position tolerance ARM concept, the classes are:
Position_tolerance_IF --> interface class Position_tolerance --> implementation class
The interface classes reflect the inheritance relationships of the ARM model and are primarily used by code that processes existing data. The inheritance structure allows code to be written at various levels of abstraction. Each interface class defines many pure virtual functions which are implemented by an implementation class subtype.
The implementation class is primarily used by code that creates new data sets using the Arm_class::newInstance() static function. There is no inheritance relationship between two implementation classes, so is either written to a specific implementation class, or a pointer to an interface class is passed to code that works at a higher level of abstraction.
The figure below shows the relationship between the interface and implementation classes. The interface classes contain pure virtual functions and can not be instantiated, but they can be used to write code at varying levels of abstraction within the ARM model. The implementation classes are subtypes of the interface classes and can be instantiated. A pointer to an instance of an implementation class can be cast to a pointer to an interface class, but can not be cast to a pointer of a different type of implementation class.
ARMCursors
The ARMCursor() class can traverse all of the ARM implementation class instances in a design. This operates similar to the RoseCursor class: specify the design using a traverse() function, specify the ARM type using a domain() function, and then loop over the set of instances using the next() function.
This only returns things that exactly match the ARM implementation type. If no type is given, the cursor will return all ARM objects in the file and you can test the type by trying to cast the return value to a specific type.
Example
ARMCursor cur; ARMObject *tmp; cur.traverse(d); cur.domain(Project::type()); while ((tmp = cur.next()) != 0) { Project * p = ARM_CAST(Project,tmp); // something }
The following example traverses all objects and finds those that match a particular interface
ARMCursor cur; ARMObject *tmp; cur.traverse(d); while ((tmp = cur.next()) != 0) { SomeType_IF * arm = tmp-> castToSomeType_IF(); if (arm) { // Responds to SomeType interface, do something } }
Implementation Class Functions
Arm_class::newInstance()
static <Arm_implementation_class> * newInstance( RoseDesign * d ); static <Arm_implementation_class> * newInstance( <stp_aim_class> * root, RoseBoolean populate = ROSE_TRUE );
The newInstance() static functions create a new ARM instance. The first and most commonly used version takes and a RoseDesign will create STEP AIM instances as required.
The second version takes a pointer to an existing AIM instance which becomes the root of a new ARM object. The second parameter determines whether the function changes the AIM data. If true, the function will force fields to certain values. This function wraps the root object, but in order to match all of the properties, you must call populate() afterwards.
Example
The following example creates a new position tolerance ARM object within a design. Afterwards, a typical application will call member functions to assign values to the ARM object's various fields, and then save the design to write out an STEP P21 text file or a STEP P28 XML file.
RoseDesign * d; Position_tolerance * pt = Position_tolerance::newInstance(d);
Arm_class::find()
static <Arm_implementation_class> * find( RoseObject * obj );
The find() static function returns a pointer to an ARM object for a particular STEP AIM instance. If the STEP AIM instance is not the root of a matching ARM object, then the find() function will return null.
Both interface and implementation classes define a find() function. The find() on the implementation class will return a value only when the AIM instance is the root of exactly that type of ARM object. The find() on the interface class will return a value when the AIM instance is the root of the given ARM type or a subtype of it.
Example
The following example shows how the implementation and interface find functions work in various cases. The example assumes an ARM model with two types, a Base object and a Subtype object which inherits from it. The resulting library has defines Base_object, Base_object_IF, Subtype_object, and Subtype_object_IF.
First, we create an instance of each ARM type.
RoseDesign * d; Base_object * arm_base = Base_object::newInstance(d); Subtype_object * arm_sub = Subtype_object::newInstance(d);
Next, we examine what happens when we call the find functions on the root AIM instance of the Base object. We see that both of the find functions for the base return values while neither of the find functions for the Subtype return values.
RoseObject * aim = arm_base -> getRoot(); Base_object * b = Base_object::find(aim); // returns value Base_object_IF * bif = Base_object_IF::find(aim); // returns value Subtype_object * s = Subtype_object::find(aim); // returns NULL Subtype_object_IF * sif = Subtype_object_IF::find(aim); // returns NULL
Finally, we call the find functions on the root AIM instance of the Subtype object. Both find functions for the Subtype return values. The Base_object_IF::find() interface find function returns a value because of the inheritance relation between Base and Subtype. However, since the underlying ARM object is not exactly an instance of Base_object, the Base_object::find() implementation find function returns NULL.
RoseObject * aim = arm_sub -> getRoot(); Base_object * b = Base_object::find(aim); // returns NULL Base_object_IF * bif = Base_object_IF::find(aim); // returns value Subtype_object * s = Subtype_object::find(aim); // returns value Subtype_object_IF * sif = Subtype_object_IF::find(aim); // returns value
See Also
getRoot()
<stp_aim_class> * getRoot();
The getRoot() function returns the main STEP AIM instance of an ARM object. In the mapping tables of an AP, paths through the AIM data are described starting from this instance.
The getRoot() function returns the a pointer using the most specific C++ class type available from the mappings. A similar function called getRootObject() is defined on the interface class, but it returns the pointer as the more general RoseObject base type.
Interface Class Functions
The following functions are generated or otherwise inherited in the interface class for each ARM type.
Arm_class_IF::find()
static <Arm_class_IF> * find( RoseObject * obj );
The find() static function returns a pointer to an ARM object for a particular STEP AIM instance. If the STEP AIM instance is not the root of a matching ARM object, then the find() function will return null.
Both interface and implementation classes define a find() function. The find() on the implementation class will return a value only when the AIM instance is the root of exactly that type of ARM object. The find() on the interface class will return a value when the AIM instance is the root of the given ARM type or a subtype of it.
The documentation for the Arm_class::find() implementation find function has an example of interface and implementation find functions.
See Also
design()
RoseDesign * design();
The design() function returns the RoseDesign object that contains the underlying AIM instances.
display()
void display();
The display() function prints a description of the ARM object on stdout to assist in debugging. This is just a wrapper around the getComment() function.
getAIMObjects()
void getAIMObjects( ListOfRoseObject * all_objs );
The getAIMObjects() function fills a list with all of the STEP AIM instances that are part of a particular ARM object. This is used internally by the garbage collector as well as for some advanced functionality.
getComment()
RoseStringObject getComment();
The getComment() function returns a string description of the contents of the ARM object. The comment is usually multiline with embedded newline characters. The form of the comment depends on the save format of the RoseDesign holding the data. Comments for STEP P21 text files are C-style /* ... */ while comments for STEP XML files are enclosed by <!-- ... -->.
The display() function simply prints this comment to stdout to assist in debugging.
Example
Given a Project application object, print the comment to stdout.
Project_IF * p; puts (p-> getComment());
This would produce something like the following:
<!-- *********************************************** * Application object: PROJECT (id10) * MAIN_WORKPLAN: id10, id11, id12, id27345 * ITS_ID: id10, id13, id14, ['New Project'] * ITS_WORKPIECES [*]: id10, id15, id12803 -->
getModuleName()
const char * getModuleName();
The getModuleName() function returns a string constant describing the type name of the underlying ARM object, in all uppercase.
Example
The following code fragments each print "I am a POSITION_TOLERANCE".
RoseDesign * d; Position_tolerance * pt = Position_tolerance::newInstance(d); printf ("I am a %s\n", pt-> getModuleName()); Position_tolerance_IF * ptif = pt; printf ("I am a %s\n", ptif-> getModuleName());
getRootObject()
RoseObject * getRootObject();
The getRootObject() function returns the main STEP AIM instance of an ARM object. In the mapping tables of an AP, paths through the AIM data are described starting from this instance.
The getRootObject() function returns the pointer as the general RoseObject base type. In order to get the pointer as a more specific C++ class type available, either use the getRoot() function is defined on implementation classes, or ROSE_CAST() the pointer to the appropriate AIM type.
See Also
populate()
void populate(); void populate( RoseBoolean strict );
The populate() function starts from the root AIM instance and attempts to match all of the ARM properties. This function exists mostly for internal use, but can be used to selectively match individual objects.
The populate() function selectively tries to find matching AIM data for just the given ARM object and all of its properties by starting with the AIM instance returned by getRoot() and matching mapping table rules against the AIM data.
The matching algorithm is controlled by the STModule::strict_find flag. If a flag is passed to populate(), it will override the global value.