From: <lk...@rh...> - 2009-10-09 14:51:44
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg DL { border : 1px #006 solid; background-color : #369; padding : 6px; color : #fff; } #msg DT { float : left; width : 6em; font-weight : bold; } #msg DL, #msg DT, #msg UL, #msg LI { font-family : arial,helvetica,sans-serif; font-size : 10pt; } h3 { font-family : arial,helvetica,sans-serif; font-size : 10pt; font-weight : bold; } #msg PRE { overflow : auto; white-space : normal; background-color : #ffc; border : 1px #fc0 solid; padding : 6px; } #msg UL, PRE, .diff { overflow : auto; } #patch h4 { font-family : arial,helvetica,sans-serif; font-size : 10pt; } #patch h4 { padding: 8px; background : #369; color : #fff; margin : 0; } #patch .propset h4, #patch .binary h4 {margin: 0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {background:#eeeeee;padding: 0 0 10px 0;} #patch .propset .diff, #patch .binary .diff {padding: 10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch .add {background:#ddffdd;} #patch .rem {background:#ffdddd;} #patch .lines, .info {color:#888888;background:#ffffff;} .diff { width : 100%; } #msg DL { border : 1px #006 solid; background-color : #369; padding : 6px; color : #fff; } #msg DT { float : left; width : 6em; font-weight : bold; } #msg DL, #msg DT, #msg UL, #msg LI { font-family : arial,helvetica,sans-serif; font-size : 10pt; } h3 { font-family : arial,helvetica,sans-serif; font-size : 10pt; font-weight : bold; } #msg PRE { overflow : auto; white-space : normal; background-color : #ffc; border : 1px #fc0 solid; padding : 6px; } #msg UL, PRE, .diff { overflow : auto; } #patch h4 { font-family : arial,helvetica,sans-serif; font-size : 10pt; } #patch h4 { padding: 8px; background : #369; color : #fff; margin : 0; } #patch .propset h4, #patch .binary h4 {margin: 0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {background:#eeeeee;padding: 0 0 10px 0;} #patch .propset .diff, #patch .binary .diff {padding: 10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch .add {background:#ddffdd;} #patch .rem {background:#ffdddd;} #patch .lines, .info {color:#888888;background:#ffffff;} .diff { width : 100%; } --></style> <title>[rhq-project.org rhq] [5245] Dumping the work done on antlr based configuration file parsing...</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>5245</dd> <dt>Author</dt> <dd>lkrejci</dd> <dt>Date</dt> <dd>2009-10-09 09:51:34 -0500 (Fri, 09 Oct 2009)</dd> </dl> <h3>Log Message</h3> <pre>Dumping the work done on antlr based configuration file parsing...</pre> <h3>Added Paths</h3> <ul> <li>rhq/trunk/modules/plugins/antlr-config/</li> <li><a href="#rhqtrunkmodulespluginsantlrconfigpomxml">rhq/trunk/modules/plugins/antlr-config/pom.xml</a></li> <li>rhq/trunk/modules/plugins/antlr-config/src/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/plugins/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/plugins/antlrconfig/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/plugins/antlrconfig/util/</li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainantlr3orgrhqpluginsantlrconfigutilTreePathg">rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/plugins/antlrconfig/util/TreePath.g</a></li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/java/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/java/org/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/</li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigAntlrTreeStructurejava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/AntlrTreeStructure.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigConfigMapperjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigMapper.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigConfigurationToPathConvertorjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigurationToPathConvertor.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigDefaultConfigurationToPathConvertorjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/DefaultConfigurationToPathConvertor.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigDfsWalkerjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/DfsWalker.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigNewEntryCreatorjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/NewEntryCreator.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigPathElementjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/PathElement.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigTreePathjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/TreePath.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigTreeStructurejava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/TreeStructure.java</a></li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/tokens/</li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigtokensIdjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/tokens/Id.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigtokensRhqConfigTokenjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/tokens/RhqConfigToken.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigtokensTransparentjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/tokens/Transparent.java</a></li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigtokensUnorderedjava">rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/tokens/Unordered.java</a></li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/resources/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/main/resources/META-INF/</li> <li><a href="#rhqtrunkmodulespluginsantlrconfigsrcmainresourcesMETAINFrhqpluginxml">rhq/trunk/modules/plugins/antlr-config/src/main/resources/META-INF/rhq-plugin.xml</a></li> <li>rhq/trunk/modules/plugins/antlr-config/src/test/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/test/java/</li> <li>rhq/trunk/modules/plugins/antlr-config/src/test/resources/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/</li> <li><a href="#rhqtrunkmodulespluginshostsantlrpomxml">rhq/trunk/modules/plugins/hosts-antlr/pom.xml</a></li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/antlr3/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/antlr3/org/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/antlr3/org/rhq/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/antlr3/org/rhq/plugins/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/antlr3/org/rhq/plugins/hosts/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/antlr3/org/rhq/plugins/hosts/parser/</li> <li><a href="#rhqtrunkmodulespluginshostsantlrsrcmainantlr3orgrhqpluginshostsparserHostsg">rhq/trunk/modules/plugins/hosts-antlr/src/main/antlr3/org/rhq/plugins/hosts/parser/Hosts.g</a></li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/java/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/plugins/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/plugins/hosts/</li> <li><a href="#rhqtrunkmodulespluginshostsantlrsrcmainjavaorgrhqpluginshostsHostsComponentjava">rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/plugins/hosts/HostsComponent.java</a></li> <li><a href="#rhqtrunkmodulespluginshostsantlrsrcmainjavaorgrhqpluginshostsHostsDiscoveryComponentjava">rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java</a></li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/plugins/hosts/helper/</li> <li><a href="#rhqtrunkmodulespluginshostsantlrsrcmainjavaorgrhqpluginshostshelperHostDefCreatorjava">rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/plugins/hosts/helper/HostDefCreator.java</a></li> <li><a href="#rhqtrunkmodulespluginshostsantlrsrcmainjavaorgrhqpluginshostshelperHostsComponentHelperjava">rhq/trunk/modules/plugins/hosts-antlr/src/main/java/org/rhq/plugins/hosts/helper/HostsComponentHelper.java</a></li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/resources/</li> <li>rhq/trunk/modules/plugins/hosts-antlr/src/main/resources/META-INF/</li> <li><a href="#rhqtrunkmodulespluginshostsantlrsrcmainresourcesMETAINFrhqpluginxml">rhq/trunk/modules/plugins/hosts-antlr/src/main/resources/META-INF/rhq-plugin.xml</a></li> </ul> <h3>Property Changed</h3> <ul> <li><a href="#rhqbranchesLUKAS_ANTLR_HOSTSsrctestjavaorgrhqpluginshostsHostsComponentTestjava">rhq/branches/LUKAS_ANTLR_HOSTS/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java</a></li> <li><a href="#rhqbranchesLUKAS_ANTLR_HOSTSsrctestresourceslog4jxml">rhq/branches/LUKAS_ANTLR_HOSTS/src/test/resources/log4j.xml</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="rhqbranchesLUKAS_ANTLR_HOSTSsrctestjavaorgrhqpluginshostsHostsComponentTestjava"></a> <div class="propset"><h4>Property changes: rhq/branches/LUKAS_ANTLR_HOSTS/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java</h4> <pre class="diff"> </pre></div> <a id="svnmimetype"></a> <div class="addfile"><h4>Added: svn:mime-type ( => )</h4> <pre class="diff"> <span class="info"> </span></pre></div> <a id="rhqbranchesLUKAS_ANTLR_HOSTSsrctestresourceslog4jxml"></a> <div class="propset"><h4>Property changes: rhq/branches/LUKAS_ANTLR_HOSTS/src/test/resources/log4j.xml</h4> <pre class="diff"> </pre></div> <a id="svnmimetype"></a> <div class="addfile"><h4>Added: svn:mime-type ( => )</h4> <pre class="diff"> <span class="info"> Added: rhq/trunk/modules/plugins/antlr-config/pom.xml </span><span class="cx">=================================================================== </span><span class="rem">--- rhq/trunk/modules/plugins/antlr-config/pom.xml (rev 0) </span><span class="add">+++ rhq/trunk/modules/plugins/antlr-config/pom.xml 2009-10-09 14:51:34 UTC (rev 5245) </span><span class="lines">@@ -0,0 +1,227 @@ </span><span class="add">+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>rhq-plugins-parent</artifactId> + <groupId>org.rhq</groupId> + <version>1.4.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.rhq</groupId> + <artifactId>rhq-antlr-config-plugin</artifactId> + <name>Antlr Configuration file parsing plugin</name> + <version>1.4.0-SNAPSHOT</version> + <description>A base plugin to be used by others to parse configuration files using grammars.</description> + <dependencies> + <dependency> + <groupId>org.antlr</groupId> + <artifactId>antlr-runtime</artifactId> + <version>3.2</version> + <scope>compile</scope> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>integration-tests</id> + <activation> + <property> + <name>maven.test.skip</name> + <value>!true</value> + </property> + </activation> + + <build> + <plugins> + <plugin> + <groupId>org.antlr</groupId> + <artifactId>antlr3-maven-plugin</artifactId> + <version>3.2</version> + <executions> + <execution> + <goals> + <goal>antlr</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.0</version> + <executions> + + <execution> + <id>copy-dependencies</id> + <phase>process-resources</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <includeScope>runtime</includeScope> + <excludeTransitive>false</excludeTransitive> + <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <phase>pre-integration-test</phase> + <configuration> + <tasks> + <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar... + </echo> + <property name="settings.localRepository" location="${user.home}/.m2/repository" /> + <mkdir dir="target/itest" /> + <mkdir dir="target/itest/plugins" /> + <mkdir dir="target/itest/lib" /> + <copy toDir="target/itest/plugins" flatten="true"> + <fileset dir="${settings.localRepository}/"> + <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" /> + </fileset> + <fileset dir="${project.build.directory}"> + <include name="${project.artifactId}-${project.version}.jar" /> + </fileset> + </copy> + <unzip dest="target/itest/lib"> + <fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" /> + <patternset> + <include name="**/lib/sigar.jar" /> + <include name="**/lib/bcel*.jar" /> + <include name="**/lib/*.so" /> + <include name="**/lib/*.sl" /> + <include name="**/lib/*.dll" /> + <include name="**/lib/*.dylib" /> + </patternset> + </unzip> + <move todir="target/itest/lib" flatten="true"> + <fileset dir="target/itest/lib"> + <include name="**/lib/*" /> + </fileset> + </move> + <delete dir="target/itest/lib/hyperic-sigar-${sigar.version}" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- Integration testing voodoo to load and test this plugin with its plugin dependencies --> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + <executions> + <execution> + <id>surefire-it</id> + <phase>integration-test</phase> + <goals> + <goal>test</goal> + </goals> + <configuration> + <skip>${maven.test.skip}</skip> + <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups> + <useSystemClassLoader>false</useSystemClassLoader> + <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine> + <!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>--> + <systemProperties> + <property> + <name>project.artifactId</name> + <value>${project.artifactId}</value> + </property> + <property> + <name>project.version</name> + <value>${project.version}</value> + </property> + </systemProperties> + </configuration> + </execution> + </executions> + </plugin> + + </plugins> + </build> + </profile> + + <profile> + <id>dev</id> + + <properties> + <rhq.rootDir>../../..</rhq.rootDir> + <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir> + <rhq.deploymentDir> + ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins + </rhq.deploymentDir> + </properties> + + <build> + <plugins> + + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.1</version> + <executions> + + <execution> + <id>deploy</id> + <phase>compile</phase> + <configuration> + <tasks> + <mkdir dir="${rhq.deploymentDir}" /> + <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" /> + <echo>*** Updating ${deployment.file}...</echo> + <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + + <execution> + <id>deploy-jar-meta-inf</id> + <phase>package</phase> + <configuration> + <tasks> + <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" /> + <echo>*** Updating META-INF dir in ${deployment.file}...</echo> + <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.outputDirectory}"> + <patternset><include name="META-INF/**" /></patternset> + </unjar> + <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF" update="true"> + </jar> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + + <execution> + <id>undeploy</id> + <phase>clean</phase> + <configuration> + <tasks> + <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" /> + <echo>*** Deleting ${deployment.file}...</echo> + <delete file="${deployment.file}" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + + </executions> + </plugin> + + </plugins> + </build> + </profile> + + </profiles> +</project> </span><span class="cx">\ No newline at end of file </span></pre></div> <a id="rhqtrunkmodulespluginsantlrconfigpomxml"></a> <div class="propset"><h4>Property changes: rhq/trunk/modules/plugins/antlr-config/pom.xml</h4> <pre class="diff"> </pre></div> <a id="svnmimetype"></a> <div class="addfile"><h4>Added: svn:mime-type ( => )</h4> <pre class="diff"> <span class="info">Added: svn:keywords + Date Author Id Revision HeadURL </span></pre></div> <a id="svneolstyle"></a> <div class="addfile"><h4>Added: svn:eol-style ( => )</h4> <pre class="diff"> <span class="info"> Added: rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/plugins/antlrconfig/util/TreePath.g </span><span class="cx">=================================================================== </span><span class="rem">--- rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/plugins/antlrconfig/util/TreePath.g (rev 0) </span><span class="add">+++ rhq/trunk/modules/plugins/antlr-config/src/main/antlr3/org/rhq/plugins/antlrconfig/util/TreePath.g 2009-10-09 14:51:34 UTC (rev 5245) </span><span class="lines">@@ -0,0 +1,101 @@ </span><span class="add">+grammar TreePath; + +options { + language = Java; + output = AST; +} + +tokens { + PATH; + ELEMENT; + POSITION_DISCRIMINATOR; + VALUE_DISCRIMINATOR; + CHILD_POSITIONAL_REFERENCE; +} + +@header { + package org.rhq.plugins.antlrconfig.util; + + import java.util.ArrayList; + import org.rhq.plugins.antlrconfig.PathElement; +} + +@lexer::header { + package org.rhq.plugins.antlrconfig.util; +} + +fragment +LETTER : 'a'..'z' | 'A'..'Z' ; + +fragment +DIGIT : '0'..'9' ; + +DOLLAR : '$' ; +PATH_SEPARATOR : '/' ; +QUOTE : '"' ; + +PATH_ELEMENT : LETTER (LETTER | DIGIT | '-' | '_')* ; +NUMBER : DIGIT+ ; + +OPEN_BRACKET : '[' ; +CLOSE_BRACKET : ']' ; +EQUALS : '=' ; + +fragment +STRING_ESCAPE_SEQUENCE : '\\' (QUOTE | 'n' | 't' | '\\') ; + +fragment +STRING_CONTENTS : (~('\\' | '\n' | '\r' | QUOTE))* (STRING_ESCAPE_SEQUENCE STRING_CONTENTS)? ; + +STRING : '"' STRING_CONTENTS '"' ; + +CHILD_REFERENCE : DOLLAR NUMBER ; + +path returns [List<PathElement> elements] +@init { + $elements = new ArrayList<PathElement>(); +} + : PATH_SEPARATOR p1=pathElement { + $elements.add($p1.pathElement); + }(PATH_SEPARATOR p2=pathElement{ + $elements.add($p2.pathElement); + })* + -> ^(PATH pathElement+) + | EOF! + ; + + +pathElement returns [PathElement pathElement] throws NumberFormatException +@init { + $pathElement = new PathElement(); +} + : el=PATH_ELEMENT { + $pathElement.setTokenTypeName($el.text); + $pathElement.setType(PathElement.Type.NAME_REFERENCE); + } (OPEN_BRACKET discriminator { + if ($discriminator.value != null) { + //TODO implement + $pathElement.setType(PathElement.Type.VALUE_REFERENCE); + $pathElement.setTokenText($discriminator.value); + } else { + $pathElement.setType(PathElement.Type.POSITION_REFERENCE); + $pathElement.setTypeRelativeTokenPosition($discriminator.position); + } + } CLOSE_BRACKET)? + -> ^(ELEMENT PATH_ELEMENT discriminator?) + | ref=CHILD_REFERENCE { + $pathElement.setType(PathElement.Type.INDEX_REFERENCE); + $pathElement.setAbsoluteTokenPosition(Integer.parseInt($ref.text.substring(1))); + } + -> ^(CHILD_POSITIONAL_REFERENCE CHILD_REFERENCE) + ; + +discriminator returns [String value, int position] +@init { + $position = -1; +} + : num=NUMBER { $position = Integer.parseInt($num.text);} + -> ^(POSITION_DISCRIMINATOR NUMBER) + | EQUALS str=STRING { $value = $str.text;} + -> ^(VALUE_DISCRIMINATOR STRING) + ; </span><span class="cx">\ No newline at end of file </span></pre></div> <a id="rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigAntlrTreeStructurejava"></a> <div class="addfile"><h4>Added: rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/AntlrTreeStructure.java (0 => 5245)</h4> <pre class="diff"> <span class="info">--- rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/AntlrTreeStructure.java (rev 0) +++ rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/AntlrTreeStructure.java 2009-10-09 14:51:34 UTC (rev 5245) </span><span class="lines">@@ -0,0 +1,46 @@ </span><span class="add">+/* + * RHQ Management Platform + * Copyright (C) 2005-2009 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.rhq.plugins.antlrconfig; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.antlr.runtime.tree.Tree; + +/** + * A tree structure provider for the generic Antlr {@link Tree} objects. + * + * @author Lukas Krejci + */ +public class AntlrTreeStructure implements TreeStructure<Tree> { + public Collection<Tree> getChildren(Tree parent) { + List<Tree> children = new ArrayList<Tree>(); + + for(int i = 0; i < parent.getChildCount(); ++i) { + children.add(parent.getChild(i)); + } + return children; + } +} </span><span class="cx">\ No newline at end of file Property changes on: rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/AntlrTreeStructure.java ___________________________________________________________________ </span></pre></div> <a id="svnmimetype"></a> <div class="addfile"><h4>Added: svn:mime-type ( => )</h4> <pre class="diff"> <span class="info">Added: svn:keywords + Date Author Id Revision HeadURL </span></pre></div> <a id="svneolstyle"></a> <div class="addfile"><h4>Added: svn:eol-style ( => )</h4> <pre class="diff"> <span class="info"> Added: rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigMapper.java </span><span class="cx">=================================================================== </span><span class="rem">--- rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigMapper.java (rev 0) </span><span class="add">+++ rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigMapper.java 2009-10-09 14:51:34 UTC (rev 5245) </span><span class="lines">@@ -0,0 +1,340 @@ </span><span class="add">+/* + * RHQ Management Platform + * Copyright (C) 2005-2009 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.rhq.plugins.antlrconfig; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.Token; +import org.antlr.runtime.TokenRewriteStream; +import org.antlr.runtime.tree.CommonTree; +import org.antlr.runtime.tree.Tree; + +import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.configuration.Property; +import org.rhq.core.domain.configuration.PropertyList; +import org.rhq.core.domain.configuration.PropertyMap; +import org.rhq.core.domain.configuration.PropertySimple; +import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; +import org.rhq.core.domain.configuration.definition.PropertyDefinition; +import org.rhq.core.domain.configuration.definition.PropertyDefinitionList; +import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap; +import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple; +import org.rhq.plugins.antlrconfig.tokens.RhqConfigToken; + +/** + * Maps RHQ {@link Configuration} objects to Antlr trees and back. + * + * @author Lukas Krejci + */ +public class ConfigMapper { + + private ConfigurationToPathConvertor pathConvertor; + private NewEntryCreator newEntryCreator; + private String[] treeTypeNames; + + private static class ConfigurationDefinitionStructure implements TreeStructure<PropertyDefinition> { + public Collection<PropertyDefinition> getChildren(PropertyDefinition parent) { + if (parent instanceof PropertyDefinitionList) { + return Collections.singletonList(((PropertyDefinitionList)parent).getMemberDefinition()); + } else if (parent instanceof PropertyDefinitionMap) { + return ((PropertyDefinitionMap)parent).getPropertyDefinitions().values(); + } + return null; + } + } + private static final ConfigurationDefinitionStructure configurationDefinitionStructure = new ConfigurationDefinitionStructure(); + + private static class ConfigurationStructure implements TreeStructure<Property> { + public Collection<Property> getChildren(Property parent) { + if (parent instanceof PropertyList) { + return ((PropertyList)parent).getList(); + } else if (parent instanceof PropertyMap) { + return ((PropertyMap)parent).getMap().values(); + } + return null; + } + } + private static final ConfigurationStructure configurationStructure = new ConfigurationStructure(); + + private static final AntlrTreeStructure astStructure = new AntlrTreeStructure(); + + public ConfigMapper() { + } + + public ConfigMapper(ConfigurationToPathConvertor pathConvertor, NewEntryCreator newEntryCreator, String[] treeTypeNames) { + this.pathConvertor = pathConvertor; + this.newEntryCreator = newEntryCreator; + this.treeTypeNames = treeTypeNames; + } + + public ConfigurationToPathConvertor getPathConvertor() { + return pathConvertor; + } + + public void setPathConvertor(ConfigurationToPathConvertor pathConvertor) { + this.pathConvertor = pathConvertor; + } + + public NewEntryCreator getNewEntryCreator() { + return newEntryCreator; + } + + public void setNewEntryCreator(NewEntryCreator newEntryCreator) { + this.newEntryCreator = newEntryCreator; + } + + public String[] getTreeTypeNames() { + return treeTypeNames; + } + + public void setTreeTypeNames(String[] treeTypeNames) { + this.treeTypeNames = treeTypeNames; + } + + public Configuration read(ConfigurationDefinition configurationDefinition, Tree configurationFileAST) throws RecognitionException { + DfsWalker<PropertyDefinition> walker = new DfsWalker<PropertyDefinition>( + configurationDefinitionStructure, configurationDefinition.getPropertyDefinitions().values()); + + Configuration config = new Configuration(); + + createProperty(configurationFileAST, config, null, null); + + return config; + } + + + public void update(Tree configurationFileAST, TokenRewriteStream fileStream, Configuration configuration) throws RecognitionException { + //TODO implement <Unordered> + DfsWalker<Tree> treeWalker = new DfsWalker<Tree>(astStructure, configurationFileAST); + HashMap<Tree, Boolean> visitedMap = new HashMap<Tree, Boolean>(); + while(treeWalker.hasNext()) { + Tree node = treeWalker.next(); + visitedMap.put(node, false); + } + + DfsWalker<Property> walker = new DfsWalker<Property>(configurationStructure, configuration.getProperties()); + + //this was a stab at <Unordered> + //Deque<Map.Entry<List<PathElement>,Tree>> lastKnownParents = new ArrayDeque<Map.Entry<List<PathElement>,Tree>>(); + //int lastDepth = 0; + + Deque<Property> newPropertiesInCreation = new ArrayDeque<Property>(); + + while(walker.hasNext()) { + Property property = walker.next(); + + while (walker.getCurrentDepth() < newPropertiesInCreation.size()) { + createProperty(configurationFileAST, fileStream, newPropertiesInCreation.pop()); + } +//this was a stab at implementing <Unordered> +// if ((propertyPath.size() - 1) > lastDepth) { +// //we stepped a level deeper... +// //there's a complication with the unordered properties. +// //their location in the config file does not necessarily correspond +// //to the order in the configuration structures and therefore we need +// //to do a little bit of voodoo here. +// //we keep a track of last known parents - stuff that has been found before +// //and try to match the new property to that hierarchy (using DFS helps here). +// +// //get the concrete path of the property (this includes all the positional and indexed +// //path elements). +// String treePath = pathConvertor.getConcretePath(propertyPath); +// List<PathElement> path = TreePath.parsePath(treePath); +// +// //now get the parent. The path stored is what we actually found in the parse tree. +// Map.Entry<List<PathElement>, Tree> parentEntry = lastKnownParents.peek(); +// if (parentEntry == null) { +// //TODO throw a better exception type? +// throw new RuntimeException("Could not find a place to put " + last.getName() + " property in its configuration file."); +// } +// +// //now we have the immediate parent and can append the concrete path ending to it. +// Tree immediateParentTree = parentEntry.getValue(); +// PathElement lastElement = path.get(path.size() - 1); +// +// ArrayList<PathElement> actualPath = new ArrayList<PathElement>(parentEntry.getKey()); +// +// if (lastElement.getType() == PathElement.Type.INDEX_REFERENCE) { +// //this is simple... the indexed references are by definition anonymous. +// //we don't know anything else about them but their index in the parent. +// //so there's not much we can do here even if the parent is <Unordered>. +// actualPath.add(lastElement); +// } else if (lastElement.getType() == PathElement.Type.POSITION_REFERENCE) { +// //ok... we have the name and the position... this means that we might have a problem +// //if the parent is unordered. +// if (immediateParentTree instanceof Unordered) { +// //TODO .... this is where I gave up... +// } else { +// //well.. parent is ordered, so we have to find the child on the position +// actualPath.add(lastElement); +// } +// } else { +// throw new RuntimeException("Concrete path contains non-concrete path elements: " + path.toString()); +// } +// } + + + String propertyTreePath = pathConvertor.getTreePath(property); + TreePath treePath = new TreePath(configurationFileAST, propertyTreePath, treeTypeNames); + Tree propertyTree = treePath.match(); + + if (propertyTree == null) { + //scenarios possible here: + //1) this is a new property added to the configuration + //2) the property has moved within the AST - we need to find it if its parent is <Unordered> + if (newPropertiesInCreation.size() == walker.getCurrentDepth()) { + createProperty(configurationFileAST, fileStream, newPropertiesInCreation.pop()); + } + newEntryCreator.prepareFor(property); + newPropertiesInCreation.push(property); + } else { + if (property instanceof PropertySimple) { + String value = ((PropertySimple)property).getStringValue(); + fileStream.replace(propertyTree.getTokenStartIndex(), propertyTree.getTokenStopIndex(), value); + } + setVisited(propertyTree, visitedMap); + } + } + + while (newPropertiesInCreation.size() > 0) { + createProperty(configurationFileAST, fileStream, newPropertiesInCreation.pop()); + } + + //ok, now we've gone through the configuration object and applied it to the tree. + //all there's left is to clear out what should be deleted from the tree. + List<Tree> toBeDeleted = new ArrayList<Tree>(); + treeWalker = new DfsWalker<Tree>(astStructure, configurationFileAST); + while(treeWalker.hasNext()) { + Tree node = treeWalker.next(); + Boolean isVisited = visitedMap.get(node); + if (!isVisited) toBeDeleted.add(node); + } + //now remove children of all things we found to be deleted from the visited map + //this will leave us only with the topmost tree nodes marked as to be deleted + for(Tree node : toBeDeleted) { + removeChildren(node, visitedMap); + } + + //and now move on to the deletion itself + for(Tree node : toBeDeleted) { + if (visitedMap.containsKey(node)) { + Token nodeToken = fileStream.get(node.getTokenStartIndex()); + if (!(nodeToken instanceof RhqConfigToken) || !((RhqConfigToken)nodeToken).isTransparent()) { + fileStream.delete(nodeToken); + } + } + } + } + + private void createProperty(Tree tree, Configuration configuration, PropertyList parentList, PropertyMap parentMap) { + PropertyDefinition propDef = pathConvertor.getPropertyDefinition(TreePath.getPath(tree, treeTypeNames)); + Property prop = instantiate(propDef); + + if (parentList != null) { + parentList.add(prop); + } else if (parentMap != null) { + parentMap.put(prop); + } else { + configuration.put(prop); + } + + if (prop instanceof PropertySimple) { + ((PropertySimple) prop).setValue(tree.getText()); + } else if (prop instanceof PropertyList) { + parentList = (PropertyList) prop; + parentMap = null; + } else if (prop instanceof PropertyMap) { + parentMap = (PropertyMap) prop; + parentList = null; + } + + for(int i = 0; i < tree.getChildCount(); ++i) { + createProperty(tree.getChild(i), configuration, parentList, parentMap); + } + } + + private Property instantiate(PropertyDefinition definition) { + if (definition instanceof PropertyDefinitionSimple) { + return new PropertySimple(definition.getName(), null); + } else if (definition instanceof PropertyDefinitionList) { + return new PropertyList(definition.getName()); + } else if (definition instanceof PropertyDefinitionMap) { + return new PropertyMap(definition.getName()); + } + + return null; + } + + private void applyInstructions(List<NewEntryCreator.OpDef> instructions, TokenRewriteStream fileStream) { + for (NewEntryCreator.OpDef instruction : instructions) { + switch (instruction.type) { + case INSERT_AFTER: + fileStream.insertAfter(instruction.tokenIndex, instruction.text); + break; + case INSERT_BEFORE: + fileStream.insertBefore(instruction.tokenIndex, instruction.text); + break; + case REPLACE: + fileStream.replace(instruction.tokenIndex, instruction.text); + break; + case DELETE: + fileStream.delete(instruction.tokenIndex); + break; + } + } + } + + private void setVisited(Tree tree, Map<Tree, Boolean> visitedMap) { + //if a tree is visited, all its children are visited as well + DfsWalker<Tree> walker = new DfsWalker<Tree>(astStructure, tree); + while(walker.hasNext()) { + Tree child = walker.next(); + visitedMap.put(child, true); + } + } + + private void removeChildren(Tree tree, Map<Tree, Boolean> visitedMap) { + Collection<Tree> children = astStructure.getChildren(tree); + DfsWalker<Tree> walker = new DfsWalker<Tree>(astStructure, children); + while(walker.hasNext()) { + Tree child = walker.next(); + visitedMap.remove(child); + } + } + + private void createProperty(Tree tree, TokenRewriteStream fileStream, Property prop) { + List<NewEntryCreator.OpDef> instructions = newEntryCreator.getInstructions(tree, prop); + if (instructions != null) { + applyInstructions(instructions, fileStream); + } + } +} </span></pre></div> <a id="rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigConfigMapperjava"></a> <div class="propset"><h4>Property changes: rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigMapper.java</h4> <pre class="diff"> </pre></div> <a id="svnmimetype"></a> <div class="addfile"><h4>Added: svn:mime-type ( => )</h4> <pre class="diff"> <span class="info">Added: svn:keywords + Date Author Id Revision HeadURL </span></pre></div> <a id="svneolstyle"></a> <div class="addfile"><h4>Added: svn:eol-style ( => )</h4> <pre class="diff"> <span class="info"> Added: rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigurationToPathConvertor.java </span><span class="cx">=================================================================== </span><span class="rem">--- rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigurationToPathConvertor.java (rev 0) </span><span class="add">+++ rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigurationToPathConvertor.java 2009-10-09 14:51:34 UTC (rev 5245) </span><span class="lines">@@ -0,0 +1,49 @@ </span><span class="add">+/* + * RHQ Management Platform + * Copyright (C) 2005-2009 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.rhq.plugins.antlrconfig; + +import java.util.List; + +import org.rhq.core.domain.configuration.Property; +import org.rhq.core.domain.configuration.definition.PropertyDefinition; + +/** + * Provides the means to convert the configuration property structure to the tree structure of the target + * configuration file's AST. + * + * @author Lukas Krejci + */ +public interface ConfigurationToPathConvertor { + + String getTreePath(Property property); + + /** + * + * @param treePath the individual path elements won't have their type set, + * but all other info will be available (i.e. name, text and position). The position + * is absolute (nth child of the parent, instead of nth child of given type) + * @return + */ + PropertyDefinition getPropertyDefinition(List<PathElement> treePath); +} </span></pre></div> <a id="rhqtrunkmodulespluginsantlrconfigsrcmainjavaorgrhqpluginsantlrconfigConfigurationToPathConvertorjava"></a> <div class="propset"><h4>Property changes: rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/ConfigurationToPathConvertor.java</h4> <pre class="diff"> </pre></div> <a id="svnmimetype"></a> <div class="addfile"><h4>Added: svn:mime-type ( => )</h4> <pre class="diff"> <span class="info">Added: svn:keywords + Date Author Id Revision HeadURL </span></pre></div> <a id="svneolstyle"></a> <div class="addfile"><h4>Added: svn:eol-style ( => )</h4> <pre class="diff"> <span class="info"> Added: rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/DefaultConfigurationToPathConvertor.java </span><span class="cx">=================================================================== </span><span class="rem">--- rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/DefaultConfigurationToPathConvertor.java (rev 0) </span><span class="add">+++ rhq/trunk/modules/plugins/antlr-config/src/main/java/org/rhq/plugins/antlrconfig/DefaultConfigurationToPathConvertor.java 2009-10-09 14:51:34 UTC (rev 5245) </span><span class="lines">@@ -0,0 +1,259 @@ </span><span class="add">+/* + * RHQ Management Platform + * Copyright (C) 2005-2009 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation, and/or the GNU Lesser + * General Public License, version 2.1, also as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with this program; + * if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.rhq.plugins.antlrconfig; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.rhq.core.domain.configuration.Property; +import org.rhq.core.domain.configuration.PropertyList; +import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; +import org.rhq.core.domain.configuration.definition.PropertyDefinition; +import org.rhq.core.domain.configuration.definition.PropertyDefinitionList; +import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap; + +/** + * This default implementation can create a tree path out of the names of the properties/property definitions. + * + * the name of a property that is supposed to be mapped to a configuration file has to start with <code>config://</code> + * "scheme" definition followed by one of the following: + * <ul> + * <li><code>/name</code> - an absolute path within the tree to the given property + * <li><code>name</code> - a path relative to the parent property + * <li><code>$[number]</code> - ([number] stands for an actual number without the brackets) defines a position of the respective child in the parent in the config file AST. + * </ul> + * The <code>name</code> can be defined with the following regex: + * <code>(\w+|$\d+)(\/(\w+|$\d+))*</code> + * + * @author Lukas Krejci + */ +public class DefaultConfigurationToPathConvertor implements ConfigurationToPathConvertor { + + public static final String NAME_PREFIX = "config://"; + public static final int NAME_PREFIX_LENGTH = NAME_PREFIX.length(); + + private ConfigurationDefinition configurationDefinition; + + public DefaultConfigurationToPathConvertor(ConfigurationDefinition configurationDefinition) { + this.configurationDefinition = configurationDefinition; + } + + /* (non-Javadoc) + * @see org.rhq.core.antlr.ConfigurationToPathConvertor#getConcretePath(org.rhq.core.domain.configuration.Property) + */ + public String getTreePath(Property property) { + String name = property.getName(); + String ret = null; + if (name.startsWith(NAME_PREFIX)) { + name = name.substring(NAME_PREFIX_LENGTH); + + if (name.startsWith("/")) { + //absolute path + ret = name; + } else { + //relative path.. we have to climb up the parents to get the full path + Property parent = property.getParentList(); + if (parent != null && !name.startsWith("$")) { + //we're inside a list constructing a concrete path and the current name + //is a name reference. + //need to figure out the position of this property inside the parent list + int pos = 0; + for(Property p : ((PropertyList)parent).getList()) { + if (p.equals(property)) { + break; + } + pos++; + } + name += "[" + (pos + 1) + "]"; //position is 1 based. + } + if (parent == null) parent = property.getParentMap(); + if (parent == null) { + //well... this is a property with a relative path but is a top level property + //we have no option but to return the relative path here. + ret = name; + } else { + String parentPath = getTreePath(parent); + ret = parentPath + "/" + name; + } + } + } + return ret; + } + + + public PropertyDefinition getPropertyDefinition(List<PathElement> treePath) { + if (treePath == null || treePath.isEmpty()) return null; + + HashMap<PropertyDefinition, Integer> partialMatches = new HashMap<PropertyDefinition, Integer>(); + + PathElement rootElement = new PathElement(treePath.get(0)); + rootElement.setTokenTypeName("/" + rootElement.getTokenTypeName()); + + for(PropertyDefinition pd : configurationDefinition.getPropertyDefinitions().values()) { + int followUp = getPartialMatchNextFollowupIndex(rootElement, 0, pd.getName()); + if (followUp >= 0) { + partialMatches.put(pd, followUp); + } + } + + if (partialMatches.isEmpty()) return null; + + ArrayList<PathElement> treePathCopy = new ArrayList<PathElement>(treePath); + //we've already processed that one. + treePathCopy.remove(0); + + for(PathElement el : treePathCopy) { + HashMap<PropertyDefinition, Integer> newPartialMatches = new HashMap<PropertyDefinition, Integer>(); + + for(Map.Entry<PropertyDefinition, Integer> entry : partialMatches.entrySet()) { + PropertyDefinition partialMatch = entry.getKey(); + String name = partialMatch.getName(); + int followupIdx = entry.getValue(); + + if (followupIdx < name.length() - NAME_PREFIX_LENGTH) { + //this definition's still "follows" the path + followupIdx = getPartialMatchNextFollowupIndex(el, followupIdx, name); + if (followupIdx >= 0) { + newPartialMatches.put(partialMatch, followupIdx); + } + } else { + //this means that this property definition matched the path so far + //but contains no more path elements. It still might have children with + //relative paths that might match the rest of the path though. + if (partialMatch instanceof PropertyDefinitionList) { + PropertyDefinition child = ((PropertyDefinitionList)partialMatch).getMemberDefinition(); + followupIdx = getPartialMatchNextFollowupIndex(el, 0, child.getName()); + if (followupIdx >= 0) { + newPartialMatches.put(child, followupIdx); + } + } else if (partialMatch instanceof PropertyDefinitionMap) { + PropertyDefinitionMap map = (PropertyDefinitionMap)partialMatch; + + for(PropertyDefinition child : map.getPropertyDefinitions().values()) { + AbsoluteIndexAndFollowupIndex indexes = getAbsoluteIndexFromName(child.getName()); + if (indexes.absoluteIndex > 0 && indexes.absoluteIndex == el.getAbsoluteTokenPosition()) { + newPartialMatches.put(child, indexes.followupIndex); + } else { + //k, this is not an absolute index, let's try matching by name + followupIdx = getParti... [truncated message content] |