Search results:

    MetaEdit+ Modeler

    MetaEdit+ Workbench


    Are there any reverse engineering features?

    Explanation:Can I take my existing Delphi / C++ / whatever code, and read it in to create graphical models? Maybe if I could then I could generate documentation, or code in different language...
     
    Solution:

    Yes, but not out of the box. Since we can have any modelling language, and generation of any kind of code, there's no possibility for built-in reverse engineering. This is a metaCASE tool, not a fixed-method CASE tool, so we have lots of flexibility in general, but some things can't be hard-coded anymore.

    MetaEdit+ has an API, XML import, and text file reading and parsing capabilities in the MERL generator language. Users can thus use any of these to write their own reverse engineering. The UML Examples project contains an example graph using a MERL generator for simple Java reverse engineering.

    However, this is not something we envisage our customers doing much, especially not round-trip engineering. The benefit of MetaEdit+ is the ability to build your own modeling language and code / documentation generation, so generated code and documentation are never edited - all changes are made to the models, and the code or documentation is regenerated as needed.

    See also the question on model-to-model transformations.


     


    Common errors

    Affects:Versions before 4.0
     
    Solution:Below are described some common error messages, the text they write as the first line to the meplus?.err file, their probable meaning, cause, and what you should do.

    Error: Message not understood: #frameworkToModelTransform:

    This occurs occasionally while closing a Diagram editor, and is harmless: close the error with the Terminate button. Service Release 1 corrects this.

    Error: Message not understood: #XXX, an UndefinedObject>>doesNotUnderstand:

    Where the message is something other than #frameworkToModelTransform: this error normally indicates some variable not being initialized because of a previous error (for which Terminate was pressed). Sometimes shutting the offending window and reopening it will suffice: if not, it is best to logout and abandon the transaction.

    Error: Message not understood: #XXX, an ABUndefinedObject(Object)>>doesNotUnderstand:

    An object has not been able to be found in the database, and is now represented as an ABUndefinedObject. You should logout with abandon. If the same error occurs next time you log in and access the same object (perform the same operation), your database is probably in a bad state. This error can occasionally occur transiently when abandoning complicated metamodelling operations: normally it goes away then if you proceed as above.

    Error: Message not understood: #XXX, 'SomePersistentObject'>>doesNotUnderstand:

    Where the object is not an UndefinedObject, but instead some persistent object (Graph_*, Property_*, Object_*, Relationship_*, Role_*; GraphRepr, ObjectRepr, RelRepr, RoleRepr; SetM) this is often a serious error. If there has been a previous error, shutting the offending window and reopening it may suffice. If not, the error is probably serious, and you should logout and abandon the transaction. Make a backup of your database files. On your next login, try and access the same object again: if the error does not reoccur, the database is probably OK. If the error reoccurs, exit, restore the backup, and try full database recovery. If that does not help, return to an earlier backup.

    Error: Strings only store Characters

    This normally indicates that a type exists in two different areas in the repository, i.e. it has been imported as part of a type or model patch at a time when the area where it already existed was not open. The offending type is visible about 8 lines down the error trace, where a subclass of TargetLevel class is being sent the userPrintOn: message, i.e. the name of the type was being accessed (e.g. to display in an Object Tool or Types Browser): Role_From_sysadmin_3043295427(TargetLevel class)>>userPrintOn:

    Sometimes it is possible to cure the problem by logging in as sysadmin and opening an Area Browser on the area where the type was mistakenly imported. Open the open script. Note that normally there are several such types: fortunately often it is clear that that area should contain no types at all. Delete the types from the open script, and similarly from the close script, and then logout committing changes.

    Error: Accessing unaccessible physical area:

    The ArtBASE area has been deleted or is otherwise unavailable. The number after the message is the number of that area, and you can find the name of the area on the basis of the number from the manager.ab file for that database. Most often, this results because a user deletes an area in the mistaken belief that no object in another area references an object in that area: for this reason we do not recommend ever deleting areas.

    Server error on startup: an ABServerMonitor>>serverPasswordCheck

    This is the error you get if the path in artbase.roo is wrong: correct the path and try again.

     


    How do I use an external text editor in Mac OS X

    Explanation:The default external editor command line for Mac OS X in MetaEdit+ 5.0 and earlier is textedit.app %1, but this no longer works in current versions of Mac OS X.
     
    Affects:Mac OS X, MetaEdit+ 5.0 and earlier
     
    Solution:Change Options... | editor command to: open -W -n -t "%1". This will cause it to use your default text editor, initially TextEdit. After editing the text, press Apple+S to save and Apple+Q to quit TextEdit. Note that you need to quit the whole TextEdit application; just closing the window leaves the TextEdit application open in the dock, and MetaEdit+ does not know that the editing has finished. The full semantics of the parameters for the OS X open command are described in the open man page.
     


    Icons on the types toolbar are cut off on HiDPI Retina screens

    Explanation:Icons on the types toolbar seem to be drawn with double size, so all but the top left corner is cut off. More may be cut off by the icon mask, which is the normal size. Also, rounded corners on scrollbars and buttons are displayed incorrectly.
     
    Affects:Mac OS X on Retina / HiDPI screen
     
    Solution:OS X tries to intelligently scale up all drawing calls when on a Retina screen (or manually selecting a scaling HiDPI resolution). This works correctly for most drawing, and symbols and texts benefit from the higher resolution. Unfortunately, for type icons, scrollbar thumbs and button corners the scaling is done twice, resulting in only a double-scale rendering of the top-left corner being visible.

    You can make OS X use a simpler but more reliable "Low Resolution" algorithm on MetaEdit+ to get essentially the same display as on a non-Retina screen. Rather than setting that for the MetaEdit+ 5.1 Workbench application as normal, you need to set it on the sub-application within the main application package:

    1. Quit MetaEdit+ if it is currently open.
    2. In the Finder, choose Applications from the Go menu.
    3. Ctrl-click the MetaEdit+ 5.1 Workbench icon and select "Open Package Contents" from the pop-up menu.
    4. Open Contents then Resources and click the "MetaEdit+ 5.1" icon so it is highlighted.
    5. Choose Get Info from the File menu.
    6. Place a checkmark next to "Open in Low Resolution" to enable Low Resolution mode.
    7. Close Get Info and use Back to return from the package contents to the main Applications list.
    8. Double click MetaEdit+ 5.1 Workbench to reopen it.

    OS X will then scale up the MetaEdit+ windows so they are physically big enough on the screen, but without the rendering problems. On the higher resolution Retina screen this looks slightly blurred, particularly in contrast to the higher resolution of the rest of the desktop, but overall is generally the better choice.


     


    Is it possible to make a report which shows a list of objects and those graphs/projects where these objects are used

    Solution:MetaEdit+'s Info Tool shows the situation for only a single object at a time, and has no printing functionality.

    The reporting language is designed for a top-down approach, and as such cannot directly produce such a report. Such reports are however easy to implement using the reporting language together with an external tool, e.g. Excel.

    Make a report which goes through each graph and reports each object one per line, with its graph. If an object is in several graphs, there will be a line for that object in each graph. Excel can then correlate these lines to make a single line, showing that object and the graphs it is in.

    1. Create a new report for Graph:
    2. In a Graph Browser, select a graph and choose Reports | Create from its popup menu. In the Report Browser: Graph | Change Graph Type... (choose 'Graph'). Report | New... (give name 'Object-Graph List'). Fill in the body of the report (please note, in line 4 there should be one tab inside each pair of single quotes, '    '):
      Report 'Object-Graph List'
      filename; 'tmp.txt'; append;
      foreach .()
      { oid; ' '; id; ' '; type; ' '; oid;1; ' '; id;1; ' '; type;1; newline;
      }
      close;
      endreport
    3. Save the report: Report | Save
    4. Run the report on all graphs in currently opened projects: Report | Run... (choose all graphs). You'll need to press Enter once for each graph during the report run.
    5. Open the generated file (tmp.txt) with Excel. Each row of the file includes the object's oid, name, type and after that the graph's oid, name and type, all separated with tabs. A wizard opens for converting the tab-separated file to Excel format:
    1. Press Next>
    2. Choose text Qualifier {none}
    3. Press Finish
    4. Select the first row label with the right mouse button, and choose Insert
    5. Fill in the first row with labels for each column: oid, object, objectType, gid, graph, graphType
    6. Ctrl-End (goes to the last cell)
    7. Shift-Ctrl-Home (selects all the data)
    8. Data | PivotTable report
    9. Next>
    10. Next>
    11. Drag each field in turn to the ROW area, keeping them in the same order
    12. Drag the gid field from the right to the DATA area.
    13. Double click the oid field on the left
    14. set its 'Subtotals' radio button to none
    15. Press the Advanced... button
    16. set the AutoSort options to Descending, Using field 'Count of gid'
      OK
      OK
    17. In the same way, set the Subtotals radio button to none for each of the other fields on the left.

    18. Next>
    19. Press Options...

      turn off Grand totals for rows and columns
      turn off 'Enable drilldown'
      OK

    20. Finish

    At the top of the pivot table are those objects that are reused most frequently.

    You can scale the oid, gid and Total columns to be thin, or hide them completely. You can now save the file as an Excel document; remember to delete the tmp.txt file after closing Excel, as the report would otherwise append to the tmp.txt file each time it is run (necessary to report on many graphs to a single file).

    Try it! Example of Object usage report (size 62976 bytes, in Excel97 format)


     


    When I do the Tutorial, the dialog box is empty for "Pick the conceptual graph type to create"

    Explanation:I am at the stage in the Tutorial where you click on editor | Table Editor. according to the tutorial you should get a dialog box with the heading 'Pick the conceptual graph type to create', and that box should have a list of types from which you select Class Diagram [UML]. The Dialog box is empty, why?
     
    Affects:Versions before 4.0
     
    Solution:You have probably not selected any method while logging in. MetaEdit+ expects that you choose the method (like UML) before making any models.

    Please read the Evaluation manual's section 'Choosing method' (Manuals\meplus\Mp-6_3.html) and proceed as described there, i.e. 1) Select ‘UML’ from the list of projects and press OK.

    Please note that if you ignore or make other selections than those proposed in the tutorial, the situation in later steps will probably be different from what is described in the tutorial.
     


    Can previously defined symbols be reused when defining a new domain specific language (to create symbol libraries)?

    Solution:Yes, they can: you can use the Symbol Library from the Symbol editor. In addition to the Symbol Library, you can also copy and paste symbols or symbol elements from one object's symbol to another. Furthermore, you can import existing symbols from outside MetaEdit+ as bitmaps or SVG vector graphics into the Symbol Editor.

    You can of course also reuse the modelling concepts themselves and their generators.
     


    Does MetaEdit+ use OCL constraints for the models or is there something similar?

    Explanation:OCL is a programming language intended to express correctness constraints on models. The OMG also envisages that it could be used to express correctness constraints on metamodels.
     
    Solution:

    In MetaEdit+ constraints are expressed as data and integrated in the metamodel. Compared to OCL this capability simplifies metamodel creation, and avoids the performance problems associated with OCL.

    Having a programming language to express something is natural when the range of possible constraints is unknown. MetaCase's experience over the last 15 years has shown that the actual useful set of constraints needed for modeling languages is rather small. The constraints can be better expressed using a set of constraint templates which can be parameterized with the desired values.

    In MetaEdit+ places to specify constraints include:

    • bindings: how metamodel elements (objects, relationships, roles, ports) can be connected, e.g. a Transition relationship has a From role connected to a State or Start State, and a To role connected to a State or Stop State.
    • cardinality constraints: how many instances of roles are allowed in n-ary relationships, e.g. in single inheritance, an Inheritance relationship can have many Subclasses but only one Superclass.
    • connectivity constraints: how many times a given object can be connected in specified types of relationships and roles, e.g. a Start State can only have one Transition leaving it.
    • port constraints: what ports can be connected, e.g. an "Out" port can only be connected to an "In" port
    • occurrence constraints: how many objects of a certain type may there be in a graph, e.g. only one "Start State" in a State Transition Diagram (4.5 and later).
    • uniqueness constraints: prevent two objects in a graph having the same name, e.g. two States both called "Editing" (4.5 and later).
    • explosions and decompositions: how models can be linked with submodels, e.g. a State in a State Transition Diagram can be decomposed into its own State Transition Diagram.
    • global uniqueness: a given property of an object must have unique values over all instances of that object, e.g. in a UML Object Diagram, the Object Name of each Object might be unique, but the Class Name property would not be: there could be several Objects of the same Class.
    • property value constraints: the set of legal values of a property can be expressed in a variety of ways, e.g. a selection from a list or by checking against a regular expression (4.5 and later).

    The above constraints are checked at modeling time. So once a model element is created, changed or updated the model check is made immediately. In MetaEdit+ it is also possibility to have model correctness checking that is executed on request by running a model check. These can be defined using MetaEdit+'s reporting language or by using external programs (e.g. metrics tools etc) that access desgin models using the MetaEdit+ API.


     


    How is the code-generation linked to MetaEdit+?

    Explanation:How does the generator know about the metamodel and metamodel modifications?
     
    Solution:

    There are three possibilities for code generation:

    1. MetaEdit+ provides its own code generator definition tool, the Generator editor, for making code generators based on any metamodel and for generating any programming language. This tool is directly integrated with the metamodel you made with MetaEdit+.
    2. You can integrate your own generator or a 3rd party generator with MetaEdit+ by using the MetaEdit+ API. With the API, any program having .NET/Webservices/SOAP framework can read the model information from MetaEdit+.
    3. The MetaEdit+ API product also includes the ability to export the models as XML. You could parse that XML and write whatever code generator you like based on it

    In most cases the easiest way is to use the integrated Generator Editor. Often this can be made even easier by writing a thin layer of code on top of your existing components, to make the task of generation easier. This has the added benefit of making the generator less dependent on a particular version of the libraries and components you use.


     


    Is it possible to generate output in another, probably lower level Domain-Specific Modeling Language, also built in MetaEdit+?

    Explanation:We've wondered about the possibility to create a layered set of DSLs.
     
    Solution:

    Yes. You could perform such a model-to-model transformation in one of at least three ways:

    1. by generating the desired XML with a report, then reading that in to create the lower-level models
    2. by exporting XML from Graph Manager, or some other text format with a report, and manipulating that in an external program to create XML to import
    3. by exporting XML or text, and reading that into an external program that makes calls back into MetaEdit+ via the API to create the lower-level models.

    However, experience with this approach, whatever tool is involved and whatever export/transform/import method is used, shows this is normally a Bad Thing. Without knowing your exact plans, I won't say that your idea is bad, but let me state several ways in which people have "gone wrong" along a path like this.

    1. Normally the idea is that each piece of data in the high-level language gets transformed to >1 piece of data in the low-level language (let's say 2 pieces). This is fine if you never (or rarely) look at the low-level language, and never (or very rarely) edit it. But if you edit it, you are now working with 2 pieces of data, but clearly they are not totally independent, since they could be produced from one piece. The idea of DSM is to come up with a minimal sufficient representation of systems, and this is the main reason for its 5-10x productivity increases: code or UML-based ways of building systems involve lots of duplication - the same information in several places.
    2. Often people say next "and we want to be able to change the high-level models still, and have those changes reflected in the low level models". That means you are working with 1+2 pieces of information, and also that you need to come up with some way to propagate the changes down to the low-level models "correctly". "Correctly" here means: without destroying information manually added there; updating the automatically generated parts; creating new generated parts; updating manually added parts to reflect changes in the top-level models (e.g. if the manually added part refers to the name of an element originally from the high level model, and that element's name has now been changed).
    3. And next people say "and we want to be able to change the low-level models, and have the high-level models update". This is even harder than 2). The only cases when it can really happen are where you don't really have a high level and low level, but two different representations at the same level. Even then, it can only really apply to the intersection of the sets of information recorded in the two different models. E.g. UML tools have one class in a model mapping to one class in the code. With sufficiently simple changes, a bit of luck and a following wind, the best UML tools today are capable of maintaining that simple mapping for the names of classes, attributes and operations. The actual code isn't kept in synch (it's not in the UML models), nor are say method calls in models kept in synch with actual calls made in the code (it could be done in theory, but in practice UML models only show a tiny fraction of the calls, so it's hard to know which ones to show automatically). The only way the synchronisation can be made "better" is by moving the two languages closer, e.g. allowing UML operations to contain the method body as text, or the code to show things like "Abstract class" as specially formatted comments (assuming the language generated doesn't have a direct representation of abstractness). Each move towards better synchronisation is thus a move away from having a higher level language and a lower level language.

    The DSM solution is to turn the question on its head and ask "OK, you showed me a high-level modeling language that doesn't yet capture enough information to build full systems. And you showed me a low-level language and a transformation into it. Now tell me what extra information you want to put in the low-level models". (Note that here we're asking for information, most likely on a (problem) domain level, not for the actual representation of that information.) "Now let's look how we can extend or change the high-level modeling language to provide places to capture that information". (Sometimes this step may require a rethink of the modeling language, especially if it's been based on a language that somebody had already made.) "And finally, let's show how we now have all the information we need, and we can generate full code directly from the top model, using the information it originally captured and the new information we would otherwise have entered in the lower-level models." (Remember that there was only a certain amount of information to be added to the lower-level models, regardless of its representation or duplication into several places there. Since we would have been able to generate the initial lower-level models from the information in the initial higher-level models, added extra information, and then generated code, we can clearly expect to be able to generate full code. Whilst it's probably not the best way, you can think how the transformation of the high-level models to low-level models worked, and the transformation of the low-level models to code worked (with the extra information), and thus how you could generate the low-level models, add into them the extra information now recorded in the high-level models, then generate code from there as you would have done in the original scenario)

    And you thought you asked a simple question! :-) Seriously though, I hope this helps you understand the issue in general. It's one of the main reasons why MDA is doomed to failure, at least in its current form of PIM *transform* -> PSM *add detail* *generate* -> code (or *transform* -> More Product Specific Model *add more detail* ...). The industry guru vote is already in on MDA, and it's a resounding "no thanks". Successful DSLs simply don't use this approach - think of SQL, for example. Whilst it would be possible to have C code generated from SQL (and I'm sure this has been done in some places) and edit it, it just leads to a greater set of things that need to have large amounts of expert work to build tools for the synchronisation, and more work for the users in learning and working in two different languages.

    Summa summarum: if you can specify a transformation from a high-level language to a low-level language, and then have modellers add more detail, and then another transformation to code, you can look instead at the information that gets added by modellers, extend the high-level language to capture it, and merge the transformations into one. It makes life easier for the modellers (one language, one model, no round trip desynch) and much easier for the metamodellers (one language, single one-way non-updating transformation). Additionally you normally find a way to record the information into significantly fewer data elements in the higher level language.


     


    Is it possible to represent nested Objects visually as nested Objects?

    Explanation:

    An object of type A contains an object of type B (or alternatively several of them). Is it possible to use a conditional layout of type B within the representation of type A? E.g.

    +------------------------+
    |     Type A             |
    | **********             |
    | * Type B *             |
    | **********             |
    +------------------------+

     
    Solution:In 4.5, this is easily accomplished with the "contents" and "containers" commands in the MERL generator language. See the Method Workbench User's Guide for details, and the Objects Nesting generator in Graph for an example. In earlier versions, there are various other ways: see below.

    1. ONE B IN AN A

    Symbol element conditions in MetaEdit+ 4.0 and earlier can only refer to the object's own properties, not properties of an object in a property. Whilst later versions of MetaEdit+ will allow symbol element conditions to use reports to reach information almost anywhere in the model, in 4.0 there are two ways that you may be able to get what you want:

    1.1 Report Identifier

    You may be able to make B have a report identifier that reveals sufficient information about it for A's symbol elements' conditions. For instance, if A has a property myB that contains an object of type B, and B has list properties Colour (values 'red' or 'green') and Shape (values 'circle' or 'square'), you could make a report identifier for B like this:

    :Colour; ' '; :Shape;

    and in Type A's symbol put four conditional elements: a red square, with condition on myB being 'red square' etc. You can also pick up individual parts of B's information via wildcard conditions, e.g. redness from 'red *', squareness from '* square'.

    1.2 A Inherits Bs Properties

    You could consider making A a subtype of B. That way all of B's properties would be available to be used in conditions in the symbol for A.

    2. SEVERAL Bs IN AN A

    If you want several B's in one A then there are two ways, depending on what you want:

    2.1 Big Transparent Object

    If Type B representations can be moved around inside an A as independent elements, and possibly have relationships between themselves:

    Make A a fairly dumb object type, whose symbol is a big rectangle with no fill (transparent), A's name at the top and lots of empty space. See http://www.metacase.com/blogs/stevek/images/usecase.gif for an example: the System object.

    In this case A doesn't "know" the B's it contains. If you want that, I'd suggest that you make A have a decomposition that contains the B's. I've seen other modeling languages that have tried showing decomposition contents at the top level, and they generally lead to more work for the modeler and semantic inconsistencies. If the B's really are contained by A, then it's better to have them hidden at the top level, and detailed one level lower, where they can't so easily break the boundaries of their A to cross into the implementation details of another A. And of course visually it's better to keep diagrams less complex.

    If you really want to have multiple A's, each visually containing and "knowing" its own B's, there are a couple of ways you could try. You can either make a separate collection property in A and add them there (accepting some duplication between the possibly getting out of synch , or draw relationships from A to each B it contains (probably making the role lines very light gray, so they aren't so visible. You can make them transparent, but that makes them hard to use). The relationship approach works nicely too in the cases when sometimes you want to show the B's inside a big A, and sometimes you'd rather have a little A and 'contains' relationships drawn down to each of its B's below it.

    2.2 List of Bs in an A

    If Type B representations are basically text, and in a regular format within an A:

    Make A have a property "Bs", whose data type is Collection: TypeB. Add a Text element in A's symbol, and set its contents to be a report - e.g. this would produce the effect above (which of course is not exactly what you want):

    do :Bs 
    {   '**********'; newline;
        '* '; id; '*'; newline; /* ending star will not align nicely */
        ''**********'; newline; 
    }
    

     


    Is the data type list for property types customizable?

    Solution:Yes, in a way: there are the basic string, text etc. property types, and various list types. If you want new types, you make e.g. new object types for those properties, giving you much more freedom as to what can be in a property. Each property of this new type can then have exactly the features you want.