I have to link two modules:
for ex: i have some information in module 'A' and the information in module 'B' which is similar to module 'A' and module 'C' has the same information. Now the linking is present between 'A' to 'B' and 'B' to 'C'. The target is to link 'C' to 'A'.
Creating a link to a DOORS object which resides in a different module does not differ from creating a link to objects of the same module. You just have to retrieve the object handle from the module.
Consider this:
Object sourceObj = ... // you already have this object handle
Object targetObj = null
const string targetModuleName = "/my/DOORS/module"
// open the module
Module mod = edit(targetModuleName, true, false)
if (null(mod)) ack("Error!")
// now it depends on how you can identify your target object
for targetObj in mod do {
// example: if the object identifier matches ...
if (... == identifier(targetObj)) {
sourceObj -> targetObj
break
}
}
Additionally, have a look at this question where Steve explains this scenario as well.
Related
During writing validation rules a came across the problem that I need some content from a rule in my grammar which is hierarchically higher than the one I pass to my validationMethod.
I know that I can refer to a "higher" rule with .eContainer but then I don't have a clue how to access the values I want to.
For example I have the following grammar snippet:
rule1:
name=ID content=rule2
;
rule2:
<<whatever content>>
;
If I have a normal validationMethod with the argument rule1 then I can access the name via .name but when I give rule2 as an argument and then referring to rule via .eConatiner the .name method does not exist.
Greetings Krzmbrzl
EObject is the root class of all AST node classes. It comes from the EMF Ecore framework which is used by Xtext to generate the AST implementation. Therefore, the EObject class contains a lot of the tree structure features, e.g., iterating through a tree. The EObject.eContainer() method returns an element of type EObject which actually is the super type of the type of the actual returned object. To get access to methods of the next higher element, you have to cast the eContainers methods result like this:
#Check
public void check(rule2 r2) {
EObject o = r2.eContainer();
rule1 r1 = (rule1) o;
String r1Name = r1.getName();
}
If the type of the parent object is ambigous, you should test whether the actual type is the expected with an instanceof expression:
#Check
public void check(rule2 r2) {
EObject o = r2.eContainer();
if (o instanceof rule1) {
rule1 r1 = (rule1) o;
String r1Name = r1.getName();
}
}
Xtend provide the same instanceof-expression like Java. But if the object to be checked definetly can have more then a few types, you can use Xtends really powerful switch expression. It supports so called type guards. You can switch over any object and instead of case value: guards simply write the a concrete type:
switch (anyAbstractTypeObject) {
ConcreteSubtypeA: {...}
ConcreteSubtypeB: {...}
}
This is an elegant shorthand if-instanceof-eleseif-... in Xtend.
If I have the following input
test = 3; //first
test = test + 3; //second
parsed with a grammar that looks like this (for example)
Declaration:
name=ID "=" DeclarationContent
;
DeclarationContent:
number=INT ("+" DeclarationContent)?
| reference=[Declaration] ("+" DeclarationContent)?
;
to which declaration does the reference refer (looking at the second declaration in my example)? Or in other words does the reference "test" (second Declaration) refer to the first Declaration ("test = 3;") or directly to itself ("test = test+ 3") and would therefor be a cycle in hierarchy.
Greeting Krzmbrzl
Xtext will always link a cross reference [Declaration] to the first elemenent which is identified by the given ID. In your example hello + 3, the cross reference behind hello will resolved to the declaration hello in line 1. But if you have more then one element with the same (qualified) name within the same scope (container of visibility) Xtext will throw an Exception. You should
implement your own ScopeProvider (Use the generated stub in your.dsl.scoping.YourDslScopeProvider) to resolve this problem or
Use the composed check to automatically validate names.
fragment = validation.JavaValidatorFragment auto-inject {
composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
}
A DOORS DXL question:
I have 2 modules, module "Parent" and module "Child". The objects inside module Child is linked to the objects inside module Parent.
Module Parent has several baselines. Instead of linking to the current version of this module, I wish to link to a specific baseline version, for example module Parent baseline 2.0.
A link could be like this:
An object in module Child [current version] ---> An object in module Parent [baseline 2.0]
Could anyone please give me a DXL example?
B.r Tor-Erling
This will create the link you are looking for on a case by case basis. You would need to supply the Object IDs for each of the links you want to create. If you are trying to update links that already exist, you'll have to loop through all the objects in the Child looking for links to the parent, create the new link to the baseline, then delete the old one.
Module mChild = edit("/PROJECT/FOLDER/MODULE_NAME", false)
Module mParent = read("/PROJECT/FOLDER/PARENT_MOD_NAME", false)
Module bParent
Object oChild = object(123, mChild)
Object oParent
String linkMod = "/PROJECT/FOLDER/LINK_MODULE"
// baseline(MAJ, MIN, SUFFIX) e.g. 2.0
Baseline b = baseline(2, 0, "")
if(baselineExists(mParent, b))
{
bParent = load(mParent, b, false)
oParent = object(456, bParent)
oChild -> linkMod -> oParent
save mChild
close bParent
}
Good Luck!
I have a bunch of modules that export an IModule interface. So in the main program I have no problems
...
let mutable modules = Seq.empty
[<ImportMany>]
member x.Modules
with get():IEnumerable<Lazy<IModule, IModuleData>> = modules
and set(a) = modules <- a
...
But now I need to expose an interface back to those modules. So each module will import a single interface
...
let mutable parent:IParent = ?
[<Import>]
member x.Parent
with get():IParent = parent
and set(a) = parent <- a
...
So my problem is how do I go about creating my mutable "parent" when I have no initial value for it? Also, is this the appropriate way to expose an API back to component parts?
Using Unchecked.defaultof<_> should do the trick, but it means that you're circumventing the F# type system, which may be a dangerous thing to do - the system tries to prevent you from accidentally dereferencing null values (and getting NullReferenceException).
Types that are declared in F# don't have null as a proper value, which is an attempt to eliminate the usual errors caused by null. The clean F# approach is to use option types to represent the fact that a value is missing:
let mutable parent:option<IParent> = None
[<Import>]
member x.Parent
with get():IParent =
match parent with
| Some p -> p
| None -> failwith "TODO: Throw some reasonable exception here!"
and set(a) = parent <- Some(a)
If you just want to say that IParent can have a null value (perhaps because you need to use it in some C# code that will ignore the F# restriction anyway), then you can mark the type definition using a special attribute that allows using null with the type.
[<AllowNullLiteral>]
type IParent =
abstract DoStuff : unit -> unit
Then you can write let mutable parent:IParent = null. The benefit of this approach is that you can also easily check whether a value is null (using just if parent <> null then ...) which is not that obvious when you use Unchecked.defaultof<_>.
let mutable parent = Unchecked.defaultof<IParent>
should do the trick.
Following up on what Tomas explained, you should probably put your imports directly into your constructor. That will allow your code to be a bit more idiomatic.
In Haskell, I use the Data.Map module, and its principal type of the same name, Data.Map.Map, like this:
import Data.Map (Map)
import qualified Data.Map as M
In F#, I want to do something similar with my Item module, which contains a type of the same name:
module Item
type Item = { Description: string }
let empty = { Description = "" }
I can't find a way to use this module qualified and the type unqualified. Can I use this module and type like this, from another module?
let getItem (): Item = Item.empty
Edit:
Adding a type alias from a client module lets me use the Item module with qualification and the Item type without qualification, but is there a better way still?
type Item = Item.Item
I think the only way to import only a single type from a module is to use type alias (as you already noted). To get a qualified access to members of the module (under a different name), you can use module alias:
type Item = Item.Item // Type-alias for type(s) from module
module I = Item // Module-alias for accessing members
// Now you can write:
let getItem() : Item = I.empty
I don't think there is any way for importing members from module selectively (as in Haskell), so this is probably the best option.