-
Notifications
You must be signed in to change notification settings - Fork 15
On-the-fly multiple inheritance to match RDF types #120
base: master
Are you sure you want to change the base?
Conversation
Signed-off-by: Andrew Berezovskyi <[email protected]>
Signed-off-by: Andrew Berezovskyi <[email protected]>
@SuppressWarnings("ALL") | ||
public class OslcShapeGenerator { | ||
public static <T extends IExtendedResource> T newShape(Resource r, Class<? extends T> shapeClass, Class<T> shapeInterface, | ||
List<Class> rdfInterfaces) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use/prefer varargs here, they are more flexible for caller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
|
||
import org.junit.Assert.* | ||
|
||
class OslcShapeGeneratorTest { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know kotlin may be easier/quicker to use, but do we really want mixing languages in lyo? Isn't this forcing potential contributors to learn another language in order to contribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right. But we need to evolve. I thought that starting from unit tests is fairly low-risk (tests can still be written in Java).
final T shape = (T) Proxy.newProxyInstance(shapeInterface.getClassLoader(), | ||
proxyClasses.toArray(new Class[0]), (proxy, method, args) -> { | ||
System.out.printf("%s called\n", method.toString()); | ||
return method.invoke(shapeBean, args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If, at the end, we are going to rely on shapeClass to being implementing all rdfInterfaces methods, I still cannot see the worth of this change. In other words, if shapeClass does not implement any of the methods declared on any rdfInterfaces classes, this line will fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line will never fail for the reasons you listed (though never say never!). The reason is that all interfaces are supposed to have no methods at all! These interfaces are 1-1 mapping to the RDF types of a resource and are not designed to be used in an OO way (eg for polymorphism). The main advantage is a support of pattern matching of rdf:type
values via reflection. The concrete class is still mapped to a shape. Think of this as bringing a tiny bit of open-world thinking to Java. But you are right, the change is fairly minimal technically and you'd need Kotlin (read about when() {}
here: https://kotlinlang.org/docs/reference/control-flow.html#when-expression) or Scala to enjoy this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But there is an idea to map those on the fly to the entries in the extendedProperies! Maybe will be a good addition.
I had many conversations with Jim and Jad about the impedance mismatch between Java programming model and the RDF model as a whole. OSLC itself tried to fix it with shapes. We then tried fixing it in Lyo with Lyo Store. After Jim shared with me papers about the ActiveRDF design, I thought that Groovy would allow us to implement similar functionality in the most direct way possible.
Recently, I had chat with Jad that it would be awesome to unmarshal the following piece of RDF:
into an instance of the most relevant shape but also make it implement all the interface matching each RDFS class. This would be the most usable way to reduce the impedance mismatch without forcing people to use bits of Groovy code. We agreed that it would be way over our heads to generate such bytecode on the fly.
Today I was leaning about Eclipse Microprofile and ended up reading a bit of code of the Apache Tamaya code that made use of the java.lang.reflect.Proxy class and I immediately knew I hit the jackpot.
In this PR you can see the implementation of the core idea for this feature. Extra work would have to be done on reflection in order to remove the need to specify all the Java classes during unmarshalling.
Right now the code is invoked like this:
All of the assertions pass:
This means both that the interfaces have been assigned properly and that the
RequirementShape
getters are called correctly (which is instantiated by the JMH itself).The PR is not ready for merging but the idea is ready for