OCL constraint using Ecore classifiers - Unknow type exception - eclipse-emf

I'm developing an Ecore model with some invariants defined in OCL, using the OCLinEcore editor. In my model, some elements have references to EClassifier; in some OCL constraints, I need to check if the EClassifier referred to is an EDataType or an EClass. Here is, in OCLinEcore, a model similar to the one I have:
import ecore : 'http://www.eclipse.org/emf/2002/Ecore#/';
package Foo : foo = 'some_namespace'
{
class EndPoint
{
attribute name : String[1];
property type : ecore::EClassifier[1];
}
class Coupling
{
invariant Compatibility:
(destination.type.oclIsKindOf(ecore::EDataType) and source.type = destination.type) or
let destinationClass : ecore::EClass = destination.type.oclAsType(ecore::EClass) in
destinationClass.isSuperTypeOf(source.type.oclAsType(ecore::EClass));
property source : EndPoint[1];
property destination : EndPoint[1];
}
}
However, when I try to validate a dynamic instance of my model, an exception occur with the following message:
An exception occured while delegating evaluation of the
'Compatibility' constraint on 'Coupling': Unknow type ([ecore,
EDataType])
When I try the expression in the OCL interactive console, I obtain the correct result. Am I doing something wrong when defining my invariant? How can I write an invariant that uses Ecore types?

Edward Willink gave me an explanation and a workaround on the OCL forum:
Naked OCL does not support the binding of ecore to something useful,
so the oclAsType(ecore::EClass) has an unresolved reference since each
ecxpression is an independent snippet in the ECore file.
The Juno release therefore adds an extension whereby a package
qualifier may be a URI, so that if you saw the above serialized it
might be
oclAsType(_'http://www.eclipse.org/emf/2002/Ecore'::ecore::EClass).
The Juno release also adds flexibility as to whether you use the new
Pivot-binding with this extended functionality. In the
Window->Preferences->OCL page make sure that the selected executor for
the default delegate is
http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot.

Related

clang: custom attributes not visible in AST

i implemented a custom attribute in clang as described in the official manual:
http://clang.llvm.org/docs/InternalsManual.html#how-to-add-an-attribute
So i added the following Code to Attr.td:
def MyAttr: InheritableAttr {
let Spellings = [GNU<"my_attr">, CXX11<"me", "my_attr">, GCC<"my_attr">, Declspec<"my_attr">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
let Documentation = [MyAttrDocs];
}
and the documentation to AttrDocs.td. After rebuilding clang, it obviously knows the attribute because i don't get an unknown attribute warning when using it. I can even access the new attribute class with libtooling, but the attribute doesn't show up in the AST, even if i add the line let ASTNode = 1 to the attribute definition.
Is there something else i need to consider or what could be the problem?
Unfortunately this was my fault, the missing step is described in the manual in section "Boilerplate": i just had to implement the semantic processing of the attribute in SemaDeclAttr.cpp by adding a new case:
case AttributeList::AT_MyAttr:
handleSimpleAttribute<MyAttrAttr>(S, D, Attr);
break;
So it works fine now.

DryIOC Container Contents

StructureMap has a super-useful debug method on the Container class called WhatDoIHave()
It shows every type in the container along with its lifecycle, guid and a bunch of other info. It's useful for debugging.
There's some info here:
http://jeremydmiller.com/2014/02/18/structuremap-3-is-gonna-tell-you-whats-wrong-and-where-it-hurts/
Does DryIOC have an equivalent debug feature?
(I'm the creator of DryIoc).
You can use container.GetServiceRegistrations() to get registration infos as #fyodor-soikin suggested.
But at the latest version (2.0.0-rc3build339) I have added VerifyResolutions method that may help you to diagnose potential resolution problems, including missing registrations as well. Here the wiki explaining it.
Example from the wiki:
// Given following SUT
public class RequiredDependency {}
public class MyService { public MyService(RequiredDependency d) {} }
// Let's assume we forgot to register RequiredDependency
var container = new Container();
container.Register<MyService>();
// Find what's missing
var results = container.VerifyResolutions();
Assert.AreEqual(1, results.Length);
Verify result is array of ServiceRegistrationInfo and ContainerException KeyValuePairs. In this example the registration info will be:
MyNamespace.MyService registered as factory {ID=14, ImplType=MyNamespace.MyService}
And the exception will be:
DryIoc.ContainerException: Unable to resolve MyNamespace.RequiredDependency as parameter "d"
in MyNamespace.MyService.
Where no service registrations found
and number of Rules.FallbackContainers: 0
and number of Rules.UnknownServiceResolvers: 0
Update:
The functionality is available in latest stable DryIoc 2.0.0.

Bi-directional reference from sub class

Simply put I have the following EMF model:
Step
successor
predecessor
ForkStep extends Step
alternateSuccessor
Now there is a bi-directional reference between the successor and its predecessor - No problem so far.
The tricky part is: How to create a bi-directional reference from alternateSuccessor to its super-class predecessor?
Normally each step can only have one predecessor and one successor. But a fork may have two successors (successor and alternateSuccessor).
If I now go on and create a bi-directional reference, EMF generates a new attribute in the super class, which seems not quite right?
Your question can be understood in two ways:
Given a model, how can we detect which step is "default" and which is "fork".
How can we enforce that users are only able to create "default" steps (single successor) or "fork" steps (multiple successors).
Case #1:
You need a single class Step where you introduce a property isForkStep.
The value of this property will be derived using OCL as follows: successor->size() > 1.
First, I created the meta-model (called the file My.ecore) according to your example. I had to add a Scenario class acting as a container for steps.
The meta-model looks as follows:
Then, I opened the My.ecore file using "OCLinEcore editor" and added the OCL code to the isForkStep property.
package test : test = 'test'
{
class Scenario {
property steps : Step[*] { ordered composes };
}
class Step {
attribute stepId : String { id };
attribute isForkStep : Boolean {
derivation: successor->size() > 1;
}
property predecessor#successor : Step[?];
property successor#predecessor : Step[*] { ordered };
}
}
Then, I tested my new meta-model by creating a "dynamic instance" from Scenario where I created 4 steps. Here is a screenshot from that shows the Scenario instance together with 4 steps. As you can see in the "Properties" view, Step 1 has the property "Is Fork Step" set to true (by clicking to the other steps, you would see false).
Case #2:
Here, I modeled the situation differently. I created an interface Step and two implementation classes - DefaultStep and ForkStep.
Then, I added different OCL constraints to both classes.
DefaultStep: successor->size() <= 1
ForkStep: successor->size() >= 2
Note: I might also use successor->size() >= 2 or successor->size() = 0 to allow ForkSteps without successors.
The meta-model looks like this:
There are many other ways how this can be implemented.
For example, you can use Java instead of OCL, or you can model the situation differently.
Btw. a nice slideshow about OCL in EMF can be found here:
http://www.slideshare.net/EdWillink/enriching-withocl

RestKit entity mapping for UnitTests does not work

I'm trying to create my RKEntityMapping outside of my UnitTest. The problem I have is it only works if I create it inside my test. For example, this works:
RKEntityMapping *accountListMapping = [RKEntityMapping mappingForEntityForName:#"CustomerListResponse" inManagedObjectStore:_sut.managedObjectStore];
[accountListMapping addAttributeMappingsFromDictionary:#{#"count": #"pageCount",
#"page": #"currentPage",
#"pages": #"pages"}];
While the following does now work. The all to accoutListMapping returns exactly what is shown above using the same managed object store:
RKEntityMapping *accountListMapping = [_sut accountListMapping];
When the RKEntityMapping is created in _sut I get this error:
<unknown>:0: error: -[SBAccountTests testAccountListFetch] : 0x9e9cd10: failed with error:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1007 "Cannot perform a mapping operation
with a nil destination object." UserInfo=0x8c64490 {NSLocalizedDescription=Cannot perform
a mapping operation with a nil destination object.}
I'm assuming the nil destination object it is referring to is destinationObject:nil.
RKMappingTest *maptest = [RKMappingTest testForMapping:accountListMapping
sourceObject:_parsedJSON
destinationObject:nil];
Make sure that the file you have created has a target membership of both your main target, and your test target. You can find this by:
clicking on the .m file of your class
open the utilities toolbar (the one on the right)
in the target membership section tick both targets.
This is because if your class does not have target membership to your test target, the test target actually creates a copy of the class that you have created, meaning it has a different binary file to the main target. This leads to that class using the test's version of the RestKit binary, rather than the main projects RestKit. This will lead to the isKindOfClass method failing when it tries to see if the mapping you have passed is of type RKObjectMapping from the main project, because it is of type RKObjectMapping from the test projects version of RestKit, so your mapping doesn't get used, and you get your crash.
At least this is my understanding of how the LLVM compiler works. I'm new to iOS dev so please feel free to correct if I got something wrong.
This problem may also be caused by duplicated class definitions, when including RestKit components for multiple targets individually when using Cocoapods.
For more information on this have a look at this answer.
I used a category on the Mapped object for example
RestKitMappings+SomeClass
+ (RKObjectMapping*)responsemappings {
return mappings;
}
now this category has to be included in the test target as well otherwise the mapping will not be passed.
When you're running a test you aren't using the entire mapping infrastructure, so RestKit isn't going to create a destination object for you. It's only going to test the mapping itself. So you need to provide all three pieces of information to the test method or it can't work.

loading classes with jodd and using them in drools

I am working on a system that uses drools to evaluate certain objects. However, these objects can be of classes that are loaded at runtime using jodd. I am able to load a file fine using the following function:
public static void loadClassFile(File file) {
try {
// use Jodd ClassLoaderUtil to load class into the current ClassLoader
ClassLoaderUtil.defineClass(getBytesFromFile(file));
} catch (IOException e) {
exceptionLog(LOG_ERROR, getInstance(), e);
}
}
Now lets say I have created a class called Tire and loaded it using the function above. Is there a way I can use the Tire class in my rule file:
rule "Tire Operational"
when
$t: Tire(pressure == 30)
then
end
Right now if i try to add this rule i get an error saying unable to resolve ObjectType Tire. My assumption would be that I would somehow need to import Tire in the rule, but I'm not really sure how to do that.
Haven't use Drools since version 3, but will try to help anyway. When you load class this way (dynamically, in the run-time, no matter if you use e.g. Class.forName() or Jodd), loaded class name is simply not available to be explicitly used in the code. I believe we can simplify your problem with the following sudo-code, where you first load a class and then try to use its name:
defineClass('Tire.class');
Tire tire = new Tire();
This obviously doesn't work since Tire type is not available at compile time: compiler does not know what type you gonna load during the execution.
What would work is to have Tire implementing some interface (e.g. VehiclePart). So then you could use the following sudo-code:
Class tireClass = defineClass('Tire.class');
VehiclePart tire = tireClass.newInstance();
System.out.println(tire.getPartName()); // prints 'tire' for example
Then maybe you can build your Drools rules over the interface VehiclePart and getPartName() property.
Addendum
Above make sense only when interface covers all the properties of dynamically loaded class. In most cases, this is not a valid solution: dynamically loaded classes simply do not share properties. So, here is another approach.
Instead of using explicit class loading, this problem can be solved by 'extending' the classloader class path. Be warn, this is a hack!
In Jodd, there is method: ClassLoaderUtil.addFileToClassPath() that can add a file or a path to the classloader in the runtime. So here are the steps that worked for me:
1) Put all dynamically created classes into some root folder, with the respect of their packages. For example, lets say we want to use a jodd.samples.TestBean class, that has two properties: number (int) and a value (string). We then need to put it this class into the root/jodd/samples folder.
2) After building all dynamic classes, extend the classloaders path:
ClassLoaderUtil.addFileToClassPath("root", ClassLoader.getSystemClassLoader());
3) load class and create it before creating KnowledgeBuilder:
Class testBeanClass = Class.forName("jodd.samples.TestBean");
Object testBean = testBeanClass.newInstance();
4) At this point you can use BeanUtils (from Jodd, for example:) to manipulate properties of the testBean instance
5) Create Drools stuff and add insert testBean into session:
knowledgeSession.insert(testBean);
6) Use it in rule file:
import jodd.samples.TestBean;
rule "xxx"
when
$t: TestBean(number == 173)
then
System.out.println("!!!");
end
This worked for me. Note that on step #2 you can try using different classloader, but you might need it to pass it to the KnowledgeBuilderFactory via KnowledgeBuilderConfiguration (i.e. PackageBuilderConfiguration).
Another solution
Another solution is to simply copy all object properties to a map, and deal with the map in the rules files. So you can use something like this at step #4:
Map map = new HashMap();
BeanTool.copy(testBean, map);
and later (step #5) add a map to Drools context instead of the bean instance. In this case it would be even better to use defineClass() method to explicitly define each class.