From:
"Ondrej Zizka"
<ozizka@redhat.com>
To: jboss-migration@redhat.com
Sent: Thursday, May 1, 2014 12:05:23 AM
Subject: Re: Let's replace the GraphVisitor interface
concept with something generic
I've put it to this doc so we can edit/comment there.
https://docs.google.com/document/d/1UOihPv_zryFilCb7T0k8992wPUt3YNP4goh9rxTC7ng/edit#
Ondra
On 1.5.2014 04:35, Ondrej Zizka
wrote:
Hi,
as we discussed before, I'd like to replace the GraphVisitor
interface with something generic.
Seriously, having hard-coded interface with methods specific
for e.g. MessageDrivenBean, EjbEntity, SpringConfiguration,
etc. is IMO not the way to go. It is hard to extend. A rule
system created around this would be cumbersome.
public void visitEjbEntity(EjbEntityFacet entry);
public void visitEjbService(EjbSessionBeanFacet entry);
public void
visitMessageDrivenBean(MessageDrivenBeanFacet entry);
public void visitEjbEntity(SpringBeanFacet entry);
...
![](cid:part3.00050005.00060307@redhat.com)
Instead, we should focus on the graph, and have just very
few node types in the core - FileNode, and the rest would
be subtypes defined in addons. Addons would, through rules:
* replace a node with a subclass, e.g.
FileNode => XmlFileNode => MavenPomNode,
FileNode => JavaFileNode =>
AnnotationNode
* add properties, e.g.
XmlFileNode's "doctype",
ClassNode's "blacklisted"
* connect nodes to them, e.g.
MavenPom ---contains--->
MavenDependencyNode
JavaFile --- imports --> [ ClassNode,
ClassNode, ... ]
This approach would:
* Leverage of Forge modularity (e.g. Maven addon
depending on XmlFile addon)
* Improve extendability (no need to squeeze everything
into the GraphVisitor interface's methods or extend it)
* Lead to much more straightforward rules implementation
- all rules would reduce to:
* matching graph information (Gremlin?)
* using DAO's / Services (for mining data from the
files/..., and for writing them during active migration)
1) Bundled - XPath, AST query, properties,
Maven remote fetch, ...
2) User's: .class packed within the addon
or a Groovy class
* writing back to the graph
* rendering pieces of HTML for the report.
Who's in? I need some scenarios where this wouldn't work.
But from what I can tell, this would be more generic, but
still simpler, than current "God-object" suffering
GraphVisitor.
As an example, take e.g. MavenRemoteFetchVisitor. https://github.com/windup/windup/blob/master/engine/rules/impl/src/main/java/org/jboss/windup/engine/visitor/inspector/MavenRemoteFetchVisitor.java
All that is doable using few simple building blocks,
directed by few lines of a rule like this:
------------------------------------------------------------------
<var name="pomNS" val="http://maven.apache.org/POM/4.0.0">
Rule 1) which would process all POM files and load the info
into the graph.
<rule id="maven.pomFiles" desc=" Analyze Maven POM
files "
phase="StaticConfigAnalysis">
<graph match="XmlFileNode[doctype='http://maven.apache.org/POM/4.0.0']"
toVar="xmls">
<for var="pom" in="xmls">
<graph:replaceSingle ref="pom"
with="MavenPomFileNode">
<properties>
<!-- <jaxb> would invoce a call
to a Service.
<properties> hander would
take returned object's bean props.
toClass would load the class from
CL or compile from .groovy coming with the migrator (addon).
-->
<jaxb toClass="PomJaxb.groovy"
fromFile="${pom.path}">
<ns name="pom"
uri="${pomNS}"/>
</jaxb>
</properties>
</graph>
</for>
</rule>
@XmlRoot
class PomJaxb {
@XmlXPath("/pom:project/pom:modelVersion")
String modelVersion;
@XmlXPath("/pom:project/pom:name")
String name;
@XmlXPath("/pom:project/pom:description" String description;
@XmlXPath("/pom:project/pom:url" String url;
}
Rule 2) which would load the dependencies and describe them
into Nodes and Edges.
<rule id="maven.pomDependencies" desc=" Analyze Maven
POM file dependencies "
phase="StaticConfigAnalysis">
<after rule="maven.pomFiles">
<graph match="MavenPomFileNode"
toVar="pomVertexes">
<for var="pomV" in="pomVertexes">
<xpath toVar="deps" fromFile="${pomV.path}"
match="/pom:project/pom:dependencies/pom:dependency"/>
<for var="depElement" in="deps">
<jaxb toVar="dep"
toClass="MavenDepencencyJaxb.groovy"
fromElement="depElement" ns="pom ${pomNS}"/>
<graph:query toVar="isBlacklisted"
q=" /* I don't know Gremlin so far,
imagine an equiv of this XPath: */
MavenDependencyNode[
g=${dep.groupId} and
a=${dep.artifactId} and v=${dep.version}
]@blacklisted
" />
<continue if="isBlacklisted /* var, or
Groovy (or EL) expression */" />
<!-- This would be useful for blacklists
and filters in general, which appear often in real life
rules. -->
<graph:insertIfNotExists
type="MavenDependencyNode" toVar="depVertex>
<properties from="dep"/>
</graph>
<graph:edge type="dependsOn" from="pomV"
to="depVertex"/>
<!-- Maybe Gremlin could
replace this? -->
</for>
</for>
</rule>
@XmlRoot
class MavenDepencencyJaxb {
// GraphKeyProperty identifies those which are
compared for insertIfNotExists.
@GraphKeyProperty @XmlXPath("./pom:groupId") String
groupId;
@GraphKeyProperty @XmlXPath("./pom:artifactId")
String artifactId;
@GraphKeyProperty @XmlXPath("./pom:version") String
version;
}
------------------------------------------------------------------
As you can see, It creates independent rules which only
communicate indirectly through the graph.
You can also see how nicely Java classes fit into this, and
how Groovy could make this easier.
SERVICES INVOCATION
Forge UI could be mapped to XML elements. I.e. <aaa
foo="bar"/> could invoke command "aaa" with given params.
I believe Forge already has this way of input, right?
GRAPH OPERATION
There would be several <graph:...> operations - CRUD
plus some special.
EXECUTION FLOW
The flow would be simple, from top to bottom, creating
variables along the way, containing objects or iterable
collections of objects. Those iterable could be used in
<for>.
Does Lincoln's executor fit this? I haven't still looked how
it works. This tree would likely be executed classically
with a stack and using tree reduction for operation
arguments.
For more complex logic, users would break the task into
multiple rules, storing data into the graph intermediately.
I'll check few more visitors to see if this is powerful
enough to satisfy all the baneeds.
.............................
Also, I'd like to eradicate any mention of an archive from
most of the code - archives should be totally transparent
for the migrators. There should be just FileNodes, connected
with ArchiveNodes, and whoever needs an information that a
file came from an archive, may look that up. See https://docs.google.com/drawings/d/1IMnds3Qu8Wwcf7_mr7NJ9a3YgtcGJ7dejl09EhWl7Vc
for illustration.
Ondra