[Buix-commits] r990 - in lutinjaxx/tags: . 0.5 0.5/jaxx-core 0.5/jaxx-core/src/main/java/jaxx 0.5/jaxx-core/src/main/java/jaxx/compiler 0.5/jaxx-core/src/main/java/jaxx/css 0.5/jaxx-core/src/main/java/jaxx/runtime 0.5/jaxx-core/src/main/java/jaxx/runtime/validator 0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui 0.5/jaxx-core/src/main/java/jaxx/tags 0.5/jaxx-core/src/main/java/jaxx/tags/swing 0.5/jaxx-core/src/main/java/jaxx/tags/validator 0.5/jaxx-core/src/main/resources 0.5/jaxx-core/src/test/java/ja
Author: tchemit Date: 2008-10-21 07:31:05 +0000 (Tue, 21 Oct 2008) New Revision: 990 Added: lutinjaxx/tags/0.5/ lutinjaxx/tags/0.5/jaxx-core/changelog lutinjaxx/tags/0.5/jaxx-core/pom.xml lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/PrintTagInfo.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataSource.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/css/Stylesheet.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/Util.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingDirectoryFieldValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingFileFieldValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingDirectoryFieldValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingFileFieldValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/RequiredFileFieldValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/resources/validators.xml lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java lutinjaxx/tags/0.5/jaxx-core/src/test/resources/jaxx/ lutinjaxx/tags/0.5/jaxx-core/src/test/resources/log4j.properties lutinjaxx/tags/0.5/jaxx-example/Calculator/pom.xml lutinjaxx/tags/0.5/jaxx-example/Components/pom.xml lutinjaxx/tags/0.5/jaxx-example/Counter/pom.xml lutinjaxx/tags/0.5/jaxx-example/LabelStyle/pom.xml lutinjaxx/tags/0.5/jaxx-example/Validation/pom.xml lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml lutinjaxx/tags/0.5/jaxx-example/pom.xml lutinjaxx/tags/0.5/jaxx-swing-action/pom.xml lutinjaxx/tags/0.5/jaxx-util/pom.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/pom.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorErrors.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorOk.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/validator/ lutinjaxx/tags/0.5/pom.xml Removed: lutinjaxx/tags/0.5/jaxx-core/changelog lutinjaxx/tags/0.5/jaxx-core/pom.xml lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/PrintTagInfo.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataSource.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/css/Stylesheet.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/Util.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/BeanValidatorHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/FieldValidatorHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java lutinjaxx/tags/0.5/jaxx-core/src/main/resources/example.jnlp lutinjaxx/tags/0.5/jaxx-core/src/main/resources/manifest.mf lutinjaxx/tags/0.5/jaxx-core/src/test/resources/log4j.properties lutinjaxx/tags/0.5/jaxx-example/Calculator/pom.xml lutinjaxx/tags/0.5/jaxx-example/Components/pom.xml lutinjaxx/tags/0.5/jaxx-example/Counter/pom.xml lutinjaxx/tags/0.5/jaxx-example/LabelStyle/pom.xml lutinjaxx/tags/0.5/jaxx-example/Validation/pom.xml lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml lutinjaxx/tags/0.5/jaxx-example/pom.xml lutinjaxx/tags/0.5/jaxx-swing-action/pom.xml lutinjaxx/tags/0.5/jaxx-util/pom.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/pom.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx lutinjaxx/tags/0.5/pom.xml Log: [maven-release-plugin] copy for tag 0.5 Copied: lutinjaxx/tags/0.5 (from rev 948, lutinjaxx/trunk) Deleted: lutinjaxx/tags/0.5/jaxx-core/changelog =================================================================== --- lutinjaxx/trunk/jaxx-core/changelog 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/changelog 2008-10-21 07:31:05 UTC (rev 990) @@ -1,9 +0,0 @@ - ver-0-5 chemit 20081002 - * 20081013 [chemit] can generate logger on jaxx files - * 20081011 [chemit] improve site - * 20081011 [chemit] fix bug on JavaFileParser : works again - * 20081002 [chemit] Using lutinproject 3.0, changing groupId to org.codelutin - * 20081002 [chemit] use a single module jaxx-core (no more core, runtime and jaxx-swing modules) - * 20081002 [chemit] Introduce JAXXContext - * 20081002 [chemit] Fix bug on method creation via scripting - * 20081002 [chemit] Improve i18n integration (works now also for tabs) Copied: lutinjaxx/tags/0.5/jaxx-core/changelog (from rev 951, lutinjaxx/trunk/jaxx-core/changelog) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/changelog (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/changelog 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,10 @@ + ver-0-5 chemit 20081002 + * 20081017 [chemit] add validator support + * 20081013 [chemit] can generate logger on jaxx files + * 20081011 [chemit] improve site + * 20081011 [chemit] fix bug on JavaFileParser : works again + * 20081002 [chemit] Using lutinproject 3.0, changing groupId to org.codelutin + * 20081002 [chemit] use a single module jaxx-core (no more core, runtime and jaxx-swing modules) + * 20081002 [chemit] Introduce JAXXContext + * 20081002 [chemit] Fix bug on method creation via scripting + * 20081002 [chemit] Improve i18n integration (works now also for tabs) Deleted: lutinjaxx/tags/0.5/jaxx-core/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-core/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,70 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>lutinjaxx</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <artifactId>jaxx-core</artifactId> - - <dependencies> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-util</artifactId> - </dependency> - - <!-- pour acceder aux BeansInfos swing via Introspector --> - <dependency> - <groupId>com.sun</groupId> - <artifactId>dt</artifactId> - <!--scope>system</scope--> - </dependency> - - <!-- pour utiliser javaHelp --> - <dependency> - <groupId>javax.help</groupId> - <artifactId>javahelp</artifactId> - </dependency> - - <dependency> - <groupId>com.opensymphony</groupId> - <artifactId>xwork</artifactId> - </dependency> - - <dependency> - <groupId>org.swinglabs</groupId> - <artifactId>jxlayer</artifactId> - </dependency> - - </dependencies> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>jaxx-core</name> - <description>Jaxx lutin library core</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - <packaging>jar</packaging> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.son}</connection> - <developerConnection>${scm.developerConnection.son}</developerConnection> - <url>${scm.url.son}</url> - </scm> -</project> Copied: lutinjaxx/tags/0.5/jaxx-core/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-core/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>lutinjaxx</artifactId> + <version>0.5</version> + </parent> + + <artifactId>jaxx-core</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-util</artifactId> + </dependency> + + <!-- pour acceder aux BeansInfos swing via Introspector --> + <dependency> + <groupId>com.sun</groupId> + <artifactId>dt</artifactId> + <!--scope>system</scope--> + </dependency> + + <!-- pour utiliser javaHelp --> + <dependency> + <groupId>javax.help</groupId> + <artifactId>javahelp</artifactId> + </dependency> + + <dependency> + <groupId>com.opensymphony</groupId> + <artifactId>xwork</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>jaxx-core</name> + <description>Jaxx lutin library core</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + <packaging>jar</packaging> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-core</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-core</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-core?root=buix</url> + </scm> +</project> Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/PrintTagInfo.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/PrintTagInfo.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/PrintTagInfo.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,71 +0,0 @@ -package jaxx; - -import jaxx.compiler.JAXXCompiler; -import jaxx.introspection.JAXXPropertyDescriptor; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.reflect.MethodDescriptor; -import jaxx.tags.DefaultObjectHandler; -import jaxx.tags.TagManager; - -/** Generates information about a tag for use on the jaxxframework.org web site. */ -public class PrintTagInfo { - /** - * Displays information about the class name in arg[0]. - * - * @param arg command-line arguments - * @throws Exception if an error occurs - */ - public static void main(String[] arg) throws Exception { - JAXXCompiler.init(); - - ClassDescriptor beanClass = ClassDescriptorLoader.getClassDescriptor(arg[0]); - DefaultObjectHandler handler = TagManager.getTagHandler(beanClass); - - DefaultObjectHandler superHandler = TagManager.getTagHandler(beanClass.getSuperclass()); - - // dump all bean properties - System.out.println("Properties in " + beanClass); - JAXXPropertyDescriptor[] properties = handler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); - JAXXPropertyDescriptor[] superProperties = superHandler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); - for (JAXXPropertyDescriptor property : properties) { - if (property.getWriteMethodDescriptor() == null) - continue; - - boolean found = false; - String name = property.getName(); - for (JAXXPropertyDescriptor superProperty : superProperties) { - if (superProperty.getName().equals(name)) { - found = true; - break; - } - } - if (!found) { - if (property.getPropertyType() == null) - System.err.println(name + " has null type"); - else { - System.out.println("{{EquivalentAttribute|" + name + "|" + arg[0].replace('.', '/') + - "|set" + JAXXCompiler.capitalize(name) + "|" + - JAXXCompiler.getCanonicalName(property.getPropertyType()) + "}}"); - System.out.println("|-"); - } - } - } - - System.out.println(); - System.out.println(); - - // dump all bound methods - MethodDescriptor[] methods = beanClass.getMethodDescriptors(); - System.out.println("Bound methods in " + beanClass); - for (MethodDescriptor method : methods) { - try { - if (handler.isMemberBound(method.getName())) - System.out.println("* <tt>" + method.getName() + "()</tt>"); - } - catch (Throwable e) { - // ignore ? - } - } - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/PrintTagInfo.java (from rev 978, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/PrintTagInfo.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/PrintTagInfo.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/PrintTagInfo.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,117 @@ +package jaxx; + +import jaxx.compiler.JAXXCompiler; +import jaxx.introspection.JAXXPropertyDescriptor; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.MethodDescriptor; +import jaxx.tags.DefaultObjectHandler; +import jaxx.tags.TagManager; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; + +/** Generates information about a tag for use on the jaxxframework.org web site. */ +public class PrintTagInfo { + /** + * Displays information about the class name in arg[0]. + * + * @param arg command-line arguments + * @throws Exception if an error occurs + */ + public static void main(String[] arg) throws Exception { + if (arg.length < 1) { + throw new IllegalArgumentException("programm needs at least two parameters : the file where to put the result, and at least one fqn class to treate"); + } + String firstarg = arg[0]; + boolean toFile = false; + BufferedWriter w; + if (firstarg.startsWith("file:")) { + w = new BufferedWriter(new FileWriter(firstarg.substring(5))); + toFile = true; + } else { + w = new BufferedWriter(new OutputStreamWriter(System.out)); + } + + try { + JAXXCompiler.loadLibraries(false); + for (int i = toFile ? 1 : 0; i < arg.length; i++) { + String className = arg[i]; + treateClass(w, className); + } + } finally { + w.flush(); + w.close(); + } + + } + + protected static void treateClass(BufferedWriter w, String className) throws ClassNotFoundException, IOException { + + ClassDescriptor beanClass = ClassDescriptorLoader.getClassDescriptor(className); + DefaultObjectHandler handler = TagManager.getTagHandler(beanClass); + + DefaultObjectHandler superHandler = TagManager.getTagHandler(beanClass.getSuperclass()); + + // dump all bean properties + w.append("Properties in ").append(String.valueOf(beanClass)); + w.newLine(); + JAXXPropertyDescriptor[] properties = handler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); + JAXXPropertyDescriptor[] superProperties = superHandler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); + for (JAXXPropertyDescriptor property : properties) { + if (property.getWriteMethodDescriptor() == null) { + continue; + } + + boolean found = false; + String name = property.getName(); + for (JAXXPropertyDescriptor superProperty : superProperties) { + if (superProperty.getName().equals(name)) { + found = true; + break; + } + } + if (!found) { + if (property.getPropertyType() == null) { + System.err.println(name + " has null type"); + } else { + w.append("{{EquivalentAttribute|"); + w.append(name); + w.append("|"); + w.append(className.replace('.', '/')); + w.append("|set"); + w.append(JAXXCompiler.capitalize(name)); + w.append("|"); + w.append(JAXXCompiler.getCanonicalName(property.getPropertyType())); + w.append("}}"); + w.append("|-"); + w.newLine(); + } + } + } + + w.newLine(); + w.newLine(); + + // dump all bound methods + dumpMethods(w, beanClass, handler); + } + + protected static void dumpMethods(BufferedWriter w, ClassDescriptor beanClass, DefaultObjectHandler handler) throws IOException { + MethodDescriptor[] methods = beanClass.getMethodDescriptors(); + w.append("Bound methods in ").append(String.valueOf(beanClass)); + w.newLine(); + for (MethodDescriptor method : methods) { + try { + if (handler.isMemberBound(method.getName())) { + w.append("* <tt>").append(method.getName()).append("()</tt>"); + w.newLine(); + } + } catch (Throwable e) { + // ignore ? + } + } + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,487 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.compiler; - -import jaxx.CompilerException; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.reflect.MethodDescriptor; -import jaxx.tags.DefaultComponentHandler; -import jaxx.tags.TagHandler; -import jaxx.tags.TagManager; -import jaxx.types.TypeManager; - -import java.awt.Container; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -/** - * Represents an object in the <code>.java</code> file being generated during compilation. There is - * a <code>CompiledObject</code> for each class tag encountered, and certain tags may generate - * additional objects for various reasons. - */ -public class CompiledObject { - /** The object's id. */ - private String id; - - /** Java code referring to the object. */ - private String javaCode; - - /** The object's class. */ - private ClassDescriptor objectClass; - - /** The style class. */ - private String styleClass; - - /** The container containing this CompiledObject. */ - private CompiledObject parent; - - /** true if this object overrides an object of the same id in a superclass of the object being compiled */ - private boolean override; - - /** - * Comma-separated Java code snippets representing the parameters that should be passed to the object's - * constructor. - */ - private String constructorParams; - - /** - * Java code snippet which performs basic initialization of the object (after it has already been constructed). - * Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other - * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. - */ - private StringBuffer initializationCode = new StringBuffer(); - - /** - * Java code snippet which completes setup by adding any child objects, or otherwise manipulates any refererenced - * objects. Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other - * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. - */ - private StringBuffer additionCode = new StringBuffer(); - - /** List of all registered event handlers. */ - private List<EventHandler> eventHandlers = new ArrayList<EventHandler>(); - - /** All properties that have been applied to this CompiledObject. */ - private Map<String, String> properties = new HashMap<String, String>(); - - - /** - * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a - * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. - * - * @param id the object's id - * @param objectClass the object's class - * @param compiler the current <code>JAXXCompiler</code> - * @throws NullPointerException if id or class is null - */ - public CompiledObject(String id, ClassDescriptor objectClass, JAXXCompiler compiler) { - this(id, objectClass, compiler, false); - } - - - /** - * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a - * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. - * - * @param id the object's id - * @param objectClass the object's class - * @param compiler the current <code>JAXXCompiler</code> - * @param force <code>true</code> to force acceptance of invalid ids - * @throws NullPointerException if id or class is null - */ - public CompiledObject(String id, ClassDescriptor objectClass, JAXXCompiler compiler, boolean force) { - this(id, id, objectClass, compiler, force); - } - - - /** - * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a - * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. - * - * @param id the object's id - * @param javaCode Java code referring to the object - * @param objectClass the object's class - * @param force <code>true</code> to force acceptance of invalid ids - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if the id is not a valid Java identifier - * @throws NullPointerException if id or class is null - */ - public CompiledObject(String id, String javaCode, ClassDescriptor objectClass, JAXXCompiler compiler, boolean force) throws CompilerException { - if (!force) { - if (!isValidID(id)) { - compiler.reportError("the id '" + id + "' is not a valid Java identifier"); - } - } - this.id = id; - this.javaCode = javaCode; - - if (objectClass == null) { - throw new NullPointerException(); - } - this.objectClass = objectClass; - } - - - public static boolean isValidID(String id) { - boolean valid = true; - if (id.length() == 0) - valid = false; - if (valid) { - if (!Character.isJavaIdentifierStart(id.charAt(0))) { - valid = false; - } - if (valid) { - for (int i = 1; i < id.length(); i++) { - if (!Character.isJavaIdentifierPart(id.charAt(i))) { - valid = false; - break; - } - } - } - } - return valid; - } - - - /** - * True if this object overrides an object in the superclass of the class being compiled. For this to be true, the - * class currently being compiled must be a subclass of another <code>JAXXObject</code> which has an - * identically-named object. - * - * @return <code>true</code> if this object is an override - * @see #setOverride - */ - public boolean isOverride() { - return override; - } - - - /** - * Sets whether this class overrides an identically-named object in the parent class. - * - * @param override <code>true</code> if this object is an override - * @see #isOverride - */ - public void setOverride(boolean override) { - this.override = override; - } - - - /** - * Returns this object's CSS style class. - * - * @return the value of the <code>styleClass</code> attribute - */ - public String getStyleClass() { - return styleClass; - } - - - /** - * Sets this object's CSS style class. - * - * @param styleClass the new style class - */ - public void setStyleClass(String styleClass) { - this.styleClass = styleClass; - } - - - /** - * Returns this object's parent container. Non-visual components (and the root container) return <code>null</code>. - * - * @return the object's parent container - */ - public CompiledObject getParent() { - return parent; - } - - - /** - * Sets this object's parent container. - * - * @param parent the parent container - */ - public void setParent(CompiledObject parent) { - if (!ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(parent.getObjectClass())) { - throw new IllegalArgumentException("parent must descend from java.awt.Container"); - } - this.parent = parent; - } - - - /** - * Returns the name of the method that should be generated in the compiled <code>.java</code> file - * in order to create this object. This is just a suggestion and may be ignored. - * - * @return the suggested name of the method which initializes this object - */ - public String getCreationMethodName() { - return "create" + JAXXCompiler.capitalize(getId()); - } - - - /** - * Returns the name of the method that should be generated in the compiled <code>.java</code> file - * in order to add children to this object. This is just a suggestion and may be ignored. - * - * @return the suggested name of the method which completes this object's setup - */ - public String getAdditionMethodName() { - return "addChildrenTo" + JAXXCompiler.capitalize(getId()); - } - - - /** - * Returns the type of this object. - * - * @return the class this <code>CompiledObject</code> represents - */ - public ClassDescriptor getObjectClass() { - return objectClass; - } - - - /** - * Returns this object's id. Generally, a field with this name will be created in the compiled <code>.java</code> - * file in order to represent this object. - * - * @return the id used to refer to this object - */ - public String getId() { - return id; - } - - - /** - * Returns Java code used to refer to this object in the compiled Java file. This is usually the same as its - * id. - * - * @return the Java code for this object - */ - public String getJavaCode() { - //if (isOverride()) // handle cases where object is overridden to be a different class - // return "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; - //else - //TODO Check if this is safe - return javaCode; - } - - - /** - * Returns a list of comma-separated Java code snippets that represent the parameters to pass to this - * object's constructor. - * - * @return the raw constructor params - * @see #setConstructorParams - */ - public String getConstructorParams() { - return constructorParams; - } - - - /** - * Sets the parameters to pass to this object's constructor. - * - * @param constructorParams comma-separated Java code snippets representing constructor params - * @see #getConstructorParams - */ - public void setConstructorParams(String constructorParams) { - this.constructorParams = constructorParams; - } - - - /** - * Returns the code that performs basic initialization of this object, after it has already been constructed. - * This basic code should not reference any other <code>CompiledObjects</code> as they may not have - * been created yet. - * - * @param compiler compiler to use - * @return the code which initializes this object - */ - public String getInitializationCode(JAXXCompiler compiler) { - StringBuffer result = new StringBuffer(initializationCode.toString()); - for (Object eventHandler : eventHandlers) { - EventHandler handler = (EventHandler) eventHandler; - result.append(getInitializationCode(handler, compiler)); - } - return result.toString(); - } - - - protected String getInitializationCode(EventHandler handler, JAXXCompiler compiler) { - MethodDescriptor addMethod = handler.getAddMethod(); - ClassDescriptor listenerClass = addMethod.getParameterTypes()[0]; - return getJavaCode() + '.' + addMethod.getName() + "((" + JAXXCompiler.getCanonicalName(listenerClass) + - ") jaxx.runtime.Util.getEventListener(" + JAXXCompiler.getCanonicalName(listenerClass) + ".class, " + - TypeManager.getJavaCode(handler.getListenerMethod().getName()) + ", " + compiler.getRootObject().getJavaCode() + ", " + - TypeManager.getJavaCode(compiler.getEventHandlerMethodName(handler)) + "));" + JAXXCompiler.getLineSeparator(); - } - - - /** - * Returns Java code to complete final setup on this object. This code may reference other - * <code>CompiledObjects</code>, as they are guaranteed to have all been created by this point. - * - * @return code which adds children and performs final setup - */ - public String getAdditionCode() { - return additionCode.toString(); - } - - - /** - * Appends code to the initialization code block. A line separator is automatically appended to the end. - * - * @param code the code to add to the initialization block - * @see #getInitializationCode - */ - public void appendInitializationCode(String code) { - this.initializationCode.append(code); - this.initializationCode.append(JAXXCompiler.getLineSeparator()); - } - - - /** - * Appends code to the addition code block. A line separator is automatically appended to the end. - * - * @param code the code to add to the addition block - * @see #getAdditionCode - */ - public void appendAdditionCode(String code) { - this.additionCode.append(code); - this.additionCode.append(JAXXCompiler.getLineSeparator()); - } - - - /** - * Stores a property for this object. The only effect of calling this method is that the property will - * be returned by <code>getProperties()</code>. - * - * @param property the name of the property - * @param value the property's value - * @see #getProperties - */ - public void addProperty(String property, String value) { - properties.put(property, value); - } - - - /** - * Returns all properties which have been set for this object. - * - * @return a <code>Map</code> containing all properties defined for this object - * @see #addProperty - */ - public Map/*<String, String>*/ getProperties() { - return properties; - } - - - // TODO: remove this temporary method and complete switchover to MethodDescriptors - public void addEventHandler(String eventId, Method addMethod, Method listenerMethod, String code, JAXXCompiler compiler) { - try { - ClassDescriptor descriptor = ClassDescriptorLoader.getClassDescriptor(getObjectClass().getName()); - String listenerClassName = addMethod.getParameterTypes()[0].getName(); - ClassDescriptor listenerDescriptor = ClassDescriptorLoader.getClassDescriptor(listenerClassName); - MethodDescriptor addMethodDescriptor = descriptor.getMethodDescriptor(addMethod.getName(), new ClassDescriptor[]{listenerDescriptor}); - MethodDescriptor listenerMethodDescriptor = listenerDescriptor.getMethodDescriptor(listenerMethod.getName(), new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(listenerMethod.getParameterTypes()[0].getName())}); - addEventHandler(eventId, addMethodDescriptor, listenerMethodDescriptor, code, compiler); - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - - - /** - * Adds an event listener to this object. The generated code will appear in the initialization block. - * - * @param eventId unique (per CompiledObject) identifier for the event handler - * @param addMethod the method which adds the event listener - * @param listenerMethod the method (in the listener class) which is called when the event is fired - * @param code the Java code for the listenerMethod's body - * @param compiler the current <code>JAXXCompiler</code> - * @see #getInitializationCode - */ - public void addEventHandler(String eventId, MethodDescriptor addMethod, MethodDescriptor listenerMethod, String code, JAXXCompiler compiler) { - EventHandler handler = new EventHandler(getId() + "." + eventId, getJavaCode(), addMethod, addMethod.getParameterTypes()[0], listenerMethod, code); - compiler.registerEventHandler(handler); - eventHandlers.add(handler); - - if (getJavaCode().indexOf(".") != -1) { // object lives in another JAXX file and consequently its initialization code won't be output - compiler.initializer.append(getInitializationCode(handler, compiler)); - } - } - - - /** - * Adds a child component to this container. The child is added without layout constraints. - * - * @param child the component to add - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if this object is not a container - * @see #addChild(CompiledObject, String, JAXXCompiler) - */ - public void addChild(CompiledObject child, JAXXCompiler compiler) throws CompilerException { - addChild(child, null, compiler); - } - - - /** - * Adds a child component to this container. This variant allows the Java code for a layout constraints - * object to be specified. - * - * @param child the component to add - * @param constraints Java code for the layout constraints object - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if this object is not a container - * @see #addChild(CompiledObject, JAXXCompiler) - */ - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - try { - if (constraints != null) { - constraints = compiler.checkJavaCode(constraints); - } - } - catch (CompilerException e) { - compiler.reportError("While parsing 'constraints' attribute: " + e.getMessage()); - } - - if (!child.isOverride()) { - TagHandler tagHandler = TagManager.getTagHandler(getObjectClass()); - if (tagHandler instanceof DefaultComponentHandler && !((DefaultComponentHandler) tagHandler).isContainer()) { - compiler.reportError("component " + this + " may not have children"); - } - - String containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); - String delegateCode = containerDelegate != null ? "." + containerDelegate + "()" : ""; - - child.setParent(this); - - if (constraints != null) { - appendAdditionCode(getJavaCode() + delegateCode + ".add(" + child.getJavaCode() + ", " + constraints + ");"); - } - else { - appendAdditionCode(getJavaCode() + delegateCode + ".add(" + child.getJavaCode() + ");"); - } - } - } - - - public String toString() { - return getObjectClass().getName() + "[id='" + id + "']"; - } - - - public void registerDataBinding(String src, String property, String assignment, JAXXCompiler compiler) throws CompilerException { - compiler.registerDataBinding(src, getId() + "." + property, assignment); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,519 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.compiler; + +import jaxx.CompilerException; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.MethodDescriptor; +import jaxx.tags.DefaultComponentHandler; +import jaxx.tags.TagHandler; +import jaxx.tags.TagManager; +import jaxx.types.TypeManager; + +import java.awt.Container; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * Represents an object in the <code>.java</code> file being generated during compilation. There is + * a <code>CompiledObject</code> for each class tag encountered, and certain tags may generate + * additional objects for various reasons. + */ +public class CompiledObject { + /** The object's id. */ + private String id; + + /** Java code referring to the object. */ + private String javaCode; + + /** The object's class. */ + private ClassDescriptor objectClass; + + /** The style class. */ + private String styleClass; + + /** The container containing this CompiledObject. */ + private CompiledObject parent; + + /** true if this object overrides an object of the same id in a superclass of the object being compiled */ + private boolean override; + + /** + * Comma-separated Java code snippets representing the parameters that should be passed to the object's + * constructor. + */ + private String constructorParams; + + /** + * Java code snippet which performs basic initialization of the object (after it has already been constructed). + * Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other + * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. + */ + private StringBuffer initializationCode = new StringBuffer(); + + /** + * Java code snippet which completes setup by adding any child objects, or otherwise manipulates any refererenced + * objects. Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other + * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. + */ + private StringBuffer additionCode = new StringBuffer(); + + /** List of all registered event handlers. */ + private List<EventHandler> eventHandlers = new ArrayList<EventHandler>(); + + /** All properties that have been applied to this CompiledObject. */ + private Map<String, String> properties = new HashMap<String, String>(); + + /** generic types of the compiled object */ + private String[] genericTypes; + + /** + * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a + * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. + * + * @param id the object's id + * @param objectClass the object's class + * @param compiler the current <code>JAXXCompiler</code> + * @throws NullPointerException if id or class is null + */ + public CompiledObject(String id, ClassDescriptor objectClass, JAXXCompiler compiler) { + this(id, objectClass, compiler, false); + } + + + /** + * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a + * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. + * + * @param id the object's id + * @param objectClass the object's class + * @param compiler the current <code>JAXXCompiler</code> + * @param force <code>true</code> to force acceptance of invalid ids + * @throws NullPointerException if id or class is null + */ + public CompiledObject(String id, ClassDescriptor objectClass, JAXXCompiler compiler, boolean force) { + this(id, id, objectClass, compiler, force); + } + + + /** + * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a + * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. + * + * @param id the object's id + * @param javaCode Java code referring to the object + * @param objectClass the object's class + * @param force <code>true</code> to force acceptance of invalid ids + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if the id is not a valid Java identifier + * @throws NullPointerException if id or class is null + */ + public CompiledObject(String id, String javaCode, ClassDescriptor objectClass, JAXXCompiler compiler, boolean force) throws CompilerException { + if (!force) { + if (!isValidID(id)) { + compiler.reportError("the id '" + id + "' is not a valid Java identifier"); + } + } + this.id = id; + this.javaCode = javaCode; + + if (objectClass == null) { + throw new NullPointerException(); + } + this.objectClass = objectClass; + } + + + public static boolean isValidID(String id) { + boolean valid = true; + if (id.length() == 0) { + valid = false; + } + if (valid) { + if (!Character.isJavaIdentifierStart(id.charAt(0))) { + valid = false; + } + if (valid) { + for (int i = 1; i < id.length(); i++) { + if (!Character.isJavaIdentifierPart(id.charAt(i))) { + valid = false; + break; + } + } + } + } + return valid; + } + + + /** + * True if this object overrides an object in the superclass of the class being compiled. For this to be true, the + * class currently being compiled must be a subclass of another <code>JAXXObject</code> which has an + * identically-named object. + * + * @return <code>true</code> if this object is an override + * @see #setOverride + */ + public boolean isOverride() { + return override; + } + + + /** + * Sets whether this class overrides an identically-named object in the parent class. + * + * @param override <code>true</code> if this object is an override + * @see #isOverride + */ + public void setOverride(boolean override) { + this.override = override; + } + + + /** + * Returns this object's CSS style class. + * + * @return the value of the <code>styleClass</code> attribute + */ + public String getStyleClass() { + return styleClass; + } + + + /** + * Sets this object's CSS style class. + * + * @param styleClass the new style class + */ + public void setStyleClass(String styleClass) { + this.styleClass = styleClass; + } + + + /** + * Returns this object's parent container. Non-visual components (and the root container) return <code>null</code>. + * + * @return the object's parent container + */ + public CompiledObject getParent() { + return parent; + } + + + /** + * Sets this object's parent container. + * + * @param parent the parent container + */ + public void setParent(CompiledObject parent) { + if (!ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(parent.getObjectClass())) { + throw new IllegalArgumentException("parent must descend from java.awt.Container"); + } + this.parent = parent; + } + + + /** + * Returns the name of the method that should be generated in the compiled <code>.java</code> file + * in order to create this object. This is just a suggestion and may be ignored. + * + * @return the suggested name of the method which initializes this object + */ + public String getCreationMethodName() { + return "create" + JAXXCompiler.capitalize(getId()); + } + + + /** + * Returns the name of the method that should be generated in the compiled <code>.java</code> file + * in order to add children to this object. This is just a suggestion and may be ignored. + * + * @return the suggested name of the method which completes this object's setup + */ + public String getAdditionMethodName() { + return "addChildrenTo" + JAXXCompiler.capitalize(getId()); + } + + + /** + * Returns the type of this object. + * + * @return the class this <code>CompiledObject</code> represents + */ + public ClassDescriptor getObjectClass() { + return objectClass; + } + + + /** + * Returns this object's id. Generally, a field with this name will be created in the compiled <code>.java</code> + * file in order to represent this object. + * + * @return the id used to refer to this object + */ + public String getId() { + return id; + } + + + /** + * Returns Java code used to refer to this object in the compiled Java file. This is usually the same as its + * id. + * + * @return the Java code for this object + */ + public String getJavaCode() { + //if (isOverride()) // handle cases where object is overridden to be a different class + // return "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; + //else + //TODO Check if this is safe + return javaCode; + } + + + /** + * Returns a list of comma-separated Java code snippets that represent the parameters to pass to this + * object's constructor. + * + * @return the raw constructor params + * @see #setConstructorParams + */ + public String getConstructorParams() { + return constructorParams; + } + + + /** + * Sets the parameters to pass to this object's constructor. + * + * @param constructorParams comma-separated Java code snippets representing constructor params + * @see #getConstructorParams + */ + public void setConstructorParams(String constructorParams) { + this.constructorParams = constructorParams; + } + + + /** + * Returns the code that performs basic initialization of this object, after it has already been constructed. + * This basic code should not reference any other <code>CompiledObjects</code> as they may not have + * been created yet. + * + * @param compiler compiler to use + * @return the code which initializes this object + */ + public String getInitializationCode(JAXXCompiler compiler) { + StringBuffer result = new StringBuffer(initializationCode.toString()); + for (Object eventHandler : eventHandlers) { + EventHandler handler = (EventHandler) eventHandler; + result.append(getInitializationCode(handler, compiler)); + } + return result.toString(); + } + + + protected String getInitializationCode(EventHandler handler, JAXXCompiler compiler) { + MethodDescriptor addMethod = handler.getAddMethod(); + ClassDescriptor listenerClass = addMethod.getParameterTypes()[0]; + return getJavaCode() + '.' + addMethod.getName() + "((" + JAXXCompiler.getCanonicalName(listenerClass) + + ") jaxx.runtime.Util.getEventListener(" + JAXXCompiler.getCanonicalName(listenerClass) + ".class, " + + TypeManager.getJavaCode(handler.getListenerMethod().getName()) + ", " + compiler.getRootObject().getJavaCode() + ", " + + TypeManager.getJavaCode(compiler.getEventHandlerMethodName(handler)) + "));" + JAXXCompiler.getLineSeparator(); + } + + + /** + * Returns Java code to complete final setup on this object. This code may reference other + * <code>CompiledObjects</code>, as they are guaranteed to have all been created by this point. + * + * @return code which adds children and performs final setup + */ + public String getAdditionCode() { + return additionCode.toString(); + } + + + /** + * Appends code to the initialization code block. A line separator is automatically appended to the end. + * + * @param code the code to add to the initialization block + * @see #getInitializationCode + */ + public void appendInitializationCode(String code) { + this.initializationCode.append(code); + this.initializationCode.append(JAXXCompiler.getLineSeparator()); + } + + + /** + * Appends code to the addition code block. A line separator is automatically appended to the end. + * + * @param code the code to add to the addition block + * @see #getAdditionCode + */ + public void appendAdditionCode(String code) { + this.additionCode.append(code); + this.additionCode.append(JAXXCompiler.getLineSeparator()); + } + + + /** + * Stores a property for this object. The only effect of calling this method is that the property will + * be returned by <code>getProperties()</code>. + * + * @param property the name of the property + * @param value the property's value + * @see #getProperties + */ + public void addProperty(String property, String value) { + properties.put(property, value); + } + + + /** + * Returns all properties which have been set for this object. + * + * @return a <code>Map</code> containing all properties defined for this object + * @see #addProperty + */ + public Map/*<String, String>*/ getProperties() { + return properties; + } + + + // TODO: remove this temporary method and complete switchover to MethodDescriptors + public void addEventHandler(String eventId, Method addMethod, Method listenerMethod, String code, JAXXCompiler compiler) { + try { + ClassDescriptor descriptor = ClassDescriptorLoader.getClassDescriptor(getObjectClass().getName()); + String listenerClassName = addMethod.getParameterTypes()[0].getName(); + ClassDescriptor listenerDescriptor = ClassDescriptorLoader.getClassDescriptor(listenerClassName); + MethodDescriptor addMethodDescriptor = descriptor.getMethodDescriptor(addMethod.getName(), new ClassDescriptor[]{listenerDescriptor}); + MethodDescriptor listenerMethodDescriptor = listenerDescriptor.getMethodDescriptor(listenerMethod.getName(), new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(listenerMethod.getParameterTypes()[0].getName())}); + addEventHandler(eventId, addMethodDescriptor, listenerMethodDescriptor, code, compiler); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + + /** + * Adds an event listener to this object. The generated code will appear in the initialization block. + * + * @param eventId unique (per CompiledObject) identifier for the event handler + * @param addMethod the method which adds the event listener + * @param listenerMethod the method (in the listener class) which is called when the event is fired + * @param code the Java code for the listenerMethod's body + * @param compiler the current <code>JAXXCompiler</code> + * @see #getInitializationCode + */ + public void addEventHandler(String eventId, MethodDescriptor addMethod, MethodDescriptor listenerMethod, String code, JAXXCompiler compiler) { + EventHandler handler = new EventHandler(getId() + "." + eventId, getJavaCode(), addMethod, addMethod.getParameterTypes()[0], listenerMethod, code); + compiler.registerEventHandler(handler); + eventHandlers.add(handler); + + if (getJavaCode().indexOf(".") != -1) { // object lives in another JAXX file and consequently its initialization code won't be output + compiler.appendInitializerCode(getInitializationCode(handler, compiler)); + } + } + + + /** + * Adds a child component to this container. The child is added without layout constraints. + * + * @param child the component to add + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if this object is not a container + * @see #addChild(CompiledObject, String, JAXXCompiler) + */ + public void addChild(CompiledObject child, JAXXCompiler compiler) throws CompilerException { + addChild(child, null, compiler); + } + + + /** + * Adds a child component to this container. This variant allows the Java code for a layout constraints + * object to be specified. + * + * @param child the component to add + * @param constraints Java code for the layout constraints object + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if this object is not a container + * @see #addChild(CompiledObject, JAXXCompiler) + */ + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + try { + if (constraints != null) { + constraints = compiler.checkJavaCode(constraints); + } + } + catch (CompilerException e) { + compiler.reportError("While parsing 'constraints' attribute: " + e.getMessage()); + } + + if (!child.isOverride()) { + TagHandler tagHandler = TagManager.getTagHandler(getObjectClass()); + if (tagHandler instanceof DefaultComponentHandler && !((DefaultComponentHandler) tagHandler).isContainer()) { + compiler.reportError("component " + this + " may not have children"); + } + + String containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); + String delegateCode = containerDelegate != null ? "." + containerDelegate + "()" : ""; + + child.setParent(this); + String javaCode = child.getJavaCode(); + if (compiler.hasValidator()) { + // some validators are defined on this object + boolean found = compiler.isComponentUsedByValidator(child.getId()); + if (found) { + // box the child component in a JxLayer + javaCode = "jaxx.runtime.Util.boxComponentWithJxLayer(" + javaCode + ")"; + } + } + + if (constraints != null) { + appendAdditionCode(getJavaCode() + delegateCode + ".add(" + javaCode + ", " + constraints + ");"); + } else { + appendAdditionCode(getJavaCode() + delegateCode + ".add(" + javaCode + ");"); + } + } + } + + @Override + public String toString() { + return getObjectClass().getName() + "[id='" + id + "']"; + } + + + public void registerDataBinding(String src, String property, String assignment, JAXXCompiler compiler) throws CompilerException { + compiler.registerDataBinding(src, getId() + "." + property, assignment); + } + + /** @return the array of generic types of the compiled object, or a empty array if none defined */ + public ClassDescriptor[] getGenericTypes() { + if (genericTypes == null) { + return new ClassDescriptor[0]; + } + try { + ClassDescriptor[] result = new ClassDescriptor[genericTypes.length]; + for (int i = 0; i < result.length; i++) { + result[i] = ClassDescriptorLoader.getClassDescriptor(genericTypes[i], getObjectClass().getClassLoader()); + } + return result; + } + catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + public void setGenericTypes(String[] genericTypes) { + this.genericTypes = genericTypes; + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,78 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.compiler; - -import jaxx.CompilerException; -import jaxx.types.TypeManager; - -/** - * Represents a data binding in a JAXX file. <code>DataBinding</code> uses {@link DataSource} to - * track changes to a source expression and update the destination. - */ -public class DataBinding { - private String id; - - /** The DatSource which tracks source expression changes. */ - private DataSource dataSource; - - /** The data binding destination in the form <code><id>.<propertyName></code>. */ - private String dest; - - /** - * A Java snippet which will cause the destination property to be updated with the current value of - * the binding. - */ - private String assignment; - - /** The current <code>JAXXCompiler</code>. */ - private JAXXCompiler compiler; - - - /** - * Creates a new data binding. - * - * @param source the Java source code for the data binding expression - * @param dest the data binding destination in the form <code><id>.<propertyName></code> - * @param assignment Java snippet which will cause the destination property to be updated with the current value of the binding - * @param compiler the current <code>JAXXCompiler</code> - */ - public DataBinding(String source, String dest, String assignment, JAXXCompiler compiler) { - this.id = dest; - this.dataSource = new DataSource(id, source, compiler); - this.dest = dest; - this.assignment = assignment; - this.compiler = compiler; - } - - - public String getId() { - return id; - } - - - /** - * Compiles the data binding expression. This method calls methods in <code>JAXXCompiler</code> - * to add the Java code that performs the data binding setup. - * - * @param quickNoDependencies true to optimize bindings with no dependencies by simply running them at startup time - * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise - * @throws CompilerException if a compilation error occurs - */ - public boolean compile(boolean quickNoDependencies) throws CompilerException { - // DataSource.compile handles all of the listener additions - boolean result = dataSource.compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + TypeManager.getJavaCode(id) + ")"); - - if (!result && quickNoDependencies) { - if (!dest.endsWith(".layout")) // layout is specially handled early in the chain - compiler.initDataBindings.append(assignment).append(JAXXCompiler.getLineSeparator()); - return false; // no dependencies, just a static expression - } else { - if (compiler.processDataBinding.length() > 0) - compiler.processDataBinding.append("else "); - compiler.processDataBinding.append("if ($dest.equals(").append(TypeManager.getJavaCode(id)).append(")) { ").append(assignment).append("}\n").append(JAXXCompiler.getLineSeparator()); - return true; - } - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,78 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.compiler; + +import jaxx.CompilerException; +import jaxx.types.TypeManager; + +/** + * Represents a data binding in a JAXX file. <code>DataBinding</code> uses {@link DataSource} to + * track changes to a source expression and update the destination. + */ +public class DataBinding { + private String id; + + /** The DatSource which tracks source expression changes. */ + private DataSource dataSource; + + /** The data binding destination in the form <code><id>.<propertyName></code>. */ + private String dest; + + /** + * A Java snippet which will cause the destination property to be updated with the current value of + * the binding. + */ + private String assignment; + + /** The current <code>JAXXCompiler</code>. */ + private JAXXCompiler compiler; + + + /** + * Creates a new data binding. + * + * @param source the Java source code for the data binding expression + * @param dest the data binding destination in the form <code><id>.<propertyName></code> + * @param assignment Java snippet which will cause the destination property to be updated with the current value of the binding + * @param compiler the current <code>JAXXCompiler</code> + */ + public DataBinding(String source, String dest, String assignment, JAXXCompiler compiler) { + this.id = dest; + this.dataSource = new DataSource(id, source, compiler); + this.dest = dest; + this.assignment = assignment; + this.compiler = compiler; + } + + + public String getId() { + return id; + } + + + /** + * Compiles the data binding expression. This method calls methods in <code>JAXXCompiler</code> + * to add the Java code that performs the data binding setup. + * + * @param quickNoDependencies true to optimize bindings with no dependencies by simply running them at startup time + * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise + * @throws CompilerException if a compilation error occurs + */ + public boolean compile(boolean quickNoDependencies) throws CompilerException { + // DataSource.compile handles all of the listener additions + boolean result = dataSource.compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + TypeManager.getJavaCode(id) + ")"); + + if (!result && quickNoDependencies) { + if (!dest.endsWith(".layout")) // layout is specially handled early in the chain + compiler.appendInitDataBindings(assignment+ JAXXCompiler.getLineSeparator()); + return false; // no dependencies, just a static expression + } + if (compiler.haveProcessDataBinding()) { + compiler.appendProcessDataBinding("else "); + } + compiler.appendProcessDataBinding("if ($dest.equals(" + TypeManager.getJavaCode(id) + ")) { " + assignment + "}\n" + JAXXCompiler.getLineSeparator()); + return true; + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataSource.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataSource.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataSource.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,408 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.compiler; - -import jaxx.CompilerException; -import jaxx.UnsupportedAttributeException; -import jaxx.parser.JavaParser; -import jaxx.parser.JavaParserConstants; -import jaxx.parser.JavaParserTreeConstants; -import jaxx.parser.SimpleNode; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.reflect.FieldDescriptor; -import jaxx.reflect.MethodDescriptor; -import jaxx.tags.DefaultObjectHandler; -import jaxx.tags.TagManager; -import jaxx.types.TypeManager; - -import java.beans.Introspector; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Represents a Java expression which fires a <code>PropertyChangeEvent</code> when it can be - * determined that its value may have changed. Events are fired on a "best effort" basis, and events - * may either be fired too often (the value has not actually changed) or not often enough (the value - * changed but no event was fired). - */ -public class DataSource { - private class NULL { - } // type attached to "null" constants in parsed expressions - - private String id; - - /** The Java source code for the expression. */ - private String source; - - /** The current <code>JAXXCompiler</code>. */ - private JAXXCompiler compiler; - - /** List of symbols which this data source expression depends on. */ - private List<String> dependencySymbols = new ArrayList<String>(); - - private StringBuffer addListenerCode = new StringBuffer(); - private StringBuffer removeListenerCode = new StringBuffer(); - private boolean compiled; - - - /** - * Creates a new data source. After creating a <code>DataSource</code>, use {@link #compile} - * to cause it to function at runtime. - * - * @param id the DataSource's id - * @param source the Java source code for the data source expression - * @param compiler the current <code>JAXXCompiler</code> - */ - public DataSource(String id, String source, JAXXCompiler compiler) { - this.id = id; - this.source = source; - this.compiler = compiler; - } - - - public String getId() { - return id; - } - - /** - * Compiles the data source expression and listener. This method calls methods in <code>JAXXCompiler</code> - * to add the Java code that performs the data source setup. Adding listeners to <code>DataSource</code> is - * slightly more complicated than with ordinary classes, because <code>DataSource</code> only exists at compile - * time. You must pass in a Java expression which evaluates to a <code>PropertyChangeListener</code>; this - * expression will be compiled and evaluated at runtime to yield the <code>DataSource's</code> listener. - * - * @param propertyChangeListenerCode Java code snippet which evaluates to a <code>PropertyChangeListener</code> - * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise - * @throws CompilerException if a compilation error occurs - */ - public boolean compile(String propertyChangeListenerCode) throws CompilerException { - if (compiled) - throw new IllegalStateException(this + " has already been compiled"); - String id = compiler.getAutoId(ClassDescriptorLoader.getClassDescriptor(getClass())); - JavaParser p = new JavaParser(new StringReader(source + ";")); - while (!p.Line()) { - SimpleNode node = p.popNode(); - scanNode(node, id); - } - - if (dependencySymbols.size() > 0) - compiler.bodyCode.append("private PropertyChangeListener ").append(id).append(" = ").append(propertyChangeListenerCode).append(";\n"); - - compileListeners(); - compiled = true; - - return dependencySymbols.size() > 0; - } - - /** @return a list of symbols on which this data source depends. */ - public Collection<String> getDependencies() { - return Collections.unmodifiableList(dependencySymbols); - } - - /** - * Examines a node to identify any dependencies it contains. - * - * @param node node to scan - * @param listenerId id of listener - * @throws jaxx.CompilerException ? - */ - private void scanNode(SimpleNode node, String listenerId) throws CompilerException { - switch (node.getId()) { - case JavaParserTreeConstants.JJTMETHODDECLARATION: - break; - case JavaParserTreeConstants.JJTFIELDDECLARATION: - break; - - default: - int count = node.jjtGetNumChildren(); - for (int i = 0; i < count; i++) - scanNode(node.getChild(i), listenerId); - determineNodeType(node, listenerId); - } - } - - private ClassDescriptor determineLiteralType(SimpleNode node) { - assert node.getId() == JavaParserTreeConstants.JJTLITERAL; - if (node.jjtGetNumChildren() == 1) { - int id = node.getChild(0).getId(); - if (id == JavaParserTreeConstants.JJTBOOLEANLITERAL) - return ClassDescriptorLoader.getClassDescriptor(boolean.class); - else if (id == JavaParserTreeConstants.JJTNULLLITERAL) - return ClassDescriptorLoader.getClassDescriptor(NULL.class); - else - throw new RuntimeException("Expected BooleanLiteral or NullLiteral, found " + JavaParserTreeConstants.jjtNodeName[id]); - } else { - int id = node.firstToken.kind; - switch (id) { - case JavaParserConstants.INTEGER_LITERAL: - if (node.firstToken.image.toLowerCase().endsWith("l")) - return ClassDescriptorLoader.getClassDescriptor(long.class); - else - return ClassDescriptorLoader.getClassDescriptor(int.class); - case JavaParserConstants.CHARACTER_LITERAL: - return ClassDescriptorLoader.getClassDescriptor(char.class); - case JavaParserConstants.FLOATING_POINT_LITERAL: - if (node.firstToken.image.toLowerCase().endsWith("f")) - return ClassDescriptorLoader.getClassDescriptor(float.class); - else - return ClassDescriptorLoader.getClassDescriptor(double.class); - case JavaParserConstants.STRING_LITERAL: - return ClassDescriptorLoader.getClassDescriptor(String.class); - default: - throw new RuntimeException("Expected literal token, found " + JavaParserConstants.tokenImage[id]); - } - } - } - - /** - * Scans through a compound symbol (foo.bar.baz) to identify and track all trackable pieces of it. - * - * @param symbol symbol to scan - * @param contextClass - * @param isMethod - * @param listenerId - * @return the type of the symbol (or null if it could not be determined). - */ - private ClassDescriptor scanCompoundSymbol(String symbol, ClassDescriptor contextClass, boolean isMethod, String listenerId) { - String[] tokens = symbol.split("\\s*\\.\\s*"); - StringBuffer currentSymbol = new StringBuffer(); - StringBuffer tokensSeenSoFar = new StringBuffer(); - boolean accepted = true; // if this ends up false, it means we weren't able to figure out - // which object the method is being invoked on - boolean recognizeClassNames = true; - for (int j = 0; j < tokens.length - (isMethod ? 1 : 0); j++) { - accepted = false; - - if (tokensSeenSoFar.length() > 0) - tokensSeenSoFar.append('.'); - tokensSeenSoFar.append(tokens[j]); - if (currentSymbol.length() > 0) - currentSymbol.append('.'); - currentSymbol.append(tokens[j]); - - if (currentSymbol.indexOf(".") == -1) { - String memberName = currentSymbol.toString(); - CompiledObject object = compiler.getCompiledObject(memberName); - if (object != null) { - contextClass = object.getObjectClass(); - currentSymbol.setLength(0); - accepted = true; - recognizeClassNames = false; - } else { - try { - FieldDescriptor field = contextClass.getFieldDescriptor(memberName); - trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false, listenerId); - contextClass = field.getType(); - currentSymbol.setLength(0); - accepted = true; - recognizeClassNames = false; - } - catch (NoSuchFieldException e) { - if (j == 0 || j == 1 && tokens[0].equals(compiler.getRootObject().getId())) { // still in root context - FieldDescriptor[] newFields = compiler.getScriptFields(); - for (FieldDescriptor newField : newFields) { - if (newField.getName().equals(memberName)) { - addListener(tokensSeenSoFar.toString(), - null, - "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), - "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); - contextClass = newField.getType(); - assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; - currentSymbol.setLength(0); - accepted = true; - recognizeClassNames = false; - break; - } - } - } - } - } - } - if (currentSymbol.length() > 0 && recognizeClassNames) { - contextClass = TagManager.resolveClass(currentSymbol.toString(), compiler); - if (contextClass != null) { - currentSymbol.setLength(0); - //accepted = true; - //recognizeClassNames = false; - // TODO: for now we don't handle statics - return null; - } - } - if (!accepted) - return null; - } - - return contextClass; - } - - /** - * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which - * can be tracked. - * - * @param expression - * @param listenerId - * @return - */ - private ClassDescriptor determineExpressionType(SimpleNode expression, String listenerId) { - assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; - SimpleNode prefix = expression.getChild(0); - if (prefix.jjtGetNumChildren() == 1) { - int type = prefix.getChild(0).getId(); - if (type == JavaParserTreeConstants.JJTLITERAL || type == JavaParserTreeConstants.JJTEXPRESSION) - prefix.setJavaType(prefix.getChild(0).getJavaType()); - else - if (type == JavaParserTreeConstants.JJTNAME && expression.jjtGetNumChildren() == 1) // name with no arguments after it - prefix.setJavaType(scanCompoundSymbol(prefix.getText().trim(), compiler.getRootObject().getObjectClass(), false, listenerId)); - } - - if (expression.jjtGetNumChildren() == 1) { - return prefix.getJavaType(); - } - - ClassDescriptor contextClass = prefix.getJavaType(); - if (contextClass == null) - contextClass = compiler.getRootObject().getObjectClass(); - String lastNode = prefix.getText().trim(); - - for (int i = 1; i < expression.jjtGetNumChildren(); i++) { - SimpleNode suffix = expression.getChild(i); - if (suffix.jjtGetNumChildren() == 1 && suffix.getChild(0).getId() == JavaParserTreeConstants.JJTARGUMENTS) { - if (suffix.getChild(0).jjtGetNumChildren() == 0) { // at the moment only no-argument methods are trackable - contextClass = scanCompoundSymbol(lastNode, contextClass, true, listenerId); - if (contextClass == null) - return null; - int dotPos = lastNode.lastIndexOf("."); - String objectCode = dotPos == -1 ? "" : lastNode.substring(0, dotPos); - for (int j = i - 2; j >= 0; j--) - objectCode = expression.getChild(j).getText() + objectCode; - if (objectCode.length() == 0) - objectCode = compiler.getRootObject().getJavaCode(); - String methodName = lastNode.substring(dotPos + 1).trim(); - try { - MethodDescriptor method = contextClass.getMethodDescriptor(methodName, new ClassDescriptor[0]); - trackMemberIfPossible(objectCode, contextClass, method.getName(), true, listenerId); - return method.getReturnType(); - } - catch (NoSuchMethodException e) { - // happens for methods defined in the current JAXX file via scripts - String propertyName = null; - if (methodName.startsWith("is")) - propertyName = Introspector.decapitalize(methodName.substring("is".length())); - else if (methodName.startsWith("get")) - propertyName = Introspector.decapitalize(methodName.substring("get".length())); - if (propertyName != null) { - MethodDescriptor[] newMethods = compiler.getScriptMethods(); - for (MethodDescriptor newMethod : newMethods) { - if (newMethod.getName().equals(methodName)) { - addListener(compiler.getRootObject().getId(), - null, - "addPropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), - "removePropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); - contextClass = newMethod.getReturnType(); - break; - } - } - } - } - } - } - lastNode = suffix.getText().trim(); - if (lastNode.startsWith(".")) - lastNode = lastNode.substring(1); - } - - return null; - } - - private void trackMemberIfPossible(String objectCode, ClassDescriptor objectClass, String memberName, boolean method, String listenerId) { - if (objectClass.isInterface()) // might be technically possible to track in some cases, but for now - return; // we can't create a DefaultObjectHandler for interfaces - - DefaultObjectHandler handler = TagManager.getTagHandler(objectClass); - try { - if (handler.isMemberBound(memberName)) { - addListener(objectCode + "." + memberName + (method ? "()" : ""), - objectCode, - handler.getAddMemberListenerCode(objectCode, id, memberName, listenerId, compiler), - handler.getRemoveMemberListenerCode(objectCode, id, memberName, listenerId, compiler)); - } - } - catch (UnsupportedAttributeException e) { - // ignore -- this is thrown for methods like toString(), for which there is no tracking and - // no setting support - } - } - - /** - * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which - * can be tracked. - * - * @param node node to scan - * @param listenerId - */ - private void determineNodeType(SimpleNode node, String listenerId) { - ClassDescriptor type = null; - if (node.jjtGetNumChildren() == 1) - type = node.getChild(0).getJavaType(); - switch (node.getId()) { - case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: - type = ClassDescriptorLoader.getClassDescriptor(Class.class); - break; - case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: - type = determineExpressionType(node, listenerId); - break; - case JavaParserTreeConstants.JJTLITERAL: - type = determineLiteralType(node); - break; - case JavaParserTreeConstants.JJTCASTEXPRESSION: - type = TagManager.resolveClass(node.getChild(0).getText(), compiler); - break; - } - node.setJavaType(type); - } - - private void addListener(String dependencySymbol, String objectCode, String addCode, String removeCode) { - if (!dependencySymbols.contains(dependencySymbol)) { - dependencySymbols.add(dependencySymbol); - if (objectCode != null) { - addListenerCode.append("if (").append(objectCode).append(" != null) {").append(JAXXCompiler.getLineSeparator()); - addListenerCode.append(" "); - } - addListenerCode.append(addCode); - if (objectCode != null) - addListenerCode.append("}"); - - if (objectCode != null) { - removeListenerCode.append("if (").append(objectCode).append(" != null) {").append(JAXXCompiler.getLineSeparator()); - removeListenerCode.append(" "); - } - removeListenerCode.append(removeCode); - if (objectCode != null) - removeListenerCode.append("}"); - } - } - - private void compileListeners() { - if (addListenerCode.length() > 0) { - if (compiler.applyDataBinding.length() > 0) - compiler.applyDataBinding.append("else "); - compiler.applyDataBinding.append("if ($binding.equals(").append(TypeManager.getJavaCode(id)).append(")) {").append(JAXXCompiler.getLineSeparator()); - compiler.applyDataBinding.append(" ").append(addListenerCode).append(JAXXCompiler.getLineSeparator()); - compiler.applyDataBinding.append("}").append(JAXXCompiler.getLineSeparator()); - } - - if (removeListenerCode.length() > 0) { - if (compiler.removeDataBinding.length() > 0) - compiler.removeDataBinding.append("else "); - compiler.removeDataBinding.append("if ($binding.equals(").append(TypeManager.getJavaCode(id)).append(")) {").append(JAXXCompiler.getLineSeparator()); - compiler.removeDataBinding.append(" ").append(removeListenerCode).append(JAXXCompiler.getLineSeparator()); - compiler.removeDataBinding.append("}").append(JAXXCompiler.getLineSeparator()); - } - } -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataSource.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataSource.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataSource.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/DataSource.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,439 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.compiler; + +import jaxx.CompilerException; +import jaxx.UnsupportedAttributeException; +import jaxx.parser.JavaParser; +import jaxx.parser.JavaParserConstants; +import jaxx.parser.JavaParserTreeConstants; +import jaxx.parser.SimpleNode; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.FieldDescriptor; +import jaxx.reflect.MethodDescriptor; +import jaxx.tags.DefaultObjectHandler; +import jaxx.tags.TagManager; +import jaxx.types.TypeManager; + +import java.beans.Introspector; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * Represents a Java expression which fires a <code>PropertyChangeEvent</code> when it can be + * determined that its value may have changed. Events are fired on a "best effort" basis, and events + * may either be fired too often (the value has not actually changed) or not often enough (the value + * changed but no event was fired). + */ +public class DataSource { + private class NULL { + } // type attached to "null" constants in parsed expressions + + private String id; + + /** The Java source code for the expression. */ + private String source; + + /** The current <code>JAXXCompiler</code>. */ + private JAXXCompiler compiler; + + /** List of symbols which this data source expression depends on. */ + private List<String> dependencySymbols = new ArrayList<String>(); + + private StringBuffer addListenerCode = new StringBuffer(); + private StringBuffer removeListenerCode = new StringBuffer(); + private boolean compiled; + + + /** + * Creates a new data source. After creating a <code>DataSource</code>, use {@link #compile} + * to cause it to function at runtime. + * + * @param id the DataSource's id + * @param source the Java source code for the data source expression + * @param compiler the current <code>JAXXCompiler</code> + */ + public DataSource(String id, String source, JAXXCompiler compiler) { + this.id = id; + this.source = source; + this.compiler = compiler; + } + + + public String getId() { + return id; + } + + /** + * Compiles the data source expression and listener. This method calls methods in <code>JAXXCompiler</code> + * to add the Java code that performs the data source setup. Adding listeners to <code>DataSource</code> is + * slightly more complicated than with ordinary classes, because <code>DataSource</code> only exists at compile + * time. You must pass in a Java expression which evaluates to a <code>PropertyChangeListener</code>; this + * expression will be compiled and evaluated at runtime to yield the <code>DataSource's</code> listener. + * + * @param propertyChangeListenerCode Java code snippet which evaluates to a <code>PropertyChangeListener</code> + * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise + * @throws CompilerException if a compilation error occurs + */ + public boolean compile(String propertyChangeListenerCode) throws CompilerException { + if (compiled) { + throw new IllegalStateException(this + " has already been compiled"); + } + String id = compiler.getAutoId(ClassDescriptorLoader.getClassDescriptor(getClass())); + JavaParser p = new JavaParser(new StringReader(source + ";")); + while (!p.Line()) { + SimpleNode node = p.popNode(); + scanNode(node, id); + } + + if (dependencySymbols.size() > 0) { + compiler.appendBodyCode("private PropertyChangeListener " + id + " = " + propertyChangeListenerCode + ";\n"); + } + + compileListeners(); + compiled = true; + + return dependencySymbols.size() > 0; + } + + /** @return a list of symbols on which this data source depends. */ + public Collection<String> getDependencies() { + return Collections.unmodifiableList(dependencySymbols); + } + + /** + * Examines a node to identify any dependencies it contains. + * + * @param node node to scan + * @param listenerId id of listener + * @throws jaxx.CompilerException ? + */ + private void scanNode(SimpleNode node, String listenerId) throws CompilerException { + switch (node.getId()) { + case JavaParserTreeConstants.JJTMETHODDECLARATION: + break; + case JavaParserTreeConstants.JJTFIELDDECLARATION: + break; + + default: + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + scanNode(node.getChild(i), listenerId); + } + determineNodeType(node, listenerId); + } + } + + private ClassDescriptor determineLiteralType(SimpleNode node) { + assert node.getId() == JavaParserTreeConstants.JJTLITERAL; + if (node.jjtGetNumChildren() == 1) { + int id = node.getChild(0).getId(); + if (id == JavaParserTreeConstants.JJTBOOLEANLITERAL) { + return ClassDescriptorLoader.getClassDescriptor(boolean.class); + } + if (id == JavaParserTreeConstants.JJTNULLLITERAL) { + return ClassDescriptorLoader.getClassDescriptor(NULL.class); + } + throw new RuntimeException("Expected BooleanLiteral or NullLiteral, found " + JavaParserTreeConstants.jjtNodeName[id]); + } + int id = node.firstToken.kind; + switch (id) { + case JavaParserConstants.INTEGER_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("l")) { + return ClassDescriptorLoader.getClassDescriptor(long.class); + } + return ClassDescriptorLoader.getClassDescriptor(int.class); + case JavaParserConstants.CHARACTER_LITERAL: + return ClassDescriptorLoader.getClassDescriptor(char.class); + case JavaParserConstants.FLOATING_POINT_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("f")) { + return ClassDescriptorLoader.getClassDescriptor(float.class); + } + return ClassDescriptorLoader.getClassDescriptor(double.class); + case JavaParserConstants.STRING_LITERAL: + return ClassDescriptorLoader.getClassDescriptor(String.class); + default: + throw new RuntimeException("Expected literal token, found " + JavaParserConstants.tokenImage[id]); + } + } + + /** + * Scans through a compound symbol (foo.bar.baz) to identify and track all trackable pieces of it. + * + * @param symbol symbol to scan + * @param contextClass + * @param isMethod + * @param listenerId + * @return the type of the symbol (or null if it could not be determined). + */ + private ClassDescriptor scanCompoundSymbol(String symbol, ClassDescriptor contextClass, boolean isMethod, String listenerId) { + String[] tokens = symbol.split("\\s*\\.\\s*"); + StringBuffer currentSymbol = new StringBuffer(); + StringBuffer tokensSeenSoFar = new StringBuffer(); + boolean accepted = true; // if this ends up false, it means we weren't able to figure out + // which object the method is being invoked on + boolean recognizeClassNames = true; + for (int j = 0; j < tokens.length - (isMethod ? 1 : 0); j++) { + accepted = false; + + if (tokensSeenSoFar.length() > 0) { + tokensSeenSoFar.append('.'); + } + tokensSeenSoFar.append(tokens[j]); + if (currentSymbol.length() > 0) { + currentSymbol.append('.'); + } + currentSymbol.append(tokens[j]); + + if (currentSymbol.indexOf(".") == -1) { + String memberName = currentSymbol.toString(); + CompiledObject object = compiler.getCompiledObject(memberName); + if (object != null) { + contextClass = object.getObjectClass(); + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + } else { + try { + FieldDescriptor field = contextClass.getFieldDescriptor(memberName); + trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false, listenerId); + contextClass = field.getType(); + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + } + catch (NoSuchFieldException e) { + if (j == 0 || j == 1 && tokens[0].equals(compiler.getRootObject().getId())) { // still in root context + FieldDescriptor[] newFields = compiler.getScriptFields(); + for (FieldDescriptor newField : newFields) { + if (newField.getName().equals(memberName)) { + addListener(tokensSeenSoFar.toString(), + null, + "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), + "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); + contextClass = newField.getType(); + assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + break; + } + } + } + } + } + } + if (currentSymbol.length() > 0 && recognizeClassNames) { + contextClass = TagManager.resolveClass(currentSymbol.toString(), compiler); + if (contextClass != null) { + currentSymbol.setLength(0); + //accepted = true; + //recognizeClassNames = false; + // TODO: for now we don't handle statics + return null; + } + } + if (!accepted) { + return null; + } + } + + return contextClass; + } + + /** + * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which + * can be tracked. + * + * @param expression + * @param listenerId + * @return + */ + private ClassDescriptor determineExpressionType(SimpleNode expression, String listenerId) { + assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; + SimpleNode prefix = expression.getChild(0); + if (prefix.jjtGetNumChildren() == 1) { + int type = prefix.getChild(0).getId(); + if (type == JavaParserTreeConstants.JJTLITERAL || type == JavaParserTreeConstants.JJTEXPRESSION) { + prefix.setJavaType(prefix.getChild(0).getJavaType()); + } else + if (type == JavaParserTreeConstants.JJTNAME && expression.jjtGetNumChildren() == 1) // name with no arguments after it + { + prefix.setJavaType(scanCompoundSymbol(prefix.getText().trim(), compiler.getRootObject().getObjectClass(), false, listenerId)); + } + } + + if (expression.jjtGetNumChildren() == 1) { + return prefix.getJavaType(); + } + + ClassDescriptor contextClass = prefix.getJavaType(); + if (contextClass == null) { + contextClass = compiler.getRootObject().getObjectClass(); + } + String lastNode = prefix.getText().trim(); + + for (int i = 1; i < expression.jjtGetNumChildren(); i++) { + SimpleNode suffix = expression.getChild(i); + if (suffix.jjtGetNumChildren() == 1 && suffix.getChild(0).getId() == JavaParserTreeConstants.JJTARGUMENTS) { + if (suffix.getChild(0).jjtGetNumChildren() == 0) { // at the moment only no-argument methods are trackable + contextClass = scanCompoundSymbol(lastNode, contextClass, true, listenerId); + if (contextClass == null) { + return null; + } + int dotPos = lastNode.lastIndexOf("."); + String objectCode = dotPos == -1 ? "" : lastNode.substring(0, dotPos); + for (int j = i - 2; j >= 0; j--) { + objectCode = expression.getChild(j).getText() + objectCode; + } + if (objectCode.length() == 0) { + objectCode = compiler.getRootObject().getJavaCode(); + } + String methodName = lastNode.substring(dotPos + 1).trim(); + try { + MethodDescriptor method = contextClass.getMethodDescriptor(methodName, new ClassDescriptor[0]); + trackMemberIfPossible(objectCode, contextClass, method.getName(), true, listenerId); + return method.getReturnType(); + } + catch (NoSuchMethodException e) { + // happens for methods defined in the current JAXX file via scripts + String propertyName = null; + if (methodName.startsWith("is")) { + propertyName = Introspector.decapitalize(methodName.substring("is".length())); + } else if (methodName.startsWith("get")) { + propertyName = Introspector.decapitalize(methodName.substring("get".length())); + } + if (propertyName != null) { + MethodDescriptor[] newMethods = compiler.getScriptMethods(); + for (MethodDescriptor newMethod : newMethods) { + if (newMethod.getName().equals(methodName)) { + addListener(compiler.getRootObject().getId(), + null, + "addPropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator(), + "removePropertyChangeListener(\"" + propertyName + "\", " + listenerId + ");" + JAXXCompiler.getLineSeparator()); + contextClass = newMethod.getReturnType(); + break; + } + } + } + } + } + } + lastNode = suffix.getText().trim(); + if (lastNode.startsWith(".")) { + lastNode = lastNode.substring(1); + } + } + + return null; + } + + private void trackMemberIfPossible(String objectCode, ClassDescriptor objectClass, String memberName, boolean method, String listenerId) { + if (objectClass.isInterface()) // might be technically possible to track in some cases, but for now + { + return; // we can't create a DefaultObjectHandler for interfaces + } + + DefaultObjectHandler handler = TagManager.getTagHandler(objectClass); + try { + if (handler.isMemberBound(memberName)) { + addListener(objectCode + "." + memberName + (method ? "()" : ""), + objectCode, + handler.getAddMemberListenerCode(objectCode, id, memberName, listenerId, compiler), + handler.getRemoveMemberListenerCode(objectCode, id, memberName, listenerId, compiler)); + } + } + catch (UnsupportedAttributeException e) { + // ignore -- this is thrown for methods like toString(), for which there is no tracking and + // no setting support + } + } + + /** + * Adds type information to nodes where possible, and as a side effect adds event listeners to nodes which + * can be tracked. + * + * @param node node to scan + * @param listenerId the listener id + */ + private void determineNodeType(SimpleNode node, String listenerId) { + ClassDescriptor type = null; + if (node.jjtGetNumChildren() == 1) { + type = node.getChild(0).getJavaType(); + } + switch (node.getId()) { + case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: + type = ClassDescriptorLoader.getClassDescriptor(Class.class); + break; + case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: + type = determineExpressionType(node, listenerId); + break; + case JavaParserTreeConstants.JJTLITERAL: + type = determineLiteralType(node); + break; + case JavaParserTreeConstants.JJTCASTEXPRESSION: + type = TagManager.resolveClass(node.getChild(0).getText(), compiler); + break; + } + node.setJavaType(type); + } + + private void addListener(String dependencySymbol, String objectCode, String addCode, String removeCode) { + if (!dependencySymbols.contains(dependencySymbol)) { + dependencySymbols.add(dependencySymbol); + if (objectCode != null) { + addListenerCode.append("if (").append(objectCode).append(" != null) {").append(JAXXCompiler.getLineSeparator()); + addListenerCode.append(" "); + } + addListenerCode.append(addCode); + if (objectCode != null) { + addListenerCode.append("}"); + } + + if (objectCode != null) { + removeListenerCode.append("if (").append(objectCode).append(" != null) {").append(JAXXCompiler.getLineSeparator()); + removeListenerCode.append(" "); + } + removeListenerCode.append(removeCode); + if (objectCode != null) { + removeListenerCode.append("}"); + } + } + } + + private void compileListeners() { + if (addListenerCode.length() > 0) { + if (compiler.haveApplyDataBinding()) { + compiler.appendApplyDataBinding("else "); + } + compiler.appendApplyDataBinding("if ($binding.equals(" + TypeManager.getJavaCode(id) + ")) {" + JAXXCompiler.getLineSeparator()); + compiler.appendApplyDataBinding(" " + addListenerCode + JAXXCompiler.getLineSeparator()); + compiler.appendApplyDataBinding("}" + JAXXCompiler.getLineSeparator()); + //if (compiler.applyDataBinding.length() > 0) + // compiler.applyDataBinding.append("else "); + //compiler.applyDataBinding.append("if ($binding.equals(").append(TypeManager.getJavaCode(id)).append(")) {").append(JAXXCompiler.getLineSeparator()); + //compiler.applyDataBinding.append(" ").append(addListenerCode).append(JAXXCompiler.getLineSeparator()); + //compiler.applyDataBinding.append("}").append(JAXXCompiler.getLineSeparator()); + } + + if (removeListenerCode.length() > 0) { + if (compiler.haveRemoveDataBinding()) { + compiler.appendRemoveDataBinding("else "); + } + compiler.appendRemoveDataBinding("if ($binding.equals(" + TypeManager.getJavaCode(id) + ")) {" + JAXXCompiler.getLineSeparator()); + compiler.appendRemoveDataBinding(" " + removeListenerCode + JAXXCompiler.getLineSeparator()); + compiler.appendRemoveDataBinding("}" + JAXXCompiler.getLineSeparator()); + //if (compiler.removeDataBinding.length() > 0) + // compiler.removeDataBinding.append("else "); + //compiler.removeDataBinding.append("if ($binding.equals(").append(TypeManager.getJavaCode(id)).append(")) {").append(JAXXCompiler.getLineSeparator()); + //compiler.removeDataBinding.append(" ").append(removeListenerCode).append(JAXXCompiler.getLineSeparator()); + //compiler.removeDataBinding.append("}").append(JAXXCompiler.getLineSeparator()); + } + } +} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,2173 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.compiler; - -import jaxx.CompilerException; -import jaxx.UnsupportedAttributeException; -import jaxx.UnsupportedTagException; -import jaxx.css.Rule; -import jaxx.css.Stylesheet; -import jaxx.parser.ParseException; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.reflect.FieldDescriptor; -import jaxx.reflect.MethodDescriptor; -import jaxx.runtime.ComponentDescriptor; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; -import jaxx.runtime.swing.Application; -import jaxx.spi.Initializer; -import jaxx.tags.DefaultObjectHandler; -import jaxx.tags.TagHandler; -import jaxx.tags.TagManager; -import jaxx.tags.swing.BeanValidatorHandler.CompiledBeanValidator; -import jaxx.types.TypeManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import org.xml.sax.helpers.AttributesImpl; -import org.xml.sax.helpers.XMLFilterImpl; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.transform.ErrorListener; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.sax.SAXSource; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectOutputStream; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Modifier; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.Set; -import java.util.Stack; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.zip.GZIPOutputStream; - -/** Compiles JAXX files into Java classes. */ -public class JAXXCompiler { - /** log */ - protected static final Log log = LogFactory.getLog(JAXXCompiler.class); - - /** - * True to throw exceptions when we encounter unresolvable classes, false to ignore. - * This is currently set to false until JAXX has full support for inner classes - * (including enumerations), because currently they don't always resolve (but will - * generally compile without error anyway). - */ - public static final boolean STRICT_CHECKS = false; - - public static final String JAXX_NAMESPACE = "http://www.jaxxframework.org/"; - public static final String JAXX_INTERNAL_NAMESPACE = "http://www.jaxxframework.org/internal"; - - /** Maximum length of an inlinable creation method. */ - private static final int INLINE_THRESHOLD = 300; - - /** Contains import declarations (of the form "javax.swing.") which are always imported in all compiler instances. */ - private static List<String> staticImports = new ArrayList<String>(); - - static { - //TODO humm, we should be able to import only what is needed - staticImports.add("java.awt.*"); - staticImports.add("java.awt.event.*"); - staticImports.add("java.beans.*"); - staticImports.add("java.io.*"); - staticImports.add("java.lang.*"); - staticImports.add("java.util.*"); - staticImports.add("javax.swing.*"); - staticImports.add("javax.swing.border.*"); - staticImports.add("javax.swing.event.*"); - staticImports.add("jaxx.runtime.swing.JAXXButtonGroup"); - staticImports.add("jaxx.runtime.swing.HBox"); - staticImports.add("jaxx.runtime.swing.VBox"); - staticImports.add("jaxx.runtime.swing.Table"); - staticImports.add("static org.codelutin.i18n.I18n._"); - staticImports.add("static org.codelutin.jaxx.util.UIHelper.createImageIcon"); - } - - private static DefaultObjectHandler firstPassClassTagHandler = new DefaultObjectHandler(ClassDescriptorLoader.getClassDescriptor(Object.class)); - - /** - * A list of Runnables which will be run after the first compilation pass. This is primarily used - * to trigger the creation of CompiledObjects, which cannot be created during the first pass and must be - * created in document order. - */ - private List<Runnable> initializers = new ArrayList<Runnable>(); - - /** Files being compiled during the compilation session, may be modified as compilation progresses and additional dependencies are found. */ - private static List<File> jaxxFiles = new ArrayList<File>(); - - /** Class names corresponding to the files in the jaxxFiles list. */ - private static List<String> jaxxFileClassNames = new ArrayList<String>(); - - /** Maps the names of classes being compiled to the compiler instance handling the compilation. */ - private static Map<String, JAXXCompiler> compilers = new HashMap<String, JAXXCompiler>(); - - /** Maps the names of classes being compiled to their symbol tables (created after the first compiler pass). */ - private static Map<File, SymbolTable> symbolTables = new HashMap<File, SymbolTable>(); - - private CompilerOptions options; - - /** Used for error reporting purposes, so we can report the right line number. */ - private Stack<Element> tagsBeingCompiled = new Stack<Element>(); - - /** Used for error reporting purposes, so we can report the right source file. */ - private Stack<File> sourceFiles = new Stack<File>(); - - /** Maps object ID strings to the objects themselves. These are created during the second compilation pass. */ - private Map<String, CompiledObject> objects = new LinkedHashMap<String, CompiledObject>(); - - /** Maps objects to their ID strings. These are created during the second compilation pass. */ - private Map<CompiledObject, String> ids = new LinkedHashMap<CompiledObject, String>(); - - private static int errorCount; - private static int warningCount; - - private boolean failed; - - /** Object corresponding to the root tag in the document. */ - private CompiledObject root; - - /** Contains strings of the form "javax.swing." */ - private Set<String> importedPackages = new HashSet<String>(); - - /** Contains strings of the form "javax.swing.Timer" */ - private Set<String> importedClasses = new HashSet<String>(); - - /** Keeps track of open components (components still having children added). */ - private Stack<CompiledObject> openComponents = new Stack<CompiledObject>(); - - /** Sequence number used to create automatic variable names. */ - private int autogenID = 0; - - private List<DataBinding> dataBindings = new ArrayList<DataBinding>(); - - private JavaFile javaFile = new JavaFile(); - - // true if a main() method has been declared in a script - boolean mainDeclared; - - /** list of validators */ - protected List<CompiledBeanValidator> validators = new ArrayList<CompiledBeanValidator>(); - - private SymbolTable symbolTable = new SymbolTable(); - - // TODO: replace these public StringBuffers with something a little less stupid - - /** Extra code to be added to the instance initializer. */ - public StringBuffer initializer = new StringBuffer(); - - /** Extra code to be added at the end of the instance initializer. */ - public StringBuffer lateInitializer = new StringBuffer(); - - /** Extra code to be added to the class body. */ - public StringBuffer bodyCode = new StringBuffer(); - - /** Code to initialize data bindings. */ - public StringBuffer initDataBindings = new StringBuffer(); - - /** Body of the applyDataBinding method. */ - public StringBuffer applyDataBinding = new StringBuffer(); - - /** Body of the removeDataBinding method. */ - public StringBuffer removeDataBinding = new StringBuffer(); - - /** Body of the processDataBinding method. */ - public StringBuffer processDataBinding = new StringBuffer(); - - /** Base directory used for path resolution (normally the directory in which the .jaxx file resides). */ - private File baseDir; - - /** .jaxx file being compiled. */ - private File src; - - /** Generated .java file. */ - private File dest; - - /** Parsed XML of src file. */ - private Document document; - - /** Name of class being compiled. */ - private String outputClassName; - - private ScriptManager scriptManager = new ScriptManager(this); - - /** Combination of all stylesheets registered using {@link #registerStylesheet}. */ - private Stylesheet stylesheet; - - /** Contains all attributes defined inline on class tags. */ - private List<Rule> inlineStyles = new ArrayList<Rule>(); - - /** - * Maps objects (expressed in Java code) to event listener classes (e.g. MouseListener) to Lists of EventHandlers. The final list - * contains all event handlers of a particular type attached to a particular object (again, as represented by a Java expression). - */ - private Map<String, Map<ClassDescriptor, List<EventHandler>>> eventHandlers = new HashMap<String, Map<ClassDescriptor, List<EventHandler>>>(); - - private Map<Object, String> uniqueIds = new HashMap<Object, String>(); - - private Map<EventHandler, String> eventHandlerMethodNames = new HashMap<EventHandler, String>(); - - /** ClassLoader which searches the user-specified class path in addition to the normal class path */ - private ClassLoader classLoader; - - private static final int PASS_1 = 0; - private static final int PASS_2 = 1; - private static int currentPass; - - public static void init() { - // forces static initializer to run if it hasn't yet - } - - public static void loadLibraries(boolean verbose) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { - ClassLoader classloader = Thread.currentThread().getContextClassLoader(); - if (verbose) { - log.info("with cl " + classloader); - } - ServiceLoader<Initializer> loader = ServiceLoader.load(Initializer.class, classloader); - for (Initializer initializer : loader) { - if (verbose) { - log.info("load initializer " + initializer); - } - initializer.initialize(); - } - } - - private JAXXCompiler(ClassLoader classLoader) { - this.options = new CompilerOptions(); - this.classLoader = classLoader; - addImport("java.lang.*"); - } - - - /** - * Creates a new JAXXCompiler. - * - * @param baseDir classpath location - * @param options options to pass to javac - * @param src location of file to compile - * @param outputClassName the out file name - */ - protected JAXXCompiler(File baseDir, File src, String outputClassName, CompilerOptions options) { - this.baseDir = baseDir; - this.src = src; - sourceFiles.push(src); - this.outputClassName = outputClassName; - this.options = options; - addImport(outputClassName.substring(0, outputClassName.lastIndexOf(".") + 1) + "*"); - for (Object staticImport : staticImports) { - addImport((String) staticImport); - } - } - - - /** - * Creates a dummy JAXXCompiler for use in unit testing. - * - * @return the compiler - */ - public static JAXXCompiler createDummyCompiler() { - return createDummyCompiler(JAXXCompiler.class.getClassLoader()); - } - - - /** - * Creates a dummy JAXXCompiler for use in unit testing. - * - * @param classLoader class loader to use - * @return the compiler - */ - public static JAXXCompiler createDummyCompiler(ClassLoader classLoader) { - return new JAXXCompiler(classLoader); - } - - - public CompilerOptions getOptions() { - return options; - } - - - public JavaFile getJavaFile() { - return javaFile; - } - - - private void compileFirstPass() throws IOException { - try { - InputStream in = new FileInputStream(src); - document = parseDocument(in); - in.close(); - compileFirstPass(document.getDocumentElement()); - } - catch (SAXParseException e) { - reportError(e.getLineNumber(), "Invalid XML: " + e.getMessage()); - } - catch (SAXException e) { - reportError(null, "Error parsing XML document: " + e); - } - } - - - private void runInitializers() { - for (Runnable runnable : initializers) { - if (log.isDebugEnabled()) { - log.debug(runnable); - } - runnable.run(); - } - initializers.clear(); - } - - - /** - * Registers a <code>Runnable</code> which will be executed after the first - * compilation pass is complete. - * - * @param r runnable to register - */ - public void registerInitializer(Runnable r) { - initializers.add(r); - } - - - private void compileSecondPass() throws IOException { - if (!tagsBeingCompiled.isEmpty()) { - throw new RuntimeException("Internal error: starting pass two, but tagsBeingCompiled is not empty: " + tagsBeingCompiled); - } - compileSecondPass(document.getDocumentElement()); - } - - - private void applyStylesheets() { - for (Object o : new ArrayList<CompiledObject>(objects.values())) { - CompiledObject object = (CompiledObject) o; - TagManager.getTagHandler(object.getObjectClass()).applyStylesheets(object, this); - } - } - - - private void generateCode() throws IOException { - if (options.getTargetDirectory() != null) { - dest = new File(options.getTargetDirectory(), outputClassName.replace('.', File.separatorChar) + ".java"); - } else { - dest = new File(baseDir, outputClassName.substring(outputClassName.lastIndexOf(".") + 1) + ".java"); - } - if (dest.exists() && !dest.setLastModified(System.currentTimeMillis())) { - log.warn("could not touch file " + dest); - } - PrintWriter out = new PrintWriter(new FileWriter(dest)); - createJavaSource(out); - out.close(); - } - - private void createJavaSource(PrintWriter out) throws IOException { - int dotPos = outputClassName.lastIndexOf("."); - String packageName = dotPos != -1 ? outputClassName.substring(0, dotPos) : null; - String simpleClassName = outputClassName.substring(dotPos + 1); - outputClass(packageName, simpleClassName, out); - } - - - public String getOutputClassName() { - return outputClassName; - } - - public static SAXParser getSAXParser() { - try { - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - SAXParser parser; - parser = factory.newSAXParser(); - return parser; - } - catch (SAXException e) { - throw new RuntimeException(e); - } - catch (ParserConfigurationException e) { - throw new RuntimeException(e); - } - } - - public static Document parseDocument(InputStream in) throws IOException, SAXException { - try { - TransformerFactory factory = TransformerFactory.newInstance(); - Transformer transformer = factory.newTransformer(); - transformer.setErrorListener(new ErrorListener() { - public void warning(TransformerException ex) throws TransformerException { - throw ex; - } - - public void error(TransformerException ex) throws TransformerException { - throw ex; - } - - public void fatalError(TransformerException ex) throws TransformerException { - throw ex; - } - }); - - DOMResult result = new DOMResult(); - transformer.transform(new SAXSource(new XMLFilterImpl(getSAXParser().getXMLReader()) { - Locator locator; - - @Override - public void setDocumentLocator(Locator locator) { - this.locator = locator; - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { - AttributesImpl resultAtts = new AttributesImpl(atts); - resultAtts.addAttribute(JAXX_INTERNAL_NAMESPACE, "line", "internal:line", "CDATA", String.valueOf(locator.getLineNumber())); - getContentHandler().startElement(uri, localName, qName, resultAtts); - } - }, new InputSource(in)), result); - return (Document) result.getNode(); - } - catch (TransformerConfigurationException e) { - throw new RuntimeException(e); - } - catch (TransformerException e) { - Throwable ex = e; - while (ex.getCause() != null) { - ex = ex.getCause(); - } - if (ex instanceof IOException) { - throw (IOException) ex; - } - if (ex instanceof SAXException) { - throw (SAXException) ex; - } - if (ex instanceof RuntimeException) { - throw (RuntimeException) ex; - } - throw new RuntimeException(ex); - } - } - - - public File getBaseDir() { - return baseDir; - } - - - public Set<String> getImportedClasses() { - return importedClasses; - } - - - public Set<String> getImportedPackages() { - return importedPackages; - } - - - private boolean inlineCreation(CompiledObject object) { - return object.getId().startsWith("$") && object.getInitializationCode(this).length() < INLINE_THRESHOLD; - } - - - public void checkOverride(CompiledObject object) throws CompilerException { - if (object.getId().startsWith("$")) { - return; - } - ClassDescriptor ancestor = root.getObjectClass(); - if (ancestor == object.getObjectClass()) { - return; - } - while (ancestor != null) { - try { - FieldDescriptor f = ancestor.getDeclaredFieldDescriptor(object.getId()); - if (!f.getType().isAssignableFrom(object.getObjectClass())) { - reportError("attempting to redefine superclass member '" + object.getId() + "' as incompatible type (was " + f.getType() + ", redefined as " + object.getObjectClass() + ")"); - } - object.setOverride(true); - break; - } - catch (NoSuchFieldException e) { - ancestor = ancestor.getSuperclass(); - } - } - } - - - private Iterator<CompiledObject> getObjectCreationOrder() { - return objects.values().iterator(); - } - - - protected JavaMethod createConstructor(String className) throws CompilerException { - StringBuffer code = new StringBuffer(); - String constructorParams = root.getConstructorParams(); - if (constructorParams != null) { - code.append(" super(").append(constructorParams).append(");"); - code.append(getLineSeparator()); - } - code.append("$initialize();"); - code.append(getLineSeparator()); - return new JavaMethod(Modifier.PUBLIC, null, className, null, null, code.toString()); - } - - - protected JavaMethod createInitializer(String className) throws CompilerException { - StringBuffer code = new StringBuffer(); - code.append("$objectMap.put(").append(TypeManager.getJavaCode(root.getId())).append(", this);"); - code.append(getLineSeparator()); - - Iterator<CompiledObject> i = getObjectCreationOrder(); - boolean lastWasMethodCall = false; - while (i.hasNext()) { - CompiledObject object = i.next(); - if (object != root && !object.isOverride()) { - if (inlineCreation(object)) { - if (lastWasMethodCall) { - lastWasMethodCall = false; - code.append(getLineSeparator()); - } - code.append(getCreationCode(object)); - code.append(getLineSeparator()); - } else { - code.append(object.getCreationMethodName()).append("();"); - code.append(getLineSeparator()); - lastWasMethodCall = true; - } - } - } - String rootCode = root.getInitializationCode(this); - if (rootCode != null && rootCode.length() > 0) { - code.append(rootCode); - code.append(getLineSeparator()); - } - code.append(getLineSeparator()); - if (initializer.length() > 0) { - code.append(initializer); - code.append(getLineSeparator()); - } - code.append("$completeSetup();"); - code.append(getLineSeparator()); - return new JavaMethod(Modifier.PRIVATE, "void", "$initialize", null, null, code.toString()); - } - - - protected JavaMethod createCompleteSetupMethod() { - StringBuffer code = new StringBuffer(); - code.append("allComponentsCreated = true;"); - code.append(getLineSeparator()); - for (CompiledObject object : objects.values()) { - if (object.getId().startsWith("$")) { - code.append(object.getAdditionCode()); - } else { - code.append(object.getAdditionMethodName()).append("();").append(getLineSeparator()); - String additionCode = object.getAdditionCode(); - if (additionCode.length() > 0) { - additionCode = "if (allComponentsCreated) {" + getLineSeparator() + additionCode + "}"; - } - javaFile.addMethod(new JavaMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), null, null, additionCode)); - } - code.append(getLineSeparator()); - } - - code.append(initDataBindings); - - if (lateInitializer.length() > 0) { - code.append(lateInitializer); - code.append(getLineSeparator()); - } - - if (hasValidator()) { - // register validator - for (CompiledBeanValidator validator : validators) { - String id = TypeManager.getJavaCode(validator.getId()); - code.append("$validatorIds.add(").append(id).append(");"); - code.append(getLineSeparator()); - code.append("getValidator(").append(id).append(").installLayers();"); - code.append("getValidator(").append(id).append(").validate();"); - code.append(getLineSeparator()); - } - } - return new JavaMethod(Modifier.PRIVATE, "void", "$completeSetup", null, null, code.toString()); - } - - - protected JavaMethod createProcessDataBindingMethod() { - StringBuffer code = new StringBuffer(); - boolean superclassIsJAXXObject = ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(root.getObjectClass()); - // the force parameter forces the update to happen even if it is already in activeBindings. This - // is used on superclass invocations b/c by the time the call gets to the superclass, it is already - // marked active and would otherwise be skipped - if (processDataBinding.length() > 0) { - code.append(" if (!$force && $activeBindings.contains($dest)) return;"); - code.append(getLineSeparator()); - code.append(" $activeBindings.add($dest);"); - code.append(getLineSeparator()); - code.append(" try {"); - code.append(getLineSeparator()); - if (processDataBinding.length() > 0) { - code.append(processDataBinding); - code.append(getLineSeparator()); - } - if (superclassIsJAXXObject) { - code.append(" else"); - code.append(getLineSeparator()); - code.append(" super.processDataBinding($dest, true);"); - code.append(getLineSeparator()); - } - code.append(" }"); - code.append(getLineSeparator()); - code.append(" finally {"); - code.append(getLineSeparator()); - code.append(" $activeBindings.remove($dest);"); - code.append(getLineSeparator()); - code.append(" }"); - code.append(getLineSeparator()); - } else if (superclassIsJAXXObject) { - code.append(" super.processDataBinding($dest, true);"); - code.append(getLineSeparator()); - } - return new JavaMethod(Modifier.PUBLIC, "void", "processDataBinding", - new JavaArgument[]{new JavaArgument("String", "$dest"), new JavaArgument("boolean", "$force")}, - null, code.toString()); - } - - - protected void createJavaFile(String packageName, String className) throws CompilerException { - String fullClassName = packageName != null ? packageName + "." + className : className; - if (root == null) { - throw new CompilerException("root tag must be a class tag"); - } - ClassDescriptor superclass = root.getObjectClass(); - boolean superclassIsJAXXObject = ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(superclass); - javaFile.setModifiers(Modifier.PUBLIC); - javaFile.setClassName(fullClassName); - javaFile.setSuperClass(getCanonicalName(superclass)); - javaFile.setInterfaces(new String[]{getCanonicalName(JAXXObject.class)}); - - for (CompiledObject object : objects.values()) { - if (!object.isOverride() && !(object instanceof ScriptInitializer)) { - int access = object.getId().startsWith("$") ? Modifier.PRIVATE : Modifier.PROTECTED; - if (object == root) { - javaFile.addField(new JavaField(access, fullClassName, object.getId(), "this")); - } else { - javaFile.addField(new JavaField(access, getCanonicalName(object.getObjectClass()), object.getId())); - } - } - } - - if (!superclassIsJAXXObject) { - // add logger - if (getOptions().isAddLogger()) { - javaFile.addImport("org.apache.commons.logging.Log"); - javaFile.addImport("org.apache.commons.logging.LogFactory"); - javaFile.addField(createLoggerField(fullClassName)); - } - - javaFile.addField(new JavaField(Modifier.PROTECTED, "java.util.List<Object>", "$activeBindings", "new ArrayList<Object>()")); - javaFile.addField(new JavaField(Modifier.PROTECTED, "java.util.Map<String,Object>", "$bindingSources", "new HashMap<String,Object>()")); - } - - javaFile.addImport("jaxx.runtime.BeanValidator"); - javaFile.addField(new JavaField(Modifier.PROTECTED, "java.util.List<String>", "$validatorIds", "new ArrayList<String>()")); - - if (stylesheet != null) { - javaFile.addField(new JavaField(0, "java.util.Map", "$previousValues", "new java.util.HashMap()")); - } - - javaFile.addMethod(createConstructor(className)); - javaFile.addMethod(createInitializer(className)); - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "BeanValidator<?>", "getValidator", new JavaArgument[]{new JavaArgument("String", "validatorId")}, - null, "return (BeanValidator)($validatorIds.contains(validatorId)?getObjectById(validatorId):null);")); - - for (DataBinding dataBinding : dataBindings) { - if (dataBinding.compile(true)) { - initDataBindings.append("applyDataBinding(").append(TypeManager.getJavaCode(dataBinding.getId())).append(");").append(JAXXCompiler.getLineSeparator()); - } - } - - javaFile.addBodyCode(bodyCode.toString()); - - for (CompiledObject object : objects.values()) { - if (!inlineCreation(object) && object != root) { - javaFile.addMethod(new JavaMethod(Modifier.PROTECTED, "void", object.getCreationMethodName(), null, null, getCreationCode(object))); - } - } - - javaFile.addField(new JavaField(Modifier.PRIVATE, "boolean", "allComponentsCreated")); - - javaFile.addMethod(createCompleteSetupMethod()); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "applyDataBinding", new JavaArgument[]{new JavaArgument("String", "$binding")}, - null, applyDataBinding.toString() + getLineSeparator() + " processDataBinding($binding);")); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removeDataBinding", new JavaArgument[]{new JavaArgument("String", "$binding")}, - null, removeDataBinding.toString())); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "processDataBinding", new JavaArgument[]{new JavaArgument("String", "dest")}, - null, "processDataBinding(dest, false);")); - - javaFile.addMethod(createProcessDataBindingMethod()); - - if (!superclassIsJAXXObject) { - javaFile.addField(createObjectMap()); - javaFile.addMethod(createGetObjectByIdMethod()); - } - - javaFile.addField(createJAXXObjectDescriptorField()); - javaFile.addMethod(createGetJAXXObjectDescriptorMethod()); - - /* - * Gestion du context - */ - javaFile.addField(createContextField()); - javaFile.addMethod(createSetContextValueMethod()); - javaFile.addMethod(createSetContextValueNameMethod()); - javaFile.addMethod(createGetContextValueMethod()); - javaFile.addMethod(createGetContextValueNameMethod()); - javaFile.addMethod(createGetParentContainer()); - javaFile.addMethod(createGetParentContainerMore()); - ClassDescriptor currentClass = root.getObjectClass(); - MethodDescriptor firePropertyChange = null; - while (firePropertyChange == null && currentClass != null) { - try { - firePropertyChange = currentClass.getDeclaredMethodDescriptor("firePropertyChange", new ClassDescriptor[]{ - ClassDescriptorLoader.getClassDescriptor(String.class), - ClassDescriptorLoader.getClassDescriptor(Object.class), - ClassDescriptorLoader.getClassDescriptor(Object.class) - }); - - } - catch (NoSuchMethodException e) { - currentClass = currentClass.getSuperclass(); - } - } - - int modifiers = firePropertyChange != null ? firePropertyChange.getModifiers() : 0; - if (Modifier.isPublic(modifiers)) { - // we have all the support we need - } - if (Modifier.isProtected(modifiers)) { - // there is property change support but the firePropertyChange method is protected - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "firePropertyChange", new JavaArgument[]{ - new JavaArgument("java.lang.String", "propertyName"), new JavaArgument("java.lang.Object", "oldValue"), new JavaArgument("java.lang.Object", "newValue")}, - null, "super.firePropertyChange(propertyName, oldValue, newValue);")); - } else { - // either no support at all or firePropertyChange isn't accessible - addPropertyChangeSupport(javaFile); - } - - addEventHandlers(javaFile); - - if (ClassDescriptorLoader.getClassDescriptor(Application.class).isAssignableFrom(root.getObjectClass()) && !mainDeclared) { - // TODO: check for existing main method first - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC | Modifier.STATIC, "void", "main", - new JavaArgument[]{new JavaArgument("String[]", "arg")}, null, - "SwingUtilities.invokeLater(new Runnable() { public void run() { new " + className + "().setVisible(true); } });")); - } - } - - - protected void outputClass(String packageName, String className, PrintWriter out) throws CompilerException { - createJavaFile(packageName, className); - out.println(javaFile.toString()); - } - - - public void addImport(String text) { - if (text.endsWith("*")) { - importedPackages.add(text.substring(0, text.length() - 1)); - } else { - importedClasses.add(text); - } - - if (!text.equals("*")) { - getJavaFile().addImport(text); - } - } - - private JavaField createLoggerField(String className) { - return new JavaField(Modifier.PUBLIC + Modifier.STATIC + Modifier.FINAL, "Log", "log", "LogFactory.getLog(" + className + ".class)"); - } - - /* - * Gestion du context - */ - private JavaField createContextField() { - return new JavaField(Modifier.PROTECTED, "Map<Object,String>", "$contextMap", "new HashMap<Object,String>()"); - } - - private JavaMethod createSetContextValueMethod() { - - return new JavaMethod(Modifier.PUBLIC, "void", "setContextValue", - new JavaArgument[]{new JavaArgument("Object", "clazz")}, null, getSetContextValueMethodCode()); - } - - private JavaMethod createSetContextValueNameMethod() { - return new JavaMethod(Modifier.PUBLIC, "void", "setContextValue", - new JavaArgument[]{new JavaArgument("Object", "clazz"), new JavaArgument("String", "name")}, null, getSetContextValueNameMethodCode()); - } - - private JavaMethod createGetContextValueMethod() { - return new JavaMethod(Modifier.PUBLIC, "<T> T", "getContextValue", - new JavaArgument[]{new JavaArgument("Class<T>", "clazz")}, null, getGetContextValueMethodCode()); - } - - private JavaMethod createGetContextValueNameMethod() { - return new JavaMethod(Modifier.PUBLIC, "<T> T", "getContextValue", - new JavaArgument[]{new JavaArgument("Class<T>", "clazz"), new JavaArgument("String", "name")}, null, getGetContextValueNameMethodCode()); - } - - private JavaMethod createGetParentContainer() { - return new JavaMethod(Modifier.PUBLIC, "<O extends Container> O", "getParentContainer", - new JavaArgument[]{new JavaArgument("Class<O>", "clazz")}, null, getGetParentContenerMethodCode()); - } - - private JavaMethod createGetParentContainerMore() { - return new JavaMethod(Modifier.PUBLIC, "<O extends Container> O", "getParentContainer", - new JavaArgument[]{new JavaArgument("Object", "source"), new JavaArgument("Class<O>", "clazz")}, null, getGetParentContenerMethodMoreCode()); - } - - private String getSetContextValueMethodCode() { - return "this.setContextValue(clazz, null);"; - } - - private String getSetContextValueNameMethodCode() { - StringBuffer result = new StringBuffer(); - result.append("$contextMap.put(clazz, name);"); - return result.toString(); - } - - private String getGetContextValueMethodCode() { - return "return this.getContextValue(clazz, null);"; - } - - private String getGetContextValueNameMethodCode() { - StringBuffer result = new StringBuffer(); - result.append("for (Map.Entry<Object,String> entry : $contextMap.entrySet()) {"); - result.append("if (clazz.isAssignableFrom(entry.getKey().getClass()) && (name == null || name == entry.getValue())) {"); - result.append("return (T) entry.getKey();}}"); - result.append("return null;"); - return result.toString(); - } - - private String getGetParentContenerMethodCode() { - StringBuffer result = new StringBuffer(); - result.append("return this.getParentContainer(this, clazz);"); - return result.toString(); - } - - private String getGetParentContenerMethodMoreCode() { - StringBuffer result = new StringBuffer(); - result.append("if (!Container.class.isAssignableFrom(source.getClass())) {return null;}"); - result.append(getLineSeparator()); - result.append("Container parent = ((Container)source).getParent();"); - result.append(getLineSeparator()); - result.append("if (parent != null && !clazz.isAssignableFrom(parent.getClass())){parent = getParentContainer(parent, clazz);}"); - result.append(getLineSeparator()); - result.append("return (O)parent;"); - return result.toString(); - } - - private JavaField createObjectMap() { - return new JavaField(Modifier.PROTECTED, "Map<String,Object>", "$objectMap", "new HashMap<String,Object>()"); - } - - - protected JavaMethod createGetObjectByIdMethod() { - return new JavaMethod(Modifier.PUBLIC, "java.lang.Object", "getObjectById", - new JavaArgument[]{new JavaArgument("String", "id")}, null, - "return $objectMap.get(id);"); - } - - - public JAXXObjectDescriptor getJAXXObjectDescriptor() { - runInitializers(); - CompiledObject[] components = new ArrayList<CompiledObject>(objects.values()).toArray(new CompiledObject[objects.size()]); - assert initializers.isEmpty() : "there are pending initializers remaining"; - assert root != null : "root object has not been defined"; - assert Arrays.asList(components).contains(root) : "root object is not registered"; - ComponentDescriptor[] descriptors = new ComponentDescriptor[components.length]; - // as we print, sort the array so that component's parents are always before the components themselves - for (int i = 0; i < components.length; i++) { - CompiledObject parent = components[i].getParent(); - while (parent != null) { - boolean found = false; - for (int j = i + 1; j < components.length; j++) { // found parent after component, swap them - if (components[j] == parent) { - components[j] = components[i]; - components[i] = parent; - found = true; - break; - } - } - if (!found) { - break; - } - parent = components[i].getParent(); - } - int parentIndex = -1; - if (parent != null) { - for (int j = 0; j < i; j++) { - if (components[j] == parent) { - parentIndex = j; - break; - } - } - } - descriptors[i] = new ComponentDescriptor(components[i].getId(), components[i] == root ? outputClassName : components[i].getObjectClass().getName(), - components[i].getStyleClass(), parentIndex != -1 ? descriptors[parentIndex] : null); - } - - Stylesheet stylesheet = getStylesheet(); - if (stylesheet == null) { - stylesheet = new Stylesheet(); - } - - return new JAXXObjectDescriptor(descriptors, stylesheet); - } - - - protected JavaField createJAXXObjectDescriptorField() { - try { - JAXXObjectDescriptor descriptor = getJAXXObjectDescriptor(); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(buffer)); - out.writeObject(descriptor); - out.close(); - // the use of the weird deprecated constructor is deliberate -- we need to store the data as a String - // in the compiled class file, since byte array initialization is horribly inefficient compared to - // String initialization. So we store the bytes in the String, and we quite explicitly want a 1:1 - // mapping between bytes and chars, with the high byte of the char set to zero. We can then safely - // reconstitute the original byte[] at a later date. This is unquestionably an abuse of the String - // type, but if we could efficiently store a byte[] we wouldn't have to do this. - String data = new String(buffer.toByteArray(), 0); - - int sizeLimit = 65000; // constant strings are limited to 64K, and I'm not brave enough to push right up to the limit - if (data.length() < sizeLimit) { - return new JavaField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", "$jaxxObjectDescriptor", TypeManager.getJavaCode(data)); - } else { - StringBuffer initializer = new StringBuffer(); - for (int i = 0; i < data.length(); i += sizeLimit) { - String name = "$jaxxObjectDescriptor" + i; - javaFile.addField(new JavaField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", name, - TypeManager.getJavaCode(data.substring(i, Math.min(i + sizeLimit, data.length()))))); - if (initializer.length() > 0) { - initializer.append(" + "); - } - initializer.append("String.valueOf(").append(name).append(")"); - } - return new JavaField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", "$jaxxObjectDescriptor", initializer.toString()); - } - } - catch (IOException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - } - - - protected JavaMethod createGetJAXXObjectDescriptorMethod() { - return new JavaMethod(Modifier.PUBLIC | Modifier.STATIC, "jaxx.runtime.JAXXObjectDescriptor", "$getJAXXObjectDescriptor", - null, null, "return jaxx.runtime.Util.decodeCompressedJAXXObjectDescriptor($jaxxObjectDescriptor);"); - } - - - public String getEventHandlerMethodName(EventHandler handler) { - String result = eventHandlerMethodNames.get(handler); - if (result == null) { - result = "$ev" + eventHandlerMethodNames.size(); - eventHandlerMethodNames.put(handler, result); - } - return result; - } - - protected void addEventHandlers(JavaFile javaFile) { - for (Map.Entry<String, Map<ClassDescriptor, List<EventHandler>>> e1 : eventHandlers.entrySet()) { - // outer loop is iterating over different objects (well, technically, different Java expressions) - for (Map.Entry<ClassDescriptor, List<EventHandler>> e2 : e1.getValue().entrySet()) { - // iterate over different types of listeners for this particular object (MouseListener, ComponentListener, etc.) - for (EventHandler handler : e2.getValue()) { - // iterate over individual event handlers of a single type - String methodName = getEventHandlerMethodName(handler); - MethodDescriptor listenerMethod = handler.getListenerMethod(); - if (listenerMethod.getParameterTypes().length != 1) { - throw new CompilerException("Expected event handler " + listenerMethod.getName() + " of class " + handler.getListenerClass() + " to have exactly one argument"); - } - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", methodName, - new JavaArgument[]{new JavaArgument(getCanonicalName(listenerMethod.getParameterTypes()[0]), "event")}, null, - handler.getJavaCode())); - - } - } - } - } - - protected String getCreationCode(CompiledObject object) throws CompilerException { - if (object instanceof ScriptInitializer) { - return object.getInitializationCode(this); - } - StringBuffer result = new StringBuffer(); - result.append(object.getId()); - result.append(" = "); - String constructorParams = object.getConstructorParams(); - if (constructorParams != null) { - result.append(" new ").append(getCanonicalName(object.getObjectClass())).append("(").append(constructorParams).append(");"); - //result.append("(").append(getCanonicalName(object.getObjectClass())).append(") new ").append(getCanonicalName(object.getObjectClass())).append("(").append(constructorParams).append(");"); - } else { - result.append("new ").append(getCanonicalName(object.getObjectClass())).append("();"); - } - result.append(getLineSeparator()); - String initCode = object.getInitializationCode(this); - if (initCode != null && initCode.length() > 0) { - result.append(initCode); - } - result.append("$objectMap.put(").append(TypeManager.getJavaCode(object.getId())).append(", ").append(object.getId()).append(");"); - - return result.toString(); - } - - - protected void addPropertyChangeSupport(JavaFile javaFile) throws CompilerException { - javaFile.addField(new JavaField(0, "java.beans.PropertyChangeSupport", "$propertyChangeSupport")); - - javaFile.addMethod(new JavaMethod(0, "java.beans.PropertyChangeSupport", "$getPropertyChangeSupport", null, null, - "if ($propertyChangeSupport == null)\n" + - " $propertyChangeSupport = new PropertyChangeSupport(this);\n" + - "return $propertyChangeSupport;")); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "addPropertyChangeListener", new JavaArgument[]{ - new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, - "$getPropertyChangeSupport().addPropertyChangeListener(listener);")); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "addPropertyChangeListener", new JavaArgument[]{ - new JavaArgument("java.lang.String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, - "$getPropertyChangeSupport().addPropertyChangeListener(property, listener);")); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removePropertyChangeListener", new JavaArgument[]{ - new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, - "$getPropertyChangeSupport().removePropertyChangeListener(listener);")); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removePropertyChangeListener", new JavaArgument[]{ - new JavaArgument("java.lang.String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, - "$getPropertyChangeSupport().removePropertyChangeListener(property, listener);")); - - javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "firePropertyChange", new JavaArgument[]{ - new JavaArgument("java.lang.String", "propertyName"), new JavaArgument("java.lang.Object", "oldValue"), new JavaArgument("java.lang.Object", "newValue")}, - null, "$getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue);")); - } - - - public void compileFirstPass(final Element tag) throws IOException { - tagsBeingCompiled.push(tag); - - String namespace = tag.getNamespaceURI(); - String fullClassName; - String localName = tag.getLocalName(); - boolean namespacePrefix = tag.getPrefix() != null; - // resolve class tags into fully-qualified class name - if (namespace != null && namespace.endsWith("*")) { - String packageName = namespace.substring(0, namespace.length() - 1); - if (localName.startsWith(packageName)) // class name is fully-qualified already - { - fullClassName = TagManager.resolveClassName(localName, this); - } else { // namespace not included in class name, probably need the namespace to resolve - fullClassName = TagManager.resolveClassName(packageName + localName, this); - if (fullClassName == null && !namespacePrefix) // it was just a default namespace, try again without using the namespace - { - fullClassName = TagManager.resolveClassName(localName, this); - } - } - } else { - fullClassName = TagManager.resolveClassName(localName, this); - } - - if (fullClassName != null) { // we are definitely dealing with a class tag - addDependencyClass(fullClassName); - namespace = fullClassName.substring(0, fullClassName.lastIndexOf(".") + 1) + "*"; - if (symbolTable.getSuperclassName() == null) { - symbolTable.setSuperclassName(fullClassName); - } - String id = tag.getAttribute("id"); - if (id.length() > 0) { - symbolTable.getClassTagIds().put(id, fullClassName); - } - } - // during the first pass, we can't create ClassDescriptors for JAXX files because they may not have been processed yet - // (and we can't wait until they have been processed because of circular dependencies). So we don't do any processing - // during the first pass which requires having a ClassDescriptor; here we determine whether we have a class tag or not - // (class tag namespaces end in "*") and use a generic handler if so. The real handler is used during the second pass. - TagHandler handler = (namespace != null && namespace.endsWith("*")) ? firstPassClassTagHandler : TagManager.getTagHandler(tag.getNamespaceURI(), localName, namespacePrefix, this); - if (handler != firstPassClassTagHandler && handler instanceof DefaultObjectHandler) { - fullClassName = ((DefaultObjectHandler) handler).getBeanClass().getName(); - //namespace = fullClassName.substring(0, fullClassName.lastIndexOf(".") + 1) + "*"; - handler = firstPassClassTagHandler; - } - if (handler == firstPassClassTagHandler) { - final String finalClassName = fullClassName; - registerInitializer(new Runnable() { // register an initializer which will create the CompiledObject after pass 1 - - public void run() { - DefaultObjectHandler handler = (DefaultObjectHandler) TagManager.getTagHandler(null, finalClassName, JAXXCompiler.this); - if (handler == null) { - throw new CompilerException("Internal error: missing TagHandler for '" + finalClassName + "'"); - } - handler.registerCompiledObject(tag, JAXXCompiler.this); - } - }); - } - if (handler != null) { - try { - handler.compileFirstPass(tag, this); - } - catch (CompilerException e) { - reportError(e); - } - } else { - reportError("Could not find a Java class corresponding to: <" + tag.getTagName() + ">"); - failed = true; - } - - Element finished = tagsBeingCompiled.pop(); - if (finished != tag) { - throw new RuntimeException("internal error: just finished compiling " + tag + ", but top of tagsBeingCompiled stack is " + finished); - } - } - - - public void compileSecondPass(Element tag) throws IOException { - tagsBeingCompiled.push(tag); - - TagHandler handler = TagManager.getTagHandler(tag.getNamespaceURI(), tag.getLocalName(), tag.getPrefix() != null, this); - if (handler != null) { - handler.compileSecondPass(tag, this); - } else { - reportError("Could not find a Java class corresponding to: <" + tag.getTagName() + ">"); - assert false : "can't-happen error: error should have been reported during the fast pass and caused an abort"; - failed = true; - } - - Element finished = tagsBeingCompiled.pop(); - if (finished != tag) { - throw new RuntimeException("internal error: just finished compiling " + tag + ", but top of tagsBeingCompiled stack is " + finished); - } - - } - - - // 1.5 adds getCanonicalName; unfortunately we can't depend on 1.5 features yet - public static String getCanonicalName(Class clazz) { - if (clazz.isArray()) { - String canonicalName = getCanonicalName(clazz.getComponentType()); - if (canonicalName != null) { - return canonicalName + "[]"; - } - return null; - } - return clazz.getName().replace('$', '.'); - } - - - public static String getCanonicalName(ClassDescriptor clazz) { - if (clazz.isArray()) { - String canonicalName = getCanonicalName(clazz.getComponentType()); - if (canonicalName != null) { - return canonicalName + "[]"; - } - return null; - } - return clazz.getName().replace('$', '.'); - } - - - public static String capitalize(String s) { - if (s.length() == 0) { - return s; - } - return Character.toUpperCase(s.charAt(0)) + s.substring(1); - } - - - public String[] parseParameterList(String parameters) throws CompilerException { - List<String> result = new ArrayList<String>(); - StringBuffer current = new StringBuffer(); - int state = 0; // normal - for (int i = 0; i < parameters.length(); i++) { - char c = parameters.charAt(i); - switch (state) { - case 0: // normal - switch (c) { - case '"': - current.append(c); - state = 1; - break; // in quoted string - case '\\': - current.append(c); - state = 2; - break; // immediately after backslash - case ',': - if (current.length() > 0) { - result.add(current.toString()); - current.setLength(0); - break; - } else { - reportError("error parsing parameter list: " + parameters); - } - default: - current.append(c); - } - break; - case 1: // in quoted string - switch (c) { - case '"': - current.append(c); - state = 0; - break; // normal - case '\\': - current.append(c); - state = 3; - break; // immediate after backslash in quoted string - default: - current.append(c); - } - break; - case 2: // immediately after backslash - current.append(c); - state = 0; // normal - break; - case 3: // immediately after backslash in quoted string - current.append(c); - state = 1; // in quoted string - break; - } - } - if (current.length() > 0) { - result.add(current.toString()); - } - return result.toArray(new String[result.size()]); - } - - - public void openComponent(CompiledObject component) throws CompilerException { - openComponent(component, null); - } - - - public void openComponent(CompiledObject component, String constraints) throws CompilerException { - CompiledObject parent = getOpenComponent(); - openInvisibleComponent(component); - if (parent != null && !component.isOverride()) { - parent.addChild(component, constraints, this); - } - } - - - public void openInvisibleComponent(CompiledObject component) { - if (!ids.containsKey(component)) { - registerCompiledObject(component); - } - openComponents.push(component); - } - - - public CompiledObject getOpenComponent() { - if (openComponents.isEmpty()) { - return null; - } - return openComponents.peek(); - } - - - public void closeComponent(CompiledObject component) { - if (openComponents.pop() != component) { - throw new IllegalArgumentException("can only close the topmost open object"); - } - } - - - public CompiledObject getRootObject() { - return root; - } - - - public void registerCompiledObject(CompiledObject object) { - assert symbolTables.values().contains(symbolTable) : "attempting to register CompiledObject before pass 1 is complete"; - if (root == null) { - root = object; - } - - String id = object.getId(); - if (ids.containsKey(object)) { - reportError("object '" + object + "' is already registered with id '" + ids.get(object) + "', cannot re-register as '" + id + "'"); - } - if (objects.containsKey(id) && !(objects.get(id) instanceof Element)) { - reportError("id '" + id + "' is already registered to component " + objects.get(id)); - } - objects.put(id, object); - ids.put(object, id); - } - - - public String getAutoId(ClassDescriptor objectClass) { - if (options.getOptimize()) { - return "$" + Integer.toString(autogenID++, 36); - } else { - String name = objectClass.getName(); - name = name.substring(name.lastIndexOf(".") + 1); - return "$" + name + autogenID++; - } - } - - - public String getUniqueId(Object object) { - String result = uniqueIds.get(object); - if (result == null) { - result = "$u" + uniqueIds.size(); - uniqueIds.put(object, result); - } - return result; - } - - - public SymbolTable getSymbolTable() { - return symbolTable; - } - - - public CompiledObject getCompiledObject(String id) { - runInitializers(); - assert symbolTables.values().contains(symbolTable) : "attempting to retrieve CompiledObject before pass 1 is complete"; - return objects.get(id); - } - - - private Matcher leftBraceMatcher = Pattern.compile("^(\\{)|[^\\\\](\\{)").matcher(""); - - private int getNextLeftBrace(String string, int pos) { - leftBraceMatcher.reset(string); - return leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; - } - - - private Matcher rightBraceMatcher = Pattern.compile("^(\\})|[^\\\\](\\})").matcher(""); - - private int getNextRightBrace(String string, int pos) { - leftBraceMatcher.reset(string); - rightBraceMatcher.reset(string); - int openCount = 1; - int rightPos; - while (openCount > 0) { - pos++; - int leftPos = leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; - rightPos = rightBraceMatcher.find(pos) ? Math.max(rightBraceMatcher.start(1), rightBraceMatcher.start(2)) : -1; - assert leftPos == -1 || leftPos >= pos; - assert rightPos == -1 || rightPos >= pos; - if (leftPos != -1 && leftPos < rightPos) { - pos = leftPos; - openCount++; - } else if (rightPos != -1) { - pos = rightPos; - openCount--; - } else { - openCount = 0; - } - } - return pos; - } - - - /** - * Examine an attribute value for data binding expressions. Returns a 'cooked' expression which - * can be used to determine the resulting value. It is expected that this expression will be used - * as the source expression in a call to {@link #registerDataBinding}. - * If the attribute value does not invoke data binding, this method returns <code>null</code> - * - * @param stringValue the string value of the property from the XML - * @param type the type of the property, from the <code>JAXXPropertyDescriptor</code> - * @return a processed version of the expression - * @throws jaxx.CompilerException ? - */ - public String processDataBindings(String stringValue, ClassDescriptor type) throws CompilerException { - int pos = getNextLeftBrace(stringValue, 0); - if (pos != -1) { - StringBuffer expression = new StringBuffer(); - int lastPos = 0; - while (pos != -1 && pos < stringValue.length()) { - if (pos > lastPos) { - if (expression.length() > 0) { - expression.append(" + "); - } - expression.append('"'); - expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos, pos))); - expression.append('"'); - } - - if (expression.length() > 0) { - expression.append(" + "); - } - expression.append('('); - int pos2 = getNextRightBrace(stringValue, pos + 1); - if (pos2 == -1) { - reportError("unmatched '{' in expression: " + stringValue); - return ""; - } - expression.append(stringValue.substring(pos + 1, pos2)); - expression.append(')'); - pos2++; - if (pos2 < stringValue.length()) { - pos = getNextLeftBrace(stringValue, pos2); - lastPos = pos2; - } else { - pos = stringValue.length(); - lastPos = pos; - } - } - if (lastPos < stringValue.length()) { - if (expression.length() > 0) { - expression.append(" + "); - } - expression.append('"'); - expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos))); - expression.append('"'); - } - return type == ClassDescriptorLoader.getClassDescriptor(String.class) ? "String.valueOf(" + expression + ")" : expression.toString(); - } - return null; - } - - - public void registerDataBinding(String src, String dest, String assignment) { - try { - src = checkJavaCode(src); - dataBindings.add(new DataBinding(src, dest, assignment, this)); - } - catch (CompilerException e) { - reportError("While parsing data binding for '" + dest.substring(dest.lastIndexOf(".") + 1) + "': " + e.getMessage()); - } - } - - - public ScriptManager getScriptManager() { - return scriptManager; - } - - - /** - * Verifies that a snippet of Java code parses correctly. A warning is generated if the string has enclosing - * curly braces. - * - * @param javaCode the Java code snippet to test - * @return a "cooked" version of the string which has enclosing curly braces removed. - * @throws CompilerException if the code cannot be parsed - */ - public String checkJavaCode(String javaCode) { - javaCode = scriptManager.trimScript(javaCode); - scriptManager.checkParse(javaCode); - return javaCode; - } - - - public void registerEventHandler(EventHandler handler) { - String objectCode = handler.getObjectCode(); - Map<ClassDescriptor, List<EventHandler>> listeners = eventHandlers.get(objectCode); - if (listeners == null) { - listeners = new HashMap<ClassDescriptor, List<EventHandler>>(); - eventHandlers.put(objectCode, listeners); - } - ClassDescriptor listenerClass = handler.getListenerClass(); - List<EventHandler> handlerList = listeners.get(listenerClass); - if (handlerList == null) { - handlerList = new ArrayList<EventHandler>(); - listeners.put(listenerClass, handlerList); - } - handlerList.add(handler); - } - - - public FieldDescriptor[] getScriptFields() { - List<FieldDescriptor> scriptFields = symbolTable.getScriptFields(); - return scriptFields.toArray(new FieldDescriptor[scriptFields.size()]); - } - - - public void addScriptField(FieldDescriptor field) { - symbolTable.getScriptFields().add(field); - } - - - public MethodDescriptor[] getScriptMethods() { - List<MethodDescriptor> scriptMethods = symbolTable.getScriptMethods(); - return scriptMethods.toArray(new MethodDescriptor[scriptMethods.size()]); - } - - - public void addScriptMethod(MethodDescriptor method) { - if (method.getName().equals("main") && method.getParameterTypes().length == 1 && method.getParameterTypes()[0].getName().equals("[Ljava.lang.String;")) { - mainDeclared = true; - } - symbolTable.getScriptMethods().add(method); - } - - - public void registerScript(String script) throws CompilerException { - registerScript(script, null); - } - - - public void registerScript(String script, File sourceFile) throws CompilerException { - if (sourceFile != null) { - sourceFiles.push(sourceFile); - } - script = script.trim(); - if (!"".equals(script) && !script.endsWith("}") && !script.endsWith(";")) { - script += ";"; - } - scriptManager.registerScript(script); - - if (sourceFile != null) { - File pop = sourceFiles.pop(); - if (pop != sourceFile) { - throw new RuntimeException("leaving registerScript(), but " + sourceFile + " was not the top entry on the stack (found " + pop + " instead)"); - } - } - } - - - public String preprocessScript(String script) throws CompilerException { - return scriptManager.preprocessScript(script); - } - - - public void registerStylesheet(Stylesheet stylesheet) { - if (this.stylesheet == null) { - this.stylesheet = stylesheet; - } else { - this.stylesheet.add(stylesheet.getRules()); - } - } - - - public Stylesheet getStylesheet() { - Stylesheet merged = new Stylesheet(); - if (stylesheet != null) { - merged.add(stylesheet.getRules()); - } - merged.add(inlineStyles.toArray(new Rule[inlineStyles.size()])); - return merged; - } - - - public Stack<File> getSourceFiles() { - return sourceFiles; - } - - - public void addInlineStyle(CompiledObject object, String propertyName, boolean dataBinding) { - inlineStyles.add(Rule.inlineAttribute(object, propertyName, dataBinding)); - } - - - public void reportWarning(String warning) { - Element currentTag = null; - if (!tagsBeingCompiled.isEmpty()) { - currentTag = tagsBeingCompiled.peek(); - } - reportWarning(currentTag, warning, 0); - } - - - public void reportWarning(Element tag, String warning, int lineOffset) { - String lineNumber = null; - if (tag != null) { - String lineAttr = tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); - if (lineAttr.length() > 0) { - lineNumber = lineAttr; - } - } - File src = sourceFiles.peek(); - try { - src = src.getCanonicalFile(); - } - catch (IOException e) { - // ignore ? - } - - System.err.print(src); - if (lineNumber != null) { - System.err.print(":" + ((sourceFiles.size() == 1) ? Integer.parseInt(lineNumber) + lineOffset : lineOffset + 1)); - } - System.err.println(": Warning: " + warning); - warningCount++; - } - - - public void reportError(String error) { - Element currentTag = null; - if (!tagsBeingCompiled.isEmpty()) { - currentTag = tagsBeingCompiled.peek(); - } - reportError(currentTag, error); - } - - - public void reportError(CompilerException ex) { - reportError(null, ex); - } - - - public void reportError(String extraMessage, CompilerException ex) { - String message = ex.getMessage(); - if (ex.getClass() == UnsupportedAttributeException.class || ex.getClass() == UnsupportedTagException.class) { - message = ex.getClass().getName().substring(ex.getClass().getName().lastIndexOf(".") + 1) + ": " + message; - } - int lineOffset; - if (ex instanceof ParseException) { - lineOffset = Math.max(0, ((ParseException) ex).getLine() - 1); - } else { - lineOffset = 0; - } - Element currentTag = null; - if (!tagsBeingCompiled.isEmpty()) { - currentTag = tagsBeingCompiled.peek(); - } - reportError(currentTag, extraMessage != null ? extraMessage + message : message, lineOffset); - } - - - public void reportError(Element tag, String error) { - reportError(tag, error, 0); - } - - - public void reportError(Element tag, String error, int lineOffset) { - int lineNumber = 0; - if (tag != null) { - String lineAttr = tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); - if (lineAttr.length() > 0) { - lineNumber = Integer.parseInt(lineAttr); - } - } - lineNumber = Math.max(lineNumber, 1) + lineOffset; - reportError(lineNumber, error); - } - - - public void reportError(int lineNumber, String error) { - File src = sourceFiles.isEmpty() ? null : sourceFiles.peek(); - try { - if (src != null) { - src = src.getCanonicalFile(); - } - } - catch (IOException e) { - // ignore ? - } - - System.err.print(src != null ? src.getPath() : "<unknown source>"); - if (lineNumber > 0) { - System.err.print(":" + lineNumber); - } - System.err.println(": " + error); - errorCount++; - failed = true; - } - - - /** - * Escapes a string using standard Java escape sequences, generally in preparation to including it in a string literal - * in a compiled Java file. - * - * @param raw the raw string to be escape - * @return a string in which all 'dangerous' characters have been replaced by equivalent Java escape sequences - */ - public static String escapeJavaString(String raw) { - StringBuffer out = new StringBuffer(raw); - for (int i = 0; i < out.length(); i++) { - char c = out.charAt(i); - if (c == '\\' || c == '"') { - out.insert(i, '\\'); - i++; - } else if (c == '\n') { - out.replace(i, i + 1, "\\n"); - i++; - } else if (c == '\r') { - out.replace(i, i + 1, "\\r"); - i++; - } else if (c < 32 || c > 127) { - String value = Integer.toString((int) c, 16); - while (value.length() < 4) { - value = "0" + value; - } - out.replace(i, i + 1, "\\u" + value); - i += 5; - } - } - return out.toString(); - } - - - /** - * Returns the system line separator string. - * - * @return the string used to separate lines - */ - public static String getLineSeparator() { - return System.getProperty("line.separator", "\n"); - } - - - /** - * Returns a <code>ClassLoader</code> which searches the user-specified class path in addition - * to the normal system class path. - * - * @return <code>ClassLoader</code> to use while resolving class references - */ - public ClassLoader getClassLoader() { - if (classLoader == null) { - String classPath = options.getClassPath(); - if (classPath == null) { - classPath = "."; - } - String[] paths = classPath.split(File.pathSeparator); - URL[] urls = new URL[paths.length]; - for (int i = 0; i < paths.length; i++) { - try { - urls[i] = new File(paths[i]).toURI().toURL(); - } - catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - classLoader = new URLClassLoader(urls, getClass().getClassLoader()); - } - - return classLoader; - } - - - /** - * @param className the name of the class to use - * @return the compiler instance which is processing the specified JAXX class. Each class is compiled by a - * different compiler instance. - */ - public static JAXXCompiler getJAXXCompiler(String className) { - return compilers != null ? compilers.get(className) : null; - } - - - /** - * @param className the name of the class to use - * @return the symbol table for the specified JAXX class. Must be called during the second compiler pass. - * Returns <code>null</code> if no such symbol table could be found. - */ - public static SymbolTable getSymbolTable(String className) { - JAXXCompiler compiler = getJAXXCompiler(className); - if (compiler == null) { - return null; - } - return compiler.getSymbolTable(); - } - - public static File URLtoFile(URL url) { - return URLtoFile(url.toString()); - } - - public static File URLtoFile(String urlString) { - if (!urlString.startsWith("file:")) { - throw new IllegalArgumentException("url must start with 'file:'"); - } - urlString = urlString.substring("file:".length()); - if (urlString.startsWith("/") && System.getProperty("os.name").startsWith("Windows")) { - urlString = urlString.substring(1); - } - try { - return new File(URLDecoder.decode(urlString.replace('/', File.separatorChar), "utf-8")); - } - catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - public void addDependencyClass(String className) { - if (!jaxxFileClassNames.contains(className)) { - URL jaxxURL = getClassLoader().getResource(className.replace('.', '/') + ".jaxx"); - URL classURL = getClassLoader().getResource(className.replace('.', '/') + ".class"); - if (jaxxURL != null && classURL != null) { - try { - File jaxxFile = URLtoFile(jaxxURL); - File classFile = URLtoFile(classURL); - if (classFile.lastModified() > jaxxFile.lastModified()) { - return; // class file is newer, no need to recompile - } - } - catch (Exception e) { - // do nothing - } - } - - if (jaxxURL != null && jaxxURL.toString().startsWith("file:")) { - File jaxxFile = URLtoFile(jaxxURL); - try { - jaxxFile = jaxxFile.getCanonicalFile(); - } - catch (IOException ex) { - // ignore ? - } - assert jaxxFile.getName().equalsIgnoreCase(className.substring(className.lastIndexOf(".") + 1) + ".jaxx") : - "expecting file name to match " + className + ", but found " + jaxxFile.getName(); - if (jaxxFile.getName().equals(className.substring(className.lastIndexOf(".") + 1) + ".jaxx")) { // check case match - if (currentPass == PASS_2) { - throw new AssertionError("Internal error: adding dependency class " + className + " during second compilation pass"); - } - jaxxFileClassNames.add(className); - jaxxFiles.add(jaxxFile); - } - } - } - } - - - /** - * Compiled a set of files, expressed as paths relative to a base directory. The class names of the compiled files are derived - * from the relative path strings (e.g. "example/Foo.jaxx" compiles into a class named "example.Foo"). Returns <code>true</code> - * if compilation succeeds, <code>false</code> if it fails. Warning and error messages are sent to <code>System.err</code>. - * - * @param base the directory against which to resolve relative paths - * @param relativePaths a list of relative paths to .jaxx files being compiled - * @param options the compiler options to use - * @return <code>true</code> if compilation succeeds, <code>false</code> otherwise - */ - public static synchronized boolean compile(File base, String[] relativePaths, CompilerOptions options) { - File[] files = new File[relativePaths.length]; - String[] classNames = new String[relativePaths.length]; - for (int i = 0; i < files.length; i++) { - files[i] = new File(base, relativePaths[i]); - classNames[i] = relativePaths[i].substring(0, relativePaths[i].lastIndexOf(".")); - classNames[i] = classNames[i].replace(File.separatorChar, '.'); - classNames[i] = classNames[i].replace('/', '.'); - classNames[i] = classNames[i].replace('\\', '.'); - classNames[i] = classNames[i].replace(':', '.'); - } - return compile(files, classNames, options); - } - - - /** Resets all state in preparation for a new compilation session. */ - private static void reset() { - errorCount = 0; - warningCount = 0; - jaxxFiles.clear(); - jaxxFileClassNames.clear(); - symbolTables.clear(); - compilers.clear(); - } - - - /** - * Compiled a set of files, with the class names specified explicitly. The class compiled from files[i] will be named classNames[i]. - * Returns <code>true</code> if compilation succeeds, <code>false</code> if it fails. Warning and error messages are sent to - * <code>System.err</code>. - * - * @param files the .jaxx files to compile - * @param classNames the names of the classes being compiled - * @param options the compiler options to use - * @return <code>true</code> if compilation succeeds, <code>false</code> otherwise - */ - public static synchronized boolean compile(File[] files, String[] classNames, CompilerOptions options) { - reset(); // just to be safe... - jaxxFiles.addAll(Arrays.asList(files)); - jaxxFileClassNames.addAll(Arrays.asList(classNames)); - try { - boolean success = true; - - // pass 1 - currentPass = PASS_1; - boolean compiled; - do { - compiled = false; - assert jaxxFiles.size() == jaxxFileClassNames.size(); - java.util.Iterator<File> filesIterator = new ArrayList<File>(jaxxFiles).iterator(); // clone it so it can safely be modified while we're iterating - java.util.Iterator<String> classNamesIterator = new ArrayList<String>(jaxxFileClassNames).iterator(); - while (filesIterator.hasNext()) { - File file = filesIterator.next(); - String className = classNamesIterator.next(); - if (options.isVerbose()) { - log.info("compile first pass for " + className); - } - if (symbolTables.get(file) == null) { - compiled = true; - if (compilers.containsKey(className)) { - throw new CompilerException("Internal error: " + className + " is already being compiled, attempting to compile it again"); - } - - File destDir = options.getTargetDirectory(); - if (destDir != null) { - int dotPos = className.lastIndexOf("."); - if (dotPos != -1) { - destDir = new File(destDir, className.substring(0, dotPos).replace('.', File.separatorChar)); - } - destDir.mkdirs(); - } else { - //destDir = file.getParentFile(); - } - JAXXCompiler compiler = new JAXXCompiler(file.getParentFile(), file, className, options); - compilers.put(className, compiler); - compiler.compileFirstPass(); - assert !symbolTables.values().contains(compiler.getSymbolTable()) : "symbolTable is already registered"; - symbolTables.put(file, compiler.getSymbolTable()); - if (compiler.failed) { - success = false; - } - } - } - - } while (compiled); - - // pass 2 - currentPass = PASS_2; - if (success) { - assert jaxxFiles.size() == jaxxFileClassNames.size(); - List<File> jaxxFilesClone = new ArrayList<File>(jaxxFiles); - for (String className : jaxxFileClassNames) { - JAXXCompiler compiler = compilers.get(className); - if (compiler == null) { - throw new CompilerException("Internal error: could not find compiler for " + className + " during second pass"); - } - if (options.isVerbose()) { - - log.info("runInitializers for " + className); - } - if (!compiler.failed) { - compiler.runInitializers(); - } - if (options.isVerbose()) { - - log.info("compile second pass for " + className); - } - compiler.compileSecondPass(); - if (options.isVerbose()) { - - log.info("done with result [" + !compiler.failed + "] for " + className); - } - if (!compiler.failed) { - - } else { - success = false; - } - } - if (!jaxxFilesClone.equals(jaxxFiles)) { - throw new AssertionError("Internal error: compilation set altered during pass 2 (was " + jaxxFilesClone + ", modified to " + jaxxFiles + ")"); - } - } - - // stylesheet application - if (success) { - assert jaxxFiles.size() == jaxxFileClassNames.size(); - for (String className : jaxxFileClassNames) { - JAXXCompiler compiler = compilers.get(className); - if (compiler == null) { - throw new CompilerException("Internal error: could not find compiler for " + className + " during stylesheet application"); - } - compiler.applyStylesheets(); - if (compiler.failed) { - success = false; - } - } - } - - // code generation - if (success) { - assert jaxxFiles.size() == jaxxFileClassNames.size(); - for (String className : jaxxFileClassNames) { - JAXXCompiler compiler = compilers.get(className); - if (compiler == null) { - throw new CompilerException("Internal error: could not find compiler for " + className + " during code generation"); - } - compiler.generateCode(); - if (compiler.failed) { - success = false; - } - } - } - - if (warningCount == 1) { - System.err.println("1 warning"); - } else if (warningCount > 0) { - System.err.println(warningCount + " warnings"); - } - if (errorCount == 1) { - System.err.println("1 error"); - } else if (errorCount > 0) { - System.err.println(errorCount + " errors"); - } - return success; - } - catch (CompilerException e) { - System.err.println(e.getMessage()); - e.printStackTrace(); - return false; - } - catch (Throwable e) { - e.printStackTrace(); - return false; - } - finally { - reset(); - } - } - - - private static void showUsage() { - System.out.println("Usage: jaxxc <options> <source files>"); - System.out.println(); - System.out.println("Source files must end in extension .jaxx"); - System.out.println("Use JAXX_OPTS environment variable to pass arguments to Java runtime"); - System.out.println(); - System.out.println("Supported options include:"); - System.out.println(" -classpath <paths> paths to search for user classes"); - System.out.println(" -cp <paths> same as -classpath"); - System.out.println(" -d <directory> target directory for generated class files"); - System.out.println(" -java or -j produce .java files, but do not compile them"); - System.out.println(" -keep or -k preserve generated .java files after compilation"); - System.out.println(" -optimize or -o optimize during compilation"); - System.out.println(" -version display version information"); - System.out.println(); - System.out.println("See http://www.jaxxframework.org/ for full documentation."); - } - - - public static String getVersion() { - return "1.0.4"; - } - - - public static void main(String[] arg) throws Exception { - boolean success = true; - - CompilerOptions options = new CompilerOptions(); - List<String> files = new ArrayList<String>(); - for (int i = 0; i < arg.length; i++) { - if (arg[i].endsWith(".jaxx")) { - files.add(arg[i]); - } else if (arg[i].equals("-d")) { - if (++i < arg.length) { - File targetDirectory = new File(arg[i]); - if (!targetDirectory.exists()) { - System.err.println("Error: could not find target directory: " + targetDirectory); - errorCount++; - success = false; - } - options.setTargetDirectory(targetDirectory); - } else { - success = false; - } - } else if (arg[i].equals("-cp") || arg[i].equals("-classpath")) { - if (++i < arg.length) { - options.setClassPath(arg[i]); - } else { - success = false; - } - } else if (arg[i].equals("-javac_opts")) { - if (++i < arg.length) { - options.setJavacOpts(arg[i]); - } else { - success = false; - } - } else if (arg[i].equals("-k") || arg[i].equals("-keep")) { - options.setKeepJavaFiles(true); - } else if (arg[i].equals("-j") || arg[i].equals("-java")) { - options.setKeepJavaFiles(true); - } else if (arg[i].equals("-o") || arg[i].equals("-optimize")) { - options.setOptimize(true); - } else if (arg[i].equals("-version")) { - System.err.println("jaxxc version " + getVersion() + " by Ethan Nicholas"); - System.err.println("http://www.jaxxframework.org/"); - System.exit(0); - } else if (arg[i].equals("-internalDumpVersion")) { // used by ant to extract the version info - System.out.println("jaxx.version=" + getVersion()); - return; - } else { - success = false; - } - } - - success &= (errorCount == 0 && files.size() > 0); - - if (success) { - success = compile(new File("."), files.toArray(new String[files.size()]), options); - } else { - showUsage(); - System.exit(1); - } - - System.exit(success ? 0 : 1); - } - - public File getDest() { - return dest; - } - - public void setFailed(boolean failed) { - this.failed = failed; - } - - public void registerValidator(CompiledBeanValidator validator) { - validators.add(validator); - } - - public boolean hasValidator() { - return !validators.isEmpty(); - } - - /** - * Check that a reference exists in symbol table on second compil pass - * - * @param tag the current tag - * @param reference the required reference - * @param strict flag to report an error if reference was not found - * @param attribute (if not null reference the attribute where is defined the reference) - * @return <code>true</code> if reference was found, <code>false</code> otherwise and add an error in compiler - */ - public boolean checkReference(Element tag, String reference, boolean strict, String attribute) { - String component = getSymbolTable().getClassTagIds().get(reference); - if (component == null) { - if (strict) { - String msg; - if (attribute != null) { - msg = "tag '" + tag.getLocalName() + "' could not find the reference '" + reference + "' on attribute [" + attribute + "]"; - } else { - msg = "tag '" + tag.getLocalName() + "' could not find the reference '" + reference + "'"; - } - reportError(msg); - } - return false; - } - return true; - } -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,1145 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.compiler; + +import jaxx.CompilerException; +import jaxx.UnsupportedAttributeException; +import jaxx.UnsupportedTagException; +import jaxx.css.Rule; +import jaxx.css.Stylesheet; +import jaxx.parser.ParseException; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.FieldDescriptor; +import jaxx.reflect.MethodDescriptor; +import jaxx.runtime.ComponentDescriptor; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.tags.DefaultObjectHandler; +import jaxx.tags.TagHandler; +import jaxx.tags.TagManager; +import jaxx.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Compiles JAXX files into Java classes. + * <p/> + * extends the {@link JAXXCompilerHelper} class wich contains all static usefull method. + * <p/> + * In that way, this class should not contains any static code, but use by inheritance the ones defined in the {@link JAXXCompilerHelper} + * <p/> + * use also a {@link #generator} ({@link JAXXObjectGenerator} to generate the java file, + * after the compilation. + */ +public class JAXXCompiler extends JAXXCompilerHelper { + + /*---------------------------------------------------------------------------------*/ + /*-- compiler fields --------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + /** flag to detec if an error occurs while compiling jaxx file */ + protected boolean failed; + + /** Object corresponding to the root tag in the document. */ + protected CompiledObject root; + + /** Contains strings of the form "javax.swing." */ + protected Set<String> importedPackages = new HashSet<String>(); + + /** Contains strings of the form "javax.swing.Timer" */ + protected Set<String> importedClasses = new HashSet<String>(); + + /** Keeps track of open components (components still having children added). */ + protected Stack<CompiledObject> openComponents = new Stack<CompiledObject>(); + + /** Sequence number used to create automatic variable names. */ + protected int autogenID = 0; + + protected List<DataBinding> dataBindings = new ArrayList<DataBinding>(); + + /** list of validators */ + protected List<CompiledBeanValidator> validators = new ArrayList<CompiledBeanValidator>(); + + /** list of objectId attached to a validator * */ + protected List<String> validatedComponents = new ArrayList<String>(); + + protected SymbolTable symbolTable = new SymbolTable(); + + /** Base directory used for path resolution (normally the directory in which the .jaxx file resides). */ + protected File baseDir; + + /** .jaxx file being compiled. */ + protected File src; + + /** Parsed XML of src file. */ + protected Document document; + + /** Name of class being compiled. */ + protected String outputClassName; + + protected ScriptManager scriptManager = new ScriptManager(this); + + /** Combination of all stylesheets registered using {@link #registerStylesheet}. */ + protected Stylesheet stylesheet; + + /** Contains all attributes defined inline on class tags. */ + protected List<Rule> inlineStyles = new ArrayList<Rule>(); + + /** + * Maps objects (expressed in Java code) to event listener classes (e.g. MouseListener) to Lists of EventHandlers. The final list + * contains all event handlers of a particular type attached to a particular object (again, as represented by a Java expression). + */ + protected Map<String, Map<ClassDescriptor, List<EventHandler>>> eventHandlers = new HashMap<String, Map<ClassDescriptor, List<EventHandler>>>(); + + /** Maps of uniqued id for objects used in compiler */ + protected Map<Object, String> uniqueIds = new HashMap<Object, String>(); + + /** Map of event handler method names used in compiler */ + protected Map<EventHandler, String> eventHandlerMethodNames = new HashMap<EventHandler, String>(); + + /** ClassLoader which searches the user-specified class path in addition to the normal class path */ + protected ClassLoader classLoader; + + /** the generator of the java file */ + protected final JAXXObjectGenerator generator; + + /** + * A list of Runnables which will be run after the first compilation pass. This is primarily used + * to trigger the creation of CompiledObjects, which cannot be created during the first pass and must be + * created in document order. + */ + protected List<Runnable> initializers = new ArrayList<Runnable>(); + + /** left brace matcher */ + protected Matcher leftBraceMatcher = Pattern.compile("^(\\{)|[^\\\\](\\{)").matcher(""); + + /** right brace matcher */ + protected Matcher rightBraceMatcher = Pattern.compile("^(\\})|[^\\\\](\\})").matcher(""); + + /*---------------------------------------------------------------------------------*/ + /*-- Constructor methods ----------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + protected JAXXCompiler(ClassLoader classLoader) { + this.options = new CompilerOptions(); + this.classLoader = classLoader; + this.generator = new JAXXObjectGenerator(this); + addImport("java.lang.*"); + } + + /** + * Creates a new JAXXCompiler. + * + * @param baseDir classpath location + * @param options options to pass to javac + * @param src location of file to compile + * @param outputClassName the out file name + */ + protected JAXXCompiler(File baseDir, File src, String outputClassName, CompilerOptions options) { + this.baseDir = baseDir; + this.src = src; + sourceFiles.push(src); + this.outputClassName = outputClassName; + this.options = options; + this.generator = new JAXXObjectGenerator(this); + addImport(outputClassName.substring(0, outputClassName.lastIndexOf(".") + 1) + "*"); + for (Object staticImport : staticImports) { + addImport((String) staticImport); + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- Initializer methods -----------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + protected void runInitializers() { + for (Runnable runnable : initializers) { + if (log.isDebugEnabled()) { + log.debug(runnable); + } + try { + runnable.run(); + } catch (Exception e) { + //TC - 20081018 report error and quit + reportError(e.getMessage()); + return; + } + } + initializers.clear(); + } + + + /** + * Registers a <code>Runnable</code> which will be executed after the first + * compilation pass is complete. + * + * @param r runnable to register + */ + public void registerInitializer(Runnable r) { + initializers.add(r); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Compile methods --------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void compileFirstPass(final Element tag) throws IOException { + tagsBeingCompiled.push(tag); + + String namespace = tag.getNamespaceURI(); + String fullClassName; + String localName = tag.getLocalName(); + boolean namespacePrefix = tag.getPrefix() != null; + // resolve class tags into fully-qualified class name + if (namespace != null && namespace.endsWith("*")) { + String packageName = namespace.substring(0, namespace.length() - 1); + if (localName.startsWith(packageName)) // class name is fully-qualified already + { + fullClassName = TagManager.resolveClassName(localName, this); + } else { // namespace not included in class name, probably need the namespace to resolve + fullClassName = TagManager.resolveClassName(packageName + localName, this); + if (fullClassName == null && !namespacePrefix) // it was just a default namespace, try again without using the namespace + { + fullClassName = TagManager.resolveClassName(localName, this); + } + } + } else { + fullClassName = TagManager.resolveClassName(localName, this); + } + + if (fullClassName != null) { // we are definitely dealing with a class tag + addDependencyClass(fullClassName); + namespace = fullClassName.substring(0, fullClassName.lastIndexOf(".") + 1) + "*"; + if (symbolTable.getSuperclassName() == null) { + symbolTable.setSuperclassName(fullClassName); + } + String id = tag.getAttribute("id"); + if (id.length() > 0) { + symbolTable.getClassTagIds().put(id, fullClassName); + } + } + // during the first pass, we can't create ClassDescriptors for JAXX files because they may not have been processed yet + // (and we can't wait until they have been processed because of circular dependencies). So we don't do any processing + // during the first pass which requires having a ClassDescriptor; here we determine whether we have a class tag or not + // (class tag namespaces end in "*") and use a generic handler if so. The real handler is used during the second pass. + TagHandler handler = (namespace != null && namespace.endsWith("*")) ? firstPassClassTagHandler : TagManager.getTagHandler(tag.getNamespaceURI(), localName, namespacePrefix, this); + if (handler != firstPassClassTagHandler && handler instanceof DefaultObjectHandler) { + fullClassName = ((DefaultObjectHandler) handler).getBeanClass().getName(); + //namespace = fullClassName.substring(0, fullClassName.lastIndexOf(".") + 1) + "*"; + handler = firstPassClassTagHandler; + } + if (handler == firstPassClassTagHandler) { + final String finalClassName = fullClassName; + registerInitializer(new Runnable() { // register an initializer which will create the CompiledObject after pass 1 + + public void run() { + DefaultObjectHandler handler = (DefaultObjectHandler) TagManager.getTagHandler(null, finalClassName, JAXXCompiler.this); + if (handler == null) { + throw new CompilerException("Internal error: missing TagHandler for '" + finalClassName + "'"); + } + handler.registerCompiledObject(tag, JAXXCompiler.this); + } + }); + } + if (handler != null) { + try { + handler.compileFirstPass(tag, this); + } + catch (CompilerException e) { + reportError(e); + } + } else { + reportError("Could not find a Java class corresponding to: <" + tag.getTagName() + ">"); + failed = true; + } + + Element finished = tagsBeingCompiled.pop(); + if (finished != tag) { + throw new RuntimeException("internal error: just finished compiling " + tag + ", but top of tagsBeingCompiled stack is " + finished); + } + } + + + public void compileSecondPass(Element tag) throws IOException { + tagsBeingCompiled.push(tag); + + TagHandler handler = TagManager.getTagHandler(tag.getNamespaceURI(), tag.getLocalName(), tag.getPrefix() != null, this); + if (handler != null) { + handler.compileSecondPass(tag, this); + } else { + reportError("Could not find a Java class corresponding to: <" + tag.getTagName() + ">"); + assert false : "can't-happen error: error should have been reported during the fast pass and caused an abort"; + failed = true; + } + + Element finished = tagsBeingCompiled.pop(); + if (finished != tag) { + throw new RuntimeException("internal error: just finished compiling " + tag + ", but top of tagsBeingCompiled stack is " + finished); + } + + } + + protected void compileFirstPass() throws IOException { + try { + InputStream in = new FileInputStream(src); + document = parseDocument(in); + in.close(); + compileFirstPass(document.getDocumentElement()); + } + catch (SAXParseException e) { + reportError(e.getLineNumber(), "Invalid XML: " + e.getMessage()); + } + catch (SAXException e) { + reportError(null, "Error parsing XML document: " + e); + } + } + + protected void compileSecondPass() throws IOException { + if (!tagsBeingCompiled.isEmpty()) { + throw new RuntimeException("Internal error: starting pass two, but tagsBeingCompiled is not empty: " + tagsBeingCompiled); + } + compileSecondPass(document.getDocumentElement()); + } + + /*---------------------------------------------------------------------------------*/ + /*-- CompiledObject methods -------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void openComponent(CompiledObject component) throws CompilerException { + openComponent(component, null); + } + + public void openComponent(CompiledObject component, String constraints) throws CompilerException { + CompiledObject parent = getOpenComponent(); + openInvisibleComponent(component); + if (parent != null && !component.isOverride()) { + parent.addChild(component, constraints, this); + } + } + + public void openInvisibleComponent(CompiledObject component) { + if (!ids.containsKey(component)) { + registerCompiledObject(component); + } + openComponents.push(component); + } + + public CompiledObject getOpenComponent() { + if (openComponents.isEmpty()) { + return null; + } + return openComponents.peek(); + } + + public void closeComponent(CompiledObject component) { + if (openComponents.pop() != component) { + throw new IllegalArgumentException("can only close the topmost open object"); + } + } + + public void registerCompiledObject(CompiledObject object) { + assert symbolTables.values().contains(symbolTable) : "attempting to register CompiledObject before pass 1 is complete"; + if (root == null) { + root = object; + } + + String id = object.getId(); + if (ids.containsKey(object)) { + reportError("object '" + object + "' is already registered with id '" + ids.get(object) + "', cannot re-register as '" + id + "'"); + } + if (objects.containsKey(id) && !(objects.get(id) instanceof Element)) { + reportError("id '" + id + "' is already registered to component " + objects.get(id)); + } + objects.put(id, object); + ids.put(object, id); + } + + public CompiledObject getCompiledObject(String id) { + runInitializers(); + assert symbolTables.values().contains(symbolTable) : "attempting to retrieve CompiledObject before pass 1 is complete"; + return objects.get(id); + } + + + protected boolean inlineCreation(CompiledObject object) { + return object.getId().startsWith("$") && object.getInitializationCode(this).length() < INLINE_THRESHOLD; + } + + public void checkOverride(CompiledObject object) throws CompilerException { + if (object.getId().startsWith("$")) { + return; + } + ClassDescriptor ancestor = root.getObjectClass(); + if (ancestor == object.getObjectClass()) { + return; + } + while (ancestor != null) { + try { + FieldDescriptor f = ancestor.getDeclaredFieldDescriptor(object.getId()); + if (!f.getType().isAssignableFrom(object.getObjectClass())) { + reportError("attempting to redefine superclass member '" + object.getId() + "' as incompatible type (was " + f.getType() + ", redefined as " + object.getObjectClass() + ")"); + } + object.setOverride(true); + break; + } + catch (NoSuchFieldException e) { + ancestor = ancestor.getSuperclass(); + } + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- DataBinding methods ----------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + /** + * Examine an attribute value for data binding expressions. Returns a 'cooked' expression which + * can be used to determine the resulting value. It is expected that this expression will be used + * as the source expression in a call to {@link #registerDataBinding}. + * If the attribute value does not invoke data binding, this method returns <code>null</code> + * + * @param stringValue the string value of the property from the XML + * @param type the type of the property, from the <code>JAXXPropertyDescriptor</code> + * @return a processed version of the expression + * @throws jaxx.CompilerException ? + */ + public String processDataBindings(String stringValue, ClassDescriptor type) throws CompilerException { + int pos = getNextLeftBrace(stringValue, 0); + if (pos != -1) { + StringBuffer expression = new StringBuffer(); + int lastPos = 0; + while (pos != -1 && pos < stringValue.length()) { + if (pos > lastPos) { + if (expression.length() > 0) { + expression.append(" + "); + } + expression.append('"'); + expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos, pos))); + expression.append('"'); + } + + if (expression.length() > 0) { + expression.append(" + "); + } + expression.append('('); + int pos2 = getNextRightBrace(stringValue, pos + 1); + if (pos2 == -1) { + reportError("unmatched '{' in expression: " + stringValue); + return ""; + } + expression.append(stringValue.substring(pos + 1, pos2)); + expression.append(')'); + pos2++; + if (pos2 < stringValue.length()) { + pos = getNextLeftBrace(stringValue, pos2); + lastPos = pos2; + } else { + pos = stringValue.length(); + lastPos = pos; + } + } + if (lastPos < stringValue.length()) { + if (expression.length() > 0) { + expression.append(" + "); + } + expression.append('"'); + expression.append(JAXXCompiler.escapeJavaString(stringValue.substring(lastPos))); + expression.append('"'); + } + return type == ClassDescriptorLoader.getClassDescriptor(String.class) ? "String.valueOf(" + expression + ")" : expression.toString(); + } + return null; + } + + + public void registerDataBinding(String src, String dest, String assignment) { + try { + src = checkJavaCode(src); + dataBindings.add(new DataBinding(src, dest, assignment, this)); + } + catch (CompilerException e) { + reportError("While parsing data binding for '" + dest.substring(dest.lastIndexOf(".") + 1) + "': " + e.getMessage()); + } + } + + public void registerEventHandler(EventHandler handler) { + String objectCode = handler.getObjectCode(); + Map<ClassDescriptor, List<EventHandler>> listeners = eventHandlers.get(objectCode); + if (listeners == null) { + listeners = new HashMap<ClassDescriptor, List<EventHandler>>(); + eventHandlers.put(objectCode, listeners); + } + ClassDescriptor listenerClass = handler.getListenerClass(); + List<EventHandler> handlerList = listeners.get(listenerClass); + if (handlerList == null) { + handlerList = new ArrayList<EventHandler>(); + listeners.put(listenerClass, handlerList); + } + handlerList.add(handler); + } + + public String getEventHandlerMethodName(EventHandler handler) { + String result = eventHandlerMethodNames.get(handler); + if (result == null) { + result = "$ev" + eventHandlerMethodNames.size(); + eventHandlerMethodNames.put(handler, result); + } + return result; + } + + /*---------------------------------------------------------------------------------*/ + /*-- Script methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void addScriptField(FieldDescriptor field) { + symbolTable.getScriptFields().add(field); + } + + public void addScriptMethod(MethodDescriptor method) { + if (method.getName().equals("main") && method.getParameterTypes().length == 1 && method.getParameterTypes()[0].getName().equals("[Ljava.lang.String;")) { + generator.setMainDeclared(true); + } + symbolTable.getScriptMethods().add(method); + } + + public void registerScript(String script) throws CompilerException { + registerScript(script, null); + } + + public void registerScript(String script, File sourceFile) throws CompilerException { + if (sourceFile != null) { + sourceFiles.push(sourceFile); + } + script = script.trim(); + if (!"".equals(script) && !script.endsWith("}") && !script.endsWith(";")) { + script += ";"; + } + scriptManager.registerScript(script); + + if (sourceFile != null) { + File pop = sourceFiles.pop(); + if (pop != sourceFile) { + throw new RuntimeException("leaving registerScript(), but " + sourceFile + " was not the top entry on the stack (found " + pop + " instead)"); + } + } + } + + public String preprocessScript(String script) throws CompilerException { + return scriptManager.preprocessScript(script); + } + + /*---------------------------------------------------------------------------------*/ + /*-- StyleSheet methods -----------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + protected void applyStylesheets() { + for (Object o : new ArrayList<CompiledObject>(objects.values())) { + CompiledObject object = (CompiledObject) o; + TagManager.getTagHandler(object.getObjectClass()).applyStylesheets(object, this); + } + } + + public void registerStylesheet(Stylesheet stylesheet) { + if (this.stylesheet == null) { + this.stylesheet = stylesheet; + } else { + this.stylesheet.add(stylesheet.getRules()); + } + } + + public void addInlineStyle(CompiledObject object, String propertyName, boolean dataBinding) { + inlineStyles.add(Rule.inlineAttribute(object, propertyName, dataBinding)); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Report methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void reportWarning(String warning) { + Element currentTag = null; + if (!tagsBeingCompiled.isEmpty()) { + currentTag = tagsBeingCompiled.peek(); + } + reportWarning(currentTag, warning, 0); + } + + + public void reportWarning(Element tag, String warning, int lineOffset) { + String lineNumber = null; + if (tag != null) { + String lineAttr = tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); + if (lineAttr.length() > 0) { + lineNumber = lineAttr; + } + } + File src = sourceFiles.peek(); + try { + src = src.getCanonicalFile(); + } + catch (IOException e) { + // ignore ? + } + + System.err.print(src); + if (lineNumber != null) { + System.err.print(":" + ((sourceFiles.size() == 1) ? Integer.parseInt(lineNumber) + lineOffset : lineOffset + 1)); + } + System.err.println(": Warning: " + warning); + warningCount++; + } + + + public void reportError(String error) { + Element currentTag = null; + if (!tagsBeingCompiled.isEmpty()) { + currentTag = tagsBeingCompiled.peek(); + } + reportError(currentTag, error); + } + + public void reportError(CompilerException ex) { + reportError(null, ex); + } + + public void reportError(String extraMessage, CompilerException ex) { + String message = ex.getMessage(); + if (ex.getClass() == UnsupportedAttributeException.class || ex.getClass() == UnsupportedTagException.class) { + message = ex.getClass().getName().substring(ex.getClass().getName().lastIndexOf(".") + 1) + ": " + message; + } + int lineOffset; + if (ex instanceof ParseException) { + lineOffset = Math.max(0, ((ParseException) ex).getLine() - 1); + } else { + lineOffset = 0; + } + Element currentTag = null; + if (!tagsBeingCompiled.isEmpty()) { + currentTag = tagsBeingCompiled.peek(); + } + reportError(currentTag, extraMessage != null ? extraMessage + message : message, lineOffset); + } + + public void reportError(Element tag, String error) { + reportError(tag, error, 0); + } + + public void reportError(Element tag, String error, int lineOffset) { + int lineNumber = 0; + if (tag != null) { + String lineAttr = tag.getAttributeNS(JAXX_INTERNAL_NAMESPACE, "line"); + if (lineAttr.length() > 0) { + lineNumber = Integer.parseInt(lineAttr); + } + } + lineNumber = Math.max(lineNumber, 1) + lineOffset; + reportError(lineNumber, error); + } + + public void reportError(int lineNumber, String error) { + File src = sourceFiles.isEmpty() ? null : sourceFiles.peek(); + try { + if (src != null) { + src = src.getCanonicalFile(); + } + } + catch (IOException e) { + // ignore ? + } + + System.err.print(src != null ? src.getPath() : "<unknown source>"); + if (lineNumber > 0) { + System.err.print(":" + lineNumber); + } + System.err.println(": " + error); + errorCount++; + failed = true; + } + + /*---------------------------------------------------------------------------------*/ + /*-- Validator methods ------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + /** + * Register in this compiler a new compiled validator. + * + * @param validator the compiled validator to register + */ + public void registerValidator(CompiledBeanValidator validator) { + validators.add(validator); + validatedComponents.addAll(validator.getFields().values()); + } + + /** @return <code>true</code> if some validators were detected, <code>false</code> otherwise */ + public boolean hasValidator() { + return !validators.isEmpty(); + } + + /** + * Test if a given CompiledObject is attached to a validator. + * + * @param componentId the compiled object to test + * @return <code>true</code> if the given compiled object is attached to a validator, <code>false</code> otherwise + */ + public boolean isComponentUsedByValidator(String componentId) { + return validatedComponents.contains(componentId); + } + + /** + * Test if a given bean is attached to a validator. + * + * @param beanId the bean to test + * @return <code>true</code> if the given bean is attached to a validator, <code>false</code> otherwise + */ + public boolean isBeanUsedByValidator(String beanId) { + for (CompiledBeanValidator validator : validators) { + if (beanId.equals(validator.getBean())) { + return true; + } + } + return false; + } + + /*---------------------------------------------------------------------------------*/ + /*-- Getter methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public Map<String, CompiledObject> getObjects() { + return objects; + } + + public List<DataBinding> getDataBindings() { + return dataBindings; + } + + public List<CompiledBeanValidator> getValidators() { + return validators; + } + + public Map<String, Map<ClassDescriptor, List<EventHandler>>> getEventHandlers() { + return eventHandlers; + } + + public CompilerOptions getOptions() { + return options; + } + + public String getOutputClassName() { + return outputClassName; + } + + public File getBaseDir() { + return baseDir; + } + + public Set<String> getImportedClasses() { + return importedClasses; + } + + public Set<String> getImportedPackages() { + return importedPackages; + } + + protected Iterator<CompiledObject> getObjectCreationOrder() { + return objects.values().iterator(); + } + + public CompiledObject getRootObject() { + return root; + } + + public Stack<File> getSourceFiles() { + return sourceFiles; + } + + public ScriptManager getScriptManager() { + return scriptManager; + } + + public SymbolTable getSymbolTable() { + return symbolTable; + } + + public Stylesheet getStylesheet() { + Stylesheet merged = new Stylesheet(); + if (stylesheet != null) { + merged.add(stylesheet.getRules()); + } + merged.add(inlineStyles.toArray(new Rule[inlineStyles.size()])); + return merged; + } + + public FieldDescriptor[] getScriptFields() { + List<FieldDescriptor> scriptFields = symbolTable.getScriptFields(); + return scriptFields.toArray(new FieldDescriptor[scriptFields.size()]); + } + + public MethodDescriptor[] getScriptMethods() { + List<MethodDescriptor> scriptMethods = symbolTable.getScriptMethods(); + return scriptMethods.toArray(new MethodDescriptor[scriptMethods.size()]); + } + + /** + * Returns a <code>ClassLoader</code> which searches the user-specified class path in addition + * to the normal system class path. + * + * @return <code>ClassLoader</code> to use while resolving class references + */ + public ClassLoader getClassLoader() { + if (classLoader == null) { + String classPath = options.getClassPath(); + if (classPath == null) { + classPath = "."; + } + String[] paths = classPath.split(File.pathSeparator); + URL[] urls = new URL[paths.length]; + for (int i = 0; i < paths.length; i++) { + try { + urls[i] = new File(paths[i]).toURI().toURL(); + } + catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + classLoader = new URLClassLoader(urls, getClass().getClassLoader()); + } + + return classLoader; + } + + public JAXXObjectDescriptor getJAXXObjectDescriptor() { + runInitializers(); + CompiledObject[] components = new ArrayList<CompiledObject>(objects.values()).toArray(new CompiledObject[objects.size()]); + assert initializers.isEmpty() : "there are pending initializers remaining"; + assert root != null : "root object has not been defined"; + assert Arrays.asList(components).contains(root) : "root object is not registered"; + ComponentDescriptor[] descriptors = new ComponentDescriptor[components.length]; + // as we print, sort the array so that component's parents are always before the components themselves + for (int i = 0; i < components.length; i++) { + CompiledObject parent = components[i].getParent(); + while (parent != null) { + boolean found = false; + for (int j = i + 1; j < components.length; j++) { // found parent after component, swap them + if (components[j] == parent) { + components[j] = components[i]; + components[i] = parent; + found = true; + break; + } + } + if (!found) { + break; + } + parent = components[i].getParent(); + } + int parentIndex = -1; + if (parent != null) { + for (int j = 0; j < i; j++) { + if (components[j] == parent) { + parentIndex = j; + break; + } + } + } + descriptors[i] = new ComponentDescriptor(components[i].getId(), components[i] == root ? outputClassName : components[i].getObjectClass().getName(), + components[i].getStyleClass(), parentIndex != -1 ? descriptors[parentIndex] : null); + } + + Stylesheet stylesheet = getStylesheet(); + if (stylesheet == null) { + stylesheet = new Stylesheet(); + } + + return new JAXXObjectDescriptor(descriptors, stylesheet); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Setter methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void setFailed(boolean failed) { + this.failed = failed; + } + + /*---------------------------------------------------------------------------------*/ + /*-- Delegate methods from JAXXObjectGenerator ------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void appendInitializerCode(String code) { + generator.getInitializer().append(code); + } + + public void appendBodyCode(String code) { + generator.getBodyCode().append(code); + } + + public void appendInitDataBindings(String code) { + generator.getInitDataBindings().append(code); + } + + public void appendProcessDataBinding(String code) { + generator.getProcessDataBinding().append(code); + } + + public void appendApplyDataBinding(String code) { + generator.getApplyDataBinding().append(code); + } + + public void appendRemoveDataBinding(String code) { + generator.getRemoveDataBinding().append(code); + } + + public void appendLateInitializer(String code) { + generator.getLateInitializer().append(code); + } + + public boolean haveProcessDataBinding() { + return generator.getProcessDataBinding().length() > 0; + } + + public boolean haveApplyDataBinding() { + return generator.getApplyDataBinding().length() > 0; + } + + public boolean haveRemoveDataBinding() { + return generator.getRemoveDataBinding().length() > 0; + } + + public void addMethodToJavaFile(JavaMethod method) { + generator.getJavaFile().addMethod(method); + } + + public boolean hasMethod(String methodName) { + JavaMethod[] methods = generator.getJavaFile().getMethods(); + for (JavaMethod method : methods) { + if (methodName.equals(method.getName())) { + return true; + } + } + return false; + } + + /*---------------------------------------------------------------------------------*/ + /*-- Other methods ----------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void addImport(String text) { + if (text.endsWith("*")) { + importedPackages.add(text.substring(0, text.length() - 1)); + } else { + importedClasses.add(text); + } + + if (!text.equals("*")) { + generator.getJavaFile().addImport(text); + } + } + + public void addDependencyClass(String className) { + if (!jaxxFileClassNames.contains(className)) { + URL jaxxURL = getClassLoader().getResource(className.replace('.', '/') + ".jaxx"); + URL classURL = getClassLoader().getResource(className.replace('.', '/') + ".class"); + if (jaxxURL != null && classURL != null) { + try { + File jaxxFile = URLtoFile(jaxxURL); + File classFile = URLtoFile(classURL); + if (classFile.lastModified() > jaxxFile.lastModified()) { + return; // class file is newer, no need to recompile + } + } + catch (Exception e) { + // do nothing + } + } + + if (jaxxURL != null && jaxxURL.toString().startsWith("file:")) { + File jaxxFile = URLtoFile(jaxxURL); + try { + jaxxFile = jaxxFile.getCanonicalFile(); + } + catch (IOException ex) { + // ignore ? + } + assert jaxxFile.getName().equalsIgnoreCase(className.substring(className.lastIndexOf(".") + 1) + ".jaxx") : + "expecting file name to match " + className + ", but found " + jaxxFile.getName(); + if (jaxxFile.getName().equals(className.substring(className.lastIndexOf(".") + 1) + ".jaxx")) { // check case match + if (currentPass == PASS_2) { + throw new AssertionError("Internal error: adding dependency class " + className + " during second compilation pass"); + } + jaxxFileClassNames.add(className); + jaxxFiles.add(jaxxFile); + } + } + } + } + + /** + * Verifies that a snippet of Java code parses correctly. A warning is generated if the string has enclosing + * curly braces. + * + * @param javaCode the Java code snippet to test + * @return a "cooked" version of the string which has enclosing curly braces removed. + * @throws CompilerException if the code cannot be parsed + */ + public String checkJavaCode(String javaCode) { + javaCode = scriptManager.trimScript(javaCode); + scriptManager.checkParse(javaCode); + return javaCode; + } + + /** + * Check that a reference exists in symbol table on second compil pass + * + * @param tag the current tag + * @param reference the required reference + * @param strict flag to report an error if reference was not found + * @param attribute (if not null reference the attribute where is defined the reference) + * @return <code>true</code> if reference was found, <code>false</code> otherwise and add an error in compiler + */ + public boolean checkReference(Element tag, String reference, boolean strict, String attribute) { + String component = getSymbolTable().getClassTagIds().get(reference); + if (component == null) { + if (strict) { + String msg; + if (attribute != null) { + msg = "tag '" + tag.getLocalName() + "' could not find the reference '" + reference + "' on attribute [" + attribute + "]"; + } else { + msg = "tag '" + tag.getLocalName() + "' could not find the reference '" + reference + "'"; + } + reportError(msg); + } + return false; + } + return true; + } + + protected int getNextLeftBrace(String string, int pos) { + leftBraceMatcher.reset(string); + return leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; + } + + protected int getNextRightBrace(String string, int pos) { + leftBraceMatcher.reset(string); + rightBraceMatcher.reset(string); + int openCount = 1; + int rightPos; + while (openCount > 0) { + pos++; + int leftPos = leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; + rightPos = rightBraceMatcher.find(pos) ? Math.max(rightBraceMatcher.start(1), rightBraceMatcher.start(2)) : -1; + assert leftPos == -1 || leftPos >= pos; + assert rightPos == -1 || rightPos >= pos; + if (leftPos != -1 && leftPos < rightPos) { + pos = leftPos; + openCount++; + } else if (rightPos != -1) { + pos = rightPos; + openCount--; + } else { + openCount = 0; + } + } + return pos; + } + + public String[] parseParameterList(String parameters) throws CompilerException { + List<String> result = new ArrayList<String>(); + StringBuffer current = new StringBuffer(); + int state = 0; // normal + for (int i = 0; i < parameters.length(); i++) { + char c = parameters.charAt(i); + switch (state) { + case 0: // normal + switch (c) { + case '"': + current.append(c); + state = 1; + break; // in quoted string + case '\\': + current.append(c); + state = 2; + break; // immediately after backslash + case ',': + if (current.length() > 0) { + result.add(current.toString()); + current.setLength(0); + break; + } else { + reportError("error parsing parameter list: " + parameters); + } + default: + current.append(c); + } + break; + case 1: // in quoted string + switch (c) { + case '"': + current.append(c); + state = 0; + break; // normal + case '\\': + current.append(c); + state = 3; + break; // immediate after backslash in quoted string + default: + current.append(c); + } + break; + case 2: // immediately after backslash + current.append(c); + state = 0; // normal + break; + case 3: // immediately after backslash in quoted string + current.append(c); + state = 1; // in quoted string + break; + } + } + if (current.length() > 0) { + result.add(current.toString()); + } + return result.toArray(new String[result.size()]); + } + + public String getAutoId(ClassDescriptor objectClass) { + if (options.getOptimize()) { + return "$" + Integer.toString(autogenID++, 36); + } else { + String name = objectClass.getName(); + name = name.substring(name.lastIndexOf(".") + 1); + return "$" + name + autogenID++; + } + } + + public String getUniqueId(Object object) { + String result = uniqueIds.get(object); + if (result == null) { + result = "$u" + uniqueIds.size(); + uniqueIds.put(object, result); + } + return result; + } + +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,657 @@ +package jaxx.compiler; + +import jaxx.CompilerException; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.spi.Initializer; +import jaxx.tags.DefaultObjectHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.XMLFilterImpl; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.Stack; + +/** @author chemit */ +public class JAXXCompilerHelper { + + /** log */ + protected static final Log log = LogFactory.getLog(JAXXCompiler.class); + + /** + * True to throw exceptions when we encounter unresolvable classes, false to ignore. + * This is currently set to false until JAXX has full support for inner classes + * (including enumerations), because currently they don't always resolve (but will + * generally compile without error anyway). + */ + public static final boolean STRICT_CHECKS = false; + + public static final String JAXX_NAMESPACE = "http://www.jaxxframework.org/"; + + public static final String JAXX_INTERNAL_NAMESPACE = "http://www.jaxxframework.org/internal"; + + /** Maximum length of an inlinable creation method. */ + protected static final int INLINE_THRESHOLD = 300; + + protected static final int PASS_1 = 0; + + protected static final int PASS_2 = 1; + + /** Contains import declarations (of the form "javax.swing.") which are always imported in all compiler instances. */ + protected static List<String> staticImports = new ArrayList<String>(); + + static { + //TODO humm, we should be able to import only what is needed + staticImports.add("java.awt.*"); + staticImports.add("java.awt.event.*"); + staticImports.add("java.beans.*"); + staticImports.add("java.io.*"); + staticImports.add("java.lang.*"); + staticImports.add("java.util.*"); + staticImports.add("javax.swing.*"); + staticImports.add("javax.swing.border.*"); + staticImports.add("javax.swing.event.*"); + staticImports.add("jaxx.runtime.swing.JAXXButtonGroup"); + staticImports.add("jaxx.runtime.swing.HBox"); + staticImports.add("jaxx.runtime.swing.VBox"); + staticImports.add("jaxx.runtime.swing.Table"); + staticImports.add("static org.codelutin.i18n.I18n._"); + staticImports.add("static org.codelutin.jaxx.util.UIHelper.createImageIcon"); + } + + protected static DefaultObjectHandler firstPassClassTagHandler = new DefaultObjectHandler(ClassDescriptorLoader.getClassDescriptor(Object.class)); + + /** Files being compiled during the compilation session, may be modified as compilation progresses and additional dependencies are found. */ + protected static List<File> jaxxFiles = new ArrayList<File>(); + + /** Class names corresponding to the files in the jaxxFiles list. */ + protected static List<String> jaxxFileClassNames = new ArrayList<String>(); + + /** Maps the names of classes being compiled to the compiler instance handling the compilation. */ + protected static Map<String, JAXXCompiler> compilers = new HashMap<String, JAXXCompiler>(); + + /** Maps the names of classes being compiled to their symbol tables (created after the first compiler pass). */ + protected static Map<File, SymbolTable> symbolTables = new HashMap<File, SymbolTable>(); + + protected static int currentPass; + + protected CompilerOptions options; + + /** Used for error reporting purposes, so we can report the right line number. */ + protected Stack<Element> tagsBeingCompiled = new Stack<Element>(); + + /** Used for error reporting purposes, so we can report the right source file. */ + protected Stack<File> sourceFiles = new Stack<File>(); + + /** Maps object ID strings to the objects themselves. These are created during the second compilation pass. */ + protected Map<String, CompiledObject> objects = new LinkedHashMap<String, CompiledObject>(); + + /** Maps objects to their ID strings. These are created during the second compilation pass. */ + protected Map<CompiledObject, String> ids = new LinkedHashMap<CompiledObject, String>(); + + protected static int errorCount; + protected static int warningCount; + + public static void loadLibraries(boolean verbose) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); + if (verbose) { + log.info("with cl " + classloader); + } + ServiceLoader<Initializer> loader = ServiceLoader.load(Initializer.class, classloader); + for (Initializer initializer : loader) { + if (verbose) { + log.info("load initializer " + initializer); + } + initializer.initialize(); + } + } + + public static void init() { + // forces static initializer to run if it hasn't yet + } + + /** Resets all state in preparation for a new compilation session. */ + protected static void reset() { + errorCount = warningCount = 0; + jaxxFiles.clear(); + jaxxFileClassNames.clear(); + symbolTables.clear(); + compilers.clear(); + } + + public static String getVersion() { + return "1.0.4"; + } + + /** + * Creates a dummy JAXXCompiler for use in unit testing. + * + * @return the compiler + */ + public static JAXXCompiler createDummyCompiler() { + return createDummyCompiler(JAXXCompiler.class.getClassLoader()); + } + + /** + * Creates a dummy JAXXCompiler for use in unit testing. + * + * @param classLoader class loader to use + * @return the compiler + */ + public static JAXXCompiler createDummyCompiler(ClassLoader classLoader) { + return new JAXXCompiler(classLoader); + } + + /** + * @param className the name of the class to use + * @return the compiler instance which is processing the specified JAXX class. Each class is compiled by a + * different compiler instance. + */ + public static JAXXCompiler getJAXXCompiler(String className) { + return compilers != null ? compilers.get(className) : null; + } + + /** + * @param className the name of the class to use + * @return the symbol table for the specified JAXX class. Must be called during the second compiler pass. + * Returns <code>null</code> if no such symbol table could be found. + */ + public static SymbolTable getSymbolTable(String className) { + JAXXCompiler compiler = getJAXXCompiler(className); + if (compiler == null) { + return null; + } + return compiler.getSymbolTable(); + } + + /** + * Returns the system line separator string. + * + * @return the string used to separate lines + */ + public static String getLineSeparator() { + return System.getProperty("line.separator", "\n"); + } + + /** + * Compiled a set of files, expressed as paths relative to a base directory. The class names of the compiled files are derived + * from the relative path strings (e.g. "example/Foo.jaxx" compiles into a class named "example.Foo"). Returns <code>true</code> + * if compilation succeeds, <code>false</code> if it fails. Warning and error messages are sent to <code>System.err</code>. + * + * @param base the directory against which to resolve relative paths + * @param relativePaths a list of relative paths to .jaxx files being compiled + * @param options the compiler options to use + * @return <code>true</code> if compilation succeeds, <code>false</code> otherwise + */ + public static synchronized boolean compile(File base, String[] relativePaths, CompilerOptions options) { + File[] files = new File[relativePaths.length]; + String[] classNames = new String[relativePaths.length]; + for (int i = 0; i < files.length; i++) { + files[i] = new File(base, relativePaths[i]); + classNames[i] = relativePaths[i].substring(0, relativePaths[i].lastIndexOf(".")); + classNames[i] = classNames[i].replace(File.separatorChar, '.'); + classNames[i] = classNames[i].replace('/', '.'); + classNames[i] = classNames[i].replace('\\', '.'); + classNames[i] = classNames[i].replace(':', '.'); + } + return compile(files, classNames, options); + } + + /** + * Compiled a set of files, with the class names specified explicitly. The class compiled from files[i] will be named classNames[i]. + * Returns <code>true</code> if compilation succeeds, <code>false</code> if it fails. Warning and error messages are sent to + * <code>System.err</code>. + * + * @param files the .jaxx files to compile + * @param classNames the names of the classes being compiled + * @param options the compiler options to use + * @return <code>true</code> if compilation succeeds, <code>false</code> otherwise + */ + public static synchronized boolean compile(File[] files, String[] classNames, CompilerOptions options) { + reset(); // just to be safe... + jaxxFiles.addAll(Arrays.asList(files)); + jaxxFileClassNames.addAll(Arrays.asList(classNames)); + try { + boolean success = true; + + // pass 1 + currentPass = PASS_1; + boolean compiled; + do { + compiled = false; + assert jaxxFiles.size() == jaxxFileClassNames.size(); + java.util.Iterator<File> filesIterator = new ArrayList<File>(jaxxFiles).iterator(); // clone it so it can safely be modified while we're iterating + java.util.Iterator<String> classNamesIterator = new ArrayList<String>(jaxxFileClassNames).iterator(); + while (filesIterator.hasNext()) { + File file = filesIterator.next(); + String className = classNamesIterator.next(); + if (options.isVerbose()) { + log.info("compile first pass for " + className); + } + if (symbolTables.get(file) == null) { + compiled = true; + if (compilers.containsKey(className)) { + throw new CompilerException("Internal error: " + className + " is already being compiled, attempting to compile it again"); + } + + File destDir = options.getTargetDirectory(); + if (destDir != null) { + int dotPos = className.lastIndexOf("."); + if (dotPos != -1) { + destDir = new File(destDir, className.substring(0, dotPos).replace('.', File.separatorChar)); + } + destDir.mkdirs(); + } else { + //destDir = file.getParentFile(); + } + JAXXCompiler compiler = new JAXXCompiler(file.getParentFile(), file, className, options); + compilers.put(className, compiler); + compiler.compileFirstPass(); + assert !symbolTables.values().contains(compiler.getSymbolTable()) : "symbolTable is already registered"; + symbolTables.put(file, compiler.getSymbolTable()); + if (compiler.failed) { + success = false; + } + } + } + + } while (compiled); + + // pass 2 + currentPass = PASS_2; + if (success) { + assert jaxxFiles.size() == jaxxFileClassNames.size(); + List<File> jaxxFilesClone = new ArrayList<File>(jaxxFiles); + for (String className : jaxxFileClassNames) { + JAXXCompiler compiler = compilers.get(className); + if (compiler == null) { + throw new CompilerException("Internal error: could not find compiler for " + className + " during second pass"); + } + if (options.isVerbose()) { + + log.info("runInitializers for " + className); + } + if (!compiler.failed) { + compiler.runInitializers(); + } + if (options.isVerbose()) { + + log.info("compile second pass for " + className); + } + compiler.compileSecondPass(); + if (options.isVerbose()) { + + log.info("done with result [" + !compiler.failed + "] for " + className); + } + if (!compiler.failed) { + + } else { + success = false; + } + } + if (!jaxxFilesClone.equals(jaxxFiles)) { + throw new AssertionError("Internal error: compilation set altered during pass 2 (was " + jaxxFilesClone + ", modified to " + jaxxFiles + ")"); + } + } + + // stylesheet application + if (success) { + assert jaxxFiles.size() == jaxxFileClassNames.size(); + for (String className : jaxxFileClassNames) { + JAXXCompiler compiler = compilers.get(className); + if (compiler == null) { + throw new CompilerException("Internal error: could not find compiler for " + className + " during stylesheet application"); + } + compiler.applyStylesheets(); + if (compiler.failed) { + success = false; + } + } + } + + // code generation + if (success) { + assert jaxxFiles.size() == jaxxFileClassNames.size(); + for (String className : jaxxFileClassNames) { + JAXXCompiler compiler = compilers.get(className); + if (compiler == null) { + throw new CompilerException("Internal error: could not find compiler for " + className + " during code generation"); + } + compiler.generator.generateCode(); + //compiler.generateCode(); + if (compiler.failed) { + success = false; + } + } + } + + if (warningCount == 1) { + System.err.println("1 warning"); + } else if (warningCount > 0) { + System.err.println(warningCount + " warnings"); + } + if (errorCount == 1) { + System.err.println("1 error"); + } else if (errorCount > 0) { + System.err.println(errorCount + " errors"); + } + return success; + } + catch (CompilerException e) { + System.err.println(e.getMessage()); + e.printStackTrace(); + return false; + } + catch (Throwable e) { + e.printStackTrace(); + return false; + } + finally { + //TC - 20081018 only reset when no error was detected + if (errorCount == 0) { + reset(); + } + } + } + + // 1.5 adds getCanonicalName; unfortunately we can't depend on 1.5 features yet + public static String getCanonicalName(Class clazz) { + if (clazz.isArray()) { + String canonicalName = getCanonicalName(clazz.getComponentType()); + if (canonicalName != null) { + return canonicalName + "[]"; + } + return null; + } + return clazz.getName().replace('$', '.'); + } + + public static String getCanonicalName(ClassDescriptor clazz) { + if (clazz.isArray()) { + String canonicalName = getCanonicalName(clazz.getComponentType()); + if (canonicalName != null) { + return canonicalName + "[]"; + } + return null; + } + return clazz.getName().replace('$', '.'); + } + + public static String getCanonicalName(CompiledObject compiled) { + ClassDescriptor clazz = compiled.getObjectClass(); + if (clazz.isArray()) { + String canonicalName = getCanonicalName(clazz.getComponentType()); + if (canonicalName != null) { + if (compiled.getGenericTypes().length > 0) { + canonicalName += "<"; + for (int i = 0; i < compiled.getGenericTypes().length; i++) { + ClassDescriptor classDescriptor = compiled.getGenericTypes()[i]; + if (i > 0) { + canonicalName += " ,"; + } + canonicalName += classDescriptor.getName(); + } + canonicalName += ">"; + } + return canonicalName + "[]"; + } + return null; + } + + String canonicalName = clazz.getName().replace('$', '.'); + if (compiled.getGenericTypes().length > 0) { + canonicalName += "<"; + for (int i = 0; i < compiled.getGenericTypes().length; i++) { + ClassDescriptor classDescriptor = compiled.getGenericTypes()[i]; + if (i > 0) { + canonicalName += " ,"; + } + canonicalName += classDescriptor.getName(); + } + canonicalName += ">"; + } + return canonicalName; + } + + public static String capitalize(String s) { + if (s.length() == 0) { + return s; + } + return Character.toUpperCase(s.charAt(0)) + s.substring(1); + } + + /** + * Escapes a string using standard Java escape sequences, generally in preparation to including it in a string literal + * in a compiled Java file. + * + * @param raw the raw string to be escape + * @return a string in which all 'dangerous' characters have been replaced by equivalent Java escape sequences + */ + public static String escapeJavaString(String raw) { + StringBuffer out = new StringBuffer(raw); + for (int i = 0; i < out.length(); i++) { + char c = out.charAt(i); + if (c == '\\' || c == '"') { + out.insert(i, '\\'); + i++; + } else if (c == '\n') { + out.replace(i, i + 1, "\\n"); + i++; + } else if (c == '\r') { + out.replace(i, i + 1, "\\r"); + i++; + } else if (c < 32 || c > 127) { + String value = Integer.toString((int) c, 16); + while (value.length() < 4) { + value = "0" + value; + } + out.replace(i, i + 1, "\\u" + value); + i += 5; + } + } + return out.toString(); + } + + public static File URLtoFile(URL url) { + return URLtoFile(url.toString()); + } + + public static File URLtoFile(String urlString) { + if (!urlString.startsWith("file:")) { + throw new IllegalArgumentException("url must start with 'file:'"); + } + urlString = urlString.substring("file:".length()); + if (urlString.startsWith("/") && System.getProperty("os.name").startsWith("Windows")) { + urlString = urlString.substring(1); + } + try { + return new File(URLDecoder.decode(urlString.replace('/', File.separatorChar), "utf-8")); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static SAXParser getSAXParser() { + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setNamespaceAware(true); + SAXParser parser; + parser = factory.newSAXParser(); + return parser; + } + catch (SAXException e) { + throw new RuntimeException(e); + } + catch (ParserConfigurationException e) { + throw new RuntimeException(e); + } + } + + public static Document parseDocument(InputStream in) throws IOException, SAXException { + try { + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); + transformer.setErrorListener(new ErrorListener() { + public void warning(TransformerException ex) throws TransformerException { + throw ex; + } + + public void error(TransformerException ex) throws TransformerException { + throw ex; + } + + public void fatalError(TransformerException ex) throws TransformerException { + throw ex; + } + }); + + DOMResult result = new DOMResult(); + transformer.transform(new SAXSource(new XMLFilterImpl(getSAXParser().getXMLReader()) { + Locator locator; + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { + AttributesImpl resultAtts = new AttributesImpl(atts); + resultAtts.addAttribute(JAXX_INTERNAL_NAMESPACE, "line", "internal:line", "CDATA", String.valueOf(locator.getLineNumber())); + getContentHandler().startElement(uri, localName, qName, resultAtts); + } + }, new InputSource(in)), result); + return (Document) result.getNode(); + } + catch (TransformerConfigurationException e) { + throw new RuntimeException(e); + } + catch (TransformerException e) { + Throwable ex = e; + while (ex.getCause() != null) { + ex = ex.getCause(); + } + if (ex instanceof IOException) { + throw (IOException) ex; + } + if (ex instanceof SAXException) { + throw (SAXException) ex; + } + if (ex instanceof RuntimeException) { + throw (RuntimeException) ex; + } + throw new RuntimeException(ex); + } + } + + protected static void showUsage() { + System.out.println("Usage: jaxxc <options> <source files>"); + System.out.println(); + System.out.println("Source files must end in extension .jaxx"); + System.out.println("Use JAXX_OPTS environment variable to pass arguments to Java runtime"); + System.out.println(); + System.out.println("Supported options include:"); + System.out.println(" -classpath <paths> paths to search for user classes"); + System.out.println(" -cp <paths> same as -classpath"); + System.out.println(" -d <directory> target directory for generated class files"); + System.out.println(" -java or -j produce .java files, but do not compile them"); + System.out.println(" -keep or -k preserve generated .java files after compilation"); + System.out.println(" -optimize or -o optimize during compilation"); + System.out.println(" -version display version information"); + System.out.println(); + System.out.println("See http://www.jaxxframework.org/ for full documentation."); + } + + public static void main(String[] arg) throws Exception { + boolean success = true; + + CompilerOptions options = new CompilerOptions(); + List<String> files = new ArrayList<String>(); + for (int i = 0; i < arg.length; i++) { + if (arg[i].endsWith(".jaxx")) { + files.add(arg[i]); + } else if (arg[i].equals("-d")) { + if (++i < arg.length) { + File targetDirectory = new File(arg[i]); + if (!targetDirectory.exists()) { + System.err.println("Error: could not find target directory: " + targetDirectory); + JAXXCompiler.errorCount++; + success = false; + } + options.setTargetDirectory(targetDirectory); + } else { + success = false; + } + } else if (arg[i].equals("-cp") || arg[i].equals("-classpath")) { + if (++i < arg.length) { + options.setClassPath(arg[i]); + } else { + success = false; + } + } else if (arg[i].equals("-javac_opts")) { + if (++i < arg.length) { + options.setJavacOpts(arg[i]); + } else { + success = false; + } + } else if (arg[i].equals("-k") || arg[i].equals("-keep")) { + options.setKeepJavaFiles(true); + } else if (arg[i].equals("-j") || arg[i].equals("-java")) { + options.setKeepJavaFiles(true); + } else if (arg[i].equals("-o") || arg[i].equals("-optimize")) { + options.setOptimize(true); + } else if (arg[i].equals("-version")) { + System.err.println("jaxxc version " + getVersion() + " by Ethan Nicholas"); + System.err.println("http://www.jaxxframework.org/"); + System.exit(0); + } else if (arg[i].equals("-internalDumpVersion")) { // used by ant to extract the version info + System.out.println("jaxx.version=" + getVersion()); + return; + } else { + success = false; + } + } + + success &= (JAXXCompiler.errorCount == 0 && files.size() > 0); + + if (success) { + success = JAXXCompiler.compile(new File("."), files.toArray(new String[files.size()]), options); + } else { + showUsage(); + System.exit(1); + } + + System.exit(success ? 0 : 1); + } + +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,657 @@ +package jaxx.compiler; + +import jaxx.CompilerException; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.MethodDescriptor; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.runtime.swing.Application; +import jaxx.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import jaxx.types.TypeManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.lang.reflect.Modifier; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPOutputStream; + +/** + * This class is a refactoring of the {@link jaxx.compiler.JAXXCompiler}. + * <p/> + * We delegate now the generation of a {@link jaxx.runtime.JAXXObject} to this class, the + * {@link jaxx.compiler.JAXXCompiler} now only deals with the compilation of files. + * + * @author chemit + */ +public class JAXXObjectGenerator { + + /** log */ + protected static final Log log = LogFactory.getLog(JAXXObjectGenerator.class); + + /** the compile used to parse the file to be generated here. */ + protected JAXXCompiler compiler; + + /** the file to be generated */ + protected JavaFile javaFile = new JavaFile(); + + /** Generated .java file. */ + protected File dest; + + /** Extra code to be added to the instance initializer. */ + protected StringBuffer initializer = new StringBuffer(); + + /** Extra code to be added at the end of the instance initializer. */ + protected StringBuffer lateInitializer = new StringBuffer(); + + /** Extra code to be added to the class body. */ + protected StringBuffer bodyCode = new StringBuffer(); + + /** Code to initialize data bindings. */ + protected StringBuffer initDataBindings = new StringBuffer(); + + /** Body of the applyDataBinding method. */ + protected StringBuffer applyDataBinding = new StringBuffer(); + + /** Body of the removeDataBinding method. */ + protected StringBuffer removeDataBinding = new StringBuffer(); + + /** Body of the processDataBinding method. */ + protected StringBuffer processDataBinding = new StringBuffer(); + + /** true if a main() method has been declared in a script */ + protected boolean mainDeclared; + + public JAXXObjectGenerator(JAXXCompiler compiler) { + this.compiler = compiler; + } + + protected void generateCode() throws IOException { + if (getOptions().getTargetDirectory() != null) { + dest = new File(getOptions().getTargetDirectory(), getOutputClassName().replace('.', File.separatorChar) + ".java"); + } else { + dest = new File(getBaseDir(), getOutputClassName().substring(getOutputClassName().lastIndexOf(".") + 1) + ".java"); + } + if (dest.exists() && !dest.setLastModified(System.currentTimeMillis())) { + log.warn("could not touch file " + dest); + } + PrintWriter out = new PrintWriter(new FileWriter(dest)); + createJavaSource(out); + out.close(); + } + + protected void createJavaSource(PrintWriter out) throws IOException { + int dotPos = getOutputClassName().lastIndexOf("."); + String packageName = dotPos != -1 ? getOutputClassName().substring(0, dotPos) : null; + String simpleClassName = getOutputClassName().substring(dotPos + 1); + outputClass(packageName, simpleClassName, out); + } + + protected void outputClass(String packageName, String className, PrintWriter out) throws CompilerException { + createJavaFile(packageName, className); + out.println(javaFile.toString()); + } + + protected void createJavaFile(String packageName, String className) throws CompilerException { + String fullClassName = packageName != null ? packageName + "." + className : className; + CompiledObject root = compiler.getRootObject(); + if (root == null) { + throw new CompilerException("root tag must be a class tag"); + } + Map<String, CompiledObject> objects = compiler.getObjects(); + ClassDescriptor superclass = root.getObjectClass(); + boolean superclassIsJAXXObject = ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(superclass); + javaFile.setModifiers(Modifier.PUBLIC); + javaFile.setClassName(fullClassName); + javaFile.setSuperClass(JAXXCompiler.getCanonicalName(superclass)); + javaFile.setInterfaces(new String[]{JAXXCompiler.getCanonicalName(JAXXObject.class)}); + + for (CompiledObject object : compiler.getObjects().values()) { + if (!object.isOverride() && !(object instanceof ScriptInitializer)) { + int access = object.getId().startsWith("$") ? Modifier.PRIVATE : Modifier.PROTECTED; + if (object == root) { + javaFile.addField(new JavaField(access, fullClassName, object.getId(), "this")); + } else { + //TC -20081017 can have generic on compiled Object + javaFile.addField(new JavaField(access, JAXXCompiler.getCanonicalName(object), object.getId())); + //javaFile.addField(new JavaField(access, getCanonicalName(object.getObjectClass()), object.getId())); + } + } + } + + if (!superclassIsJAXXObject) { + // add logger + if (getOptions().isAddLogger()) { + javaFile.addImport("org.apache.commons.logging.Log"); + javaFile.addImport("org.apache.commons.logging.LogFactory"); + javaFile.addField(createLoggerField(fullClassName)); + } + + javaFile.addField(new JavaField(Modifier.PROTECTED, "java.util.List<Object>", "$activeBindings", "new ArrayList<Object>()")); + javaFile.addField(new JavaField(Modifier.PROTECTED, "java.util.Map<String,Object>", "$bindingSources", "new HashMap<String,Object>()")); + javaFile.addField(new JavaField(Modifier.PROTECTED, "java.util.List<String>", "validatorIds", "new ArrayList<String>()")); + } + + javaFile.addImport("jaxx.runtime.validator.BeanValidator"); + + if (compiler.getStylesheet() != null) { + javaFile.addField(new JavaField(0, "java.util.Map", "$previousValues", "new java.util.HashMap()")); + } + + javaFile.addMethod(createConstructor(className)); + javaFile.addMethod(createInitializer(className)); + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "BeanValidator<?>", "getValidator", new JavaArgument[]{new JavaArgument("String", "validatorId")}, + null, "return (BeanValidator)(validatorIds.contains(validatorId)?getObjectById(validatorId):null);")); + + for (DataBinding dataBinding : compiler.getDataBindings()) { + if (dataBinding.compile(true)) { + initDataBindings.append("applyDataBinding(").append(TypeManager.getJavaCode(dataBinding.getId())).append(");").append(JAXXCompiler.getLineSeparator()); + } + } + + javaFile.addBodyCode(bodyCode.toString()); + + for (CompiledObject object : objects.values()) { + if (!compiler.inlineCreation(object) && object != root) { + javaFile.addMethod(new JavaMethod(Modifier.PROTECTED, "void", object.getCreationMethodName(), null, null, getCreationCode(object))); + } + } + + javaFile.addField(new JavaField(Modifier.PRIVATE, "boolean", "allComponentsCreated")); + + javaFile.addMethod(createCompleteSetupMethod()); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "applyDataBinding", new JavaArgument[]{new JavaArgument("String", "$binding")}, + null, applyDataBinding.toString() + JAXXCompiler.getLineSeparator() + " processDataBinding($binding);")); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removeDataBinding", new JavaArgument[]{new JavaArgument("String", "$binding")}, + null, removeDataBinding.toString())); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "processDataBinding", new JavaArgument[]{new JavaArgument("String", "dest")}, + null, "processDataBinding(dest, false);")); + + javaFile.addMethod(createProcessDataBindingMethod()); + + if (!superclassIsJAXXObject) { + javaFile.addField(createObjectMap()); + javaFile.addMethod(createGetObjectByIdMethod()); + } + + javaFile.addField(createJAXXObjectDescriptorField()); + javaFile.addMethod(createGetJAXXObjectDescriptorMethod()); + + /* + * Gestion du context + */ + javaFile.addField(createContextField()); + javaFile.addMethod(createSetContextValueMethod()); + javaFile.addMethod(createSetContextValueNameMethod()); + javaFile.addMethod(createGetContextValueMethod()); + javaFile.addMethod(createGetContextValueNameMethod()); + javaFile.addMethod(createGetParentContainer()); + javaFile.addMethod(createGetParentContainerMore()); + ClassDescriptor currentClass = root.getObjectClass(); + MethodDescriptor firePropertyChange = null; + while (firePropertyChange == null && currentClass != null) { + try { + firePropertyChange = currentClass.getDeclaredMethodDescriptor("firePropertyChange", new ClassDescriptor[]{ + ClassDescriptorLoader.getClassDescriptor(String.class), + ClassDescriptorLoader.getClassDescriptor(Object.class), + ClassDescriptorLoader.getClassDescriptor(Object.class) + }); + + } + catch (NoSuchMethodException e) { + currentClass = currentClass.getSuperclass(); + } + } + + int modifiers = firePropertyChange != null ? firePropertyChange.getModifiers() : 0; + if (Modifier.isPublic(modifiers)) { + // we have all the support we need + } + if (Modifier.isProtected(modifiers)) { + // there is property change support but the firePropertyChange method is protected + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "firePropertyChange", new JavaArgument[]{ + new JavaArgument("java.lang.String", "propertyName"), new JavaArgument("java.lang.Object", "oldValue"), new JavaArgument("java.lang.Object", "newValue")}, + null, "super.firePropertyChange(propertyName, oldValue, newValue);")); + } else { + // either no support at all or firePropertyChange isn't accessible + addPropertyChangeSupport(javaFile); + } + + addEventHandlers(javaFile); + + if (ClassDescriptorLoader.getClassDescriptor(Application.class).isAssignableFrom(root.getObjectClass()) && !isMainDeclared()) { + // TODO: check for existing main method first + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC | Modifier.STATIC, "void", "main", + new JavaArgument[]{new JavaArgument("String[]", "arg")}, null, + "SwingUtilities.invokeLater(new Runnable() { public void run() { new " + className + "().setVisible(true); } });")); + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create fields ----------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + private JavaField createObjectMap() { + return new JavaField(Modifier.PROTECTED, "Map<String,Object>", "$objectMap", "new HashMap<String,Object>()"); + } + + private JavaField createContextField() { + return new JavaField(Modifier.PROTECTED, "Map<Object,String>", "$contextMap", "new HashMap<Object,String>()"); + } + + private JavaField createLoggerField(String className) { + return new JavaField(Modifier.PUBLIC + Modifier.STATIC + Modifier.FINAL, "Log", "log", "LogFactory.getLog(" + className + ".class)"); + } + + protected JavaField createJAXXObjectDescriptorField() { + try { + JAXXObjectDescriptor descriptor = compiler.getJAXXObjectDescriptor(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(buffer)); + out.writeObject(descriptor); + out.close(); + // the use of the weird deprecated constructor is deliberate -- we need to store the data as a String + // in the compiled class file, since byte array initialization is horribly inefficient compared to + // String initialization. So we store the bytes in the String, and we quite explicitly want a 1:1 + // mapping between bytes and chars, with the high byte of the char set to zero. We can then safely + // reconstitute the original byte[] at a later date. This is unquestionably an abuse of the String + // type, but if we could efficiently store a byte[] we wouldn't have to do this. + String data = new String(buffer.toByteArray(), 0); + + int sizeLimit = 65000; // constant strings are limited to 64K, and I'm not brave enough to push right up to the limit + if (data.length() < sizeLimit) { + return new JavaField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", "$jaxxObjectDescriptor", TypeManager.getJavaCode(data)); + } else { + StringBuffer initializer = new StringBuffer(); + for (int i = 0; i < data.length(); i += sizeLimit) { + String name = "$jaxxObjectDescriptor" + i; + javaFile.addField(new JavaField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", name, + TypeManager.getJavaCode(data.substring(i, Math.min(i + sizeLimit, data.length()))))); + if (initializer.length() > 0) { + initializer.append(" + "); + } + initializer.append("String.valueOf(").append(name).append(")"); + } + return new JavaField(Modifier.PRIVATE | Modifier.STATIC, "java.lang.String", "$jaxxObjectDescriptor", initializer.toString()); + } + } catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + protected JavaMethod createGetJAXXObjectDescriptorMethod() { + return new JavaMethod(Modifier.PUBLIC | Modifier.STATIC, "jaxx.runtime.JAXXObjectDescriptor", "$getJAXXObjectDescriptor", + null, null, "return jaxx.runtime.Util.decodeCompressedJAXXObjectDescriptor($jaxxObjectDescriptor);"); + } + + protected JavaMethod createGetObjectByIdMethod() { + return new JavaMethod(Modifier.PUBLIC, "java.lang.Object", "getObjectById", + new JavaArgument[]{new JavaArgument("String", "id")}, null, + "return $objectMap.get(id);"); + } + + private JavaMethod createSetContextValueMethod() { + + return new JavaMethod(Modifier.PUBLIC, "void", "setContextValue", + new JavaArgument[]{new JavaArgument("Object", "clazz")}, null, getSetContextValueMethodCode()); + } + + private JavaMethod createSetContextValueNameMethod() { + return new JavaMethod(Modifier.PUBLIC, "void", "setContextValue", + new JavaArgument[]{new JavaArgument("Object", "clazz"), new JavaArgument("String", "name")}, null, getSetContextValueNameMethodCode()); + } + + private JavaMethod createGetContextValueMethod() { + return new JavaMethod(Modifier.PUBLIC, "<T> T", "getContextValue", + new JavaArgument[]{new JavaArgument("Class<T>", "clazz")}, null, getGetContextValueMethodCode()); + } + + private JavaMethod createGetContextValueNameMethod() { + return new JavaMethod(Modifier.PUBLIC, "<T> T", "getContextValue", + new JavaArgument[]{new JavaArgument("Class<T>", "clazz"), new JavaArgument("String", "name")}, null, getGetContextValueNameMethodCode()); + } + + private JavaMethod createGetParentContainer() { + return new JavaMethod(Modifier.PUBLIC, "<O extends Container> O", "getParentContainer", + new JavaArgument[]{new JavaArgument("Class<O>", "clazz")}, null, getGetParentContenerMethodCode()); + } + + private JavaMethod createGetParentContainerMore() { + return new JavaMethod(Modifier.PUBLIC, "<O extends Container> O", "getParentContainer", + new JavaArgument[]{new JavaArgument("Object", "source"), new JavaArgument("Class<O>", "clazz")}, null, getGetParentContenerMethodMoreCode()); + } + + + protected void addPropertyChangeSupport(JavaFile javaFile) throws CompilerException { + javaFile.addField(new JavaField(0, "java.beans.PropertyChangeSupport", "$propertyChangeSupport")); + + javaFile.addMethod(new JavaMethod(0, "java.beans.PropertyChangeSupport", "$getPropertyChangeSupport", null, null, + "if ($propertyChangeSupport == null)\n" + + " $propertyChangeSupport = new PropertyChangeSupport(this);\n" + + "return $propertyChangeSupport;")); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "addPropertyChangeListener", new JavaArgument[]{ + new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, + "$getPropertyChangeSupport().addPropertyChangeListener(listener);")); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "addPropertyChangeListener", new JavaArgument[]{ + new JavaArgument("java.lang.String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, + "$getPropertyChangeSupport().addPropertyChangeListener(property, listener);")); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removePropertyChangeListener", new JavaArgument[]{ + new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, + "$getPropertyChangeSupport().removePropertyChangeListener(listener);")); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "removePropertyChangeListener", new JavaArgument[]{ + new JavaArgument("java.lang.String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener")}, null, + "$getPropertyChangeSupport().removePropertyChangeListener(property, listener);")); + + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", "firePropertyChange", new JavaArgument[]{ + new JavaArgument("java.lang.String", "propertyName"), new JavaArgument("java.lang.Object", "oldValue"), new JavaArgument("java.lang.Object", "newValue")}, + null, "$getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue);")); + } + + + protected void addEventHandlers(JavaFile javaFile) { + for (Map.Entry<String, Map<ClassDescriptor, List<EventHandler>>> e1 : compiler.getEventHandlers().entrySet()) { + // outer loop is iterating over different objects (well, technically, different Java expressions) + for (Map.Entry<ClassDescriptor, List<EventHandler>> e2 : e1.getValue().entrySet()) { + // iterate over different types of listeners for this particular object (MouseListener, ComponentListener, etc.) + for (EventHandler handler : e2.getValue()) { + // iterate over individual event handlers of a single type + String methodName = compiler.getEventHandlerMethodName(handler); + MethodDescriptor listenerMethod = handler.getListenerMethod(); + if (listenerMethod.getParameterTypes().length != 1) { + throw new CompilerException("Expected event handler " + listenerMethod.getName() + " of class " + handler.getListenerClass() + " to have exactly one argument"); + } + javaFile.addMethod(new JavaMethod(Modifier.PUBLIC, "void", methodName, + new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(listenerMethod.getParameterTypes()[0]), "event")}, null, + handler.getJavaCode())); + } + } + } + } + + protected JavaMethod createConstructor(String className) throws CompilerException { + StringBuffer code = new StringBuffer(); + String constructorParams = compiler.getRootObject().getConstructorParams(); + if (constructorParams != null) { + code.append(" super(").append(constructorParams).append(");"); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append("$initialize();"); + code.append(JAXXCompiler.getLineSeparator()); + return new JavaMethod(Modifier.PUBLIC, null, className, null, null, code.toString()); + } + + + protected JavaMethod createInitializer(String className) throws CompilerException { + StringBuffer code = new StringBuffer(); + CompiledObject root = compiler.getRootObject(); + code.append("$objectMap.put(").append(TypeManager.getJavaCode(root.getId())).append(", this);"); + code.append(JAXXCompiler.getLineSeparator()); + + Iterator<CompiledObject> i = compiler.getObjectCreationOrder(); + boolean lastWasMethodCall = false; + while (i.hasNext()) { + CompiledObject object = i.next(); + if (object != root && !object.isOverride()) { + if (compiler.inlineCreation(object)) { + if (lastWasMethodCall) { + lastWasMethodCall = false; + code.append(JAXXCompiler.getLineSeparator()); + } + code.append(getCreationCode(object)); + code.append(JAXXCompiler.getLineSeparator()); + } else { + code.append(object.getCreationMethodName()).append("();"); + code.append(JAXXCompiler.getLineSeparator()); + lastWasMethodCall = true; + } + } + } + String rootCode = root.getInitializationCode(compiler); + if (rootCode != null && rootCode.length() > 0) { + code.append(rootCode); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append(JAXXCompiler.getLineSeparator()); + if (initializer.length() > 0) { + code.append(initializer); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append("$completeSetup();"); + code.append(JAXXCompiler.getLineSeparator()); + return new JavaMethod(Modifier.PRIVATE, "void", "$initialize", null, null, code.toString()); + } + + + protected JavaMethod createCompleteSetupMethod() { + StringBuffer code = new StringBuffer(); + code.append("allComponentsCreated = true;"); + code.append(JAXXCompiler.getLineSeparator()); + for (CompiledObject object : compiler.getObjects().values()) { + //TC - 20081017 only generate the method if not empty ? + if (object.getId().startsWith("$")) { + code.append(object.getAdditionCode()).append(JAXXCompiler.getLineSeparator()); + } else { + String additionCode = object.getAdditionCode(); + if (additionCode.length() > 0) { + code.append(object.getAdditionMethodName()).append("();").append(JAXXCompiler.getLineSeparator()); + additionCode = "if (allComponentsCreated) {" + JAXXCompiler.getLineSeparator() + additionCode + "}"; + javaFile.addMethod(new JavaMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), null, null, additionCode)); + } + } + //code.append(getLineSeparator()); + } + + code.append(initDataBindings); + + if (lateInitializer.length() > 0) { + code.append(lateInitializer); + code.append(JAXXCompiler.getLineSeparator()); + } + + if (compiler.hasValidator()) { + // register validator + for (CompiledBeanValidator validator : compiler.getValidators()) { + String id = TypeManager.getJavaCode(validator.getId()); + code.append("validatorIds.add(").append(id).append(");"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("getValidator(").append(id).append(").installUIs();"); + code.append("getValidator(").append(id).append(").validate();"); + code.append(JAXXCompiler.getLineSeparator()); + } + } + return new JavaMethod(Modifier.PRIVATE, "void", "$completeSetup", null, null, code.toString()); + } + + protected JavaMethod createProcessDataBindingMethod() { + StringBuffer code = new StringBuffer(); + boolean superclassIsJAXXObject = ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(compiler.getRootObject().getObjectClass()); + // the force parameter forces the update to happen even if it is already in activeBindings. This + // is used on superclass invocations b/c by the time the call gets to the superclass, it is already + // marked active and would otherwise be skipped + if (processDataBinding.length() > 0) { + code.append(" if (!$force && $activeBindings.contains($dest)) return;"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" $activeBindings.add($dest);"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" try {"); + code.append(JAXXCompiler.getLineSeparator()); + if (processDataBinding.length() > 0) { + code.append(processDataBinding); + code.append(JAXXCompiler.getLineSeparator()); + } + if (superclassIsJAXXObject) { + code.append(" else"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" super.processDataBinding($dest, true);"); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append(" }"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" finally {"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" $activeBindings.remove($dest);"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" }"); + code.append(JAXXCompiler.getLineSeparator()); + } else if (superclassIsJAXXObject) { + code.append(" super.processDataBinding($dest, true);"); + code.append(JAXXCompiler.getLineSeparator()); + } + return new JavaMethod(Modifier.PUBLIC, "void", "processDataBinding", + new JavaArgument[]{new JavaArgument("String", "$dest"), new JavaArgument("boolean", "$force")}, + null, code.toString()); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create methods code ----------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + private String getSetContextValueMethodCode() { + return "this.setContextValue(clazz, null);"; + } + + private String getSetContextValueNameMethodCode() { + StringBuffer result = new StringBuffer(); + result.append("$contextMap.put(clazz, name);"); + return result.toString(); + } + + private String getGetContextValueMethodCode() { + return "return this.getContextValue(clazz, null);"; + } + + private String getGetContextValueNameMethodCode() { + StringBuffer result = new StringBuffer(); + result.append("for (Map.Entry<Object,String> entry : $contextMap.entrySet()) {"); + result.append("if (clazz.isAssignableFrom(entry.getKey().getClass()) && (name == null || name == entry.getValue())) {"); + result.append("return (T) entry.getKey();}}"); + result.append("return null;"); + return result.toString(); + } + + private String getGetParentContenerMethodCode() { + StringBuffer result = new StringBuffer(); + result.append("return this.getParentContainer(this, clazz);"); + return result.toString(); + } + + private String getGetParentContenerMethodMoreCode() { + StringBuffer result = new StringBuffer(); + result.append("if (!Container.class.isAssignableFrom(source.getClass())) {return null;}"); + result.append(JAXXCompiler.getLineSeparator()); + result.append("Container parent = ((Container)source).getParent();"); + result.append(JAXXCompiler.getLineSeparator()); + result.append("if (parent != null && !clazz.isAssignableFrom(parent.getClass())){parent = getParentContainer(parent, clazz);}"); + result.append(JAXXCompiler.getLineSeparator()); + result.append("return (O)parent;"); + return result.toString(); + } + + protected String getCreationCode(CompiledObject object) throws CompilerException { + if (object instanceof ScriptInitializer) { + return object.getInitializationCode(compiler); + } + StringBuffer result = new StringBuffer(); + result.append(object.getId()); + result.append(" = "); + String constructorParams = object.getConstructorParams(); + if (constructorParams != null) { + //TC - 20081017 compiledObject can have generics + result.append(" new ").append(JAXXCompiler.getCanonicalName(object)).append("(").append(constructorParams).append(");"); + //result.append("(").append(getCanonicalName(object.getObjectClass())).append(") new ").append(getCanonicalName(object.getObjectClass())).append("(").append(constructorParams).append(");"); + } else { + //TC - 20081017 compiledObject can have generics + result.append("new ").append(JAXXCompiler.getCanonicalName(object)).append("();"); + } + result.append(JAXXCompiler.getLineSeparator()); + String initCode = object.getInitializationCode(compiler); + if (initCode != null && initCode.length() > 0) { + result.append(initCode); + } + result.append("$objectMap.put(").append(TypeManager.getJavaCode(object.getId())).append(", ").append(object.getId()).append(");"); + + return result.toString(); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Delegate methods from JAXXCompiler -------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public String getOutputClassName() { + return compiler.getOutputClassName(); + } + + public File getBaseDir() { + return compiler.getBaseDir(); + } + + public CompilerOptions getOptions() { + return compiler.getOptions(); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Getter methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public JavaFile getJavaFile() { + return javaFile; + } + + public StringBuffer getInitializer() { + return initializer; + } + + public StringBuffer getLateInitializer() { + return lateInitializer; + } + + public StringBuffer getBodyCode() { + return bodyCode; + } + + public StringBuffer getInitDataBindings() { + return initDataBindings; + } + + public StringBuffer getApplyDataBinding() { + return applyDataBinding; + } + + public StringBuffer getRemoveDataBinding() { + return removeDataBinding; + } + + public StringBuffer getProcessDataBinding() { + return processDataBinding; + } + + public boolean isMainDeclared() { + return mainDeclared; + } + + /*---------------------------------------------------------------------------------*/ + /*-- Setter methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public void setMainDeclared(boolean mainDeclared) { + this.mainDeclared = mainDeclared; + } +} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,336 +0,0 @@ -package jaxx.compiler; - -import jaxx.CompilerException; -import jaxx.parser.JavaParser; -import jaxx.parser.JavaParserTreeConstants; -import jaxx.parser.SimpleNode; -import jaxx.reflect.FieldDescriptor; -import jaxx.reflect.MethodDescriptor; -import jaxx.tags.TagManager; - -import java.io.StringReader; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ScriptManager { - private JAXXCompiler compiler; - - - ScriptManager(JAXXCompiler compiler) { - this.compiler = compiler; - } - - - /** - * Strips unnecessary curly braces from around the script, generating a warning if they are found. - * - * @param script script to trim - * @return the trimed script - */ - public String trimScript(String script) { - script = script.trim(); - if (script.startsWith("{") && script.endsWith("}")) { - compiler.reportWarning("curly braces are unnecessary for script '" + script + "'"); - script = script.substring(1, script.length() - 1); - } - return script; - } - - - public void checkParse(String script) throws CompilerException { - script = trimScript(script); - JavaParser p = new JavaParser(new StringReader(script)); - while (!p.Line()) { - // ??? - } - } - - - public String preprocessScript(String script) throws CompilerException { - script = trimScript(script); - StringBuffer result = new StringBuffer(); - JavaParser p = new JavaParser(new StringReader(script)); - //JavaParser p = new JavaParser(new StringReader(script + ";")); - while (!p.Line()) { - SimpleNode node = p.popNode(); - if (node != null) { - preprocessScriptNode(node, false); - result.append(node.getText()); - } - } - return result.toString(); - } - - - /** - * Scans through a compound symbol (foo.bar.baz) to identify and compile the JAXX class it refers to, if any. - * - * @param symbol symbol to scan - */ - private void scanCompoundSymbol(String symbol) { - String[] tokens = symbol.split("\\."); - StringBuffer currentSymbol = new StringBuffer(); - for (String token : tokens) { - if (currentSymbol.length() > 0) - currentSymbol.append('.'); - currentSymbol.append(token.trim()); - - String contextClass = TagManager.resolveClassName(currentSymbol.toString(), compiler); - if (contextClass != null) { - compiler.addDependencyClass(contextClass); - } - } - } - - - private void preprocessScriptNode(SimpleNode node, boolean staticContext) throws CompilerException { - // identify static methods and initializers -- we can't fire events statically - if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION) { - if (node.getParent().getChild(0).getText().indexOf("static") != -1) { - staticContext = true; - } - } else if (node.getId() == JavaParserTreeConstants.JJTINITIALIZER) - if (node.getText().trim().startsWith("static")) { - staticContext = true; - } - - int count = node.jjtGetNumChildren(); - for (int i = 0; i < count; i++) { - preprocessScriptNode(node.getChild(i), staticContext); - } - - int id = node.getId(); - if (id == JavaParserTreeConstants.JJTNAME || id == JavaParserTreeConstants.JJTCLASSORINTERFACETYPE) { - scanCompoundSymbol(node.getText()); - } - if (!staticContext) { - String lhs = null; - if (id == JavaParserTreeConstants.JJTASSIGNMENTEXPRESSION || (id == JavaParserTreeConstants.JJTPOSTFIXEXPRESSION && node.jjtGetNumChildren() == 2)) { - lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); - } - else - if (id == JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION || id == JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION) { - lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); - } - if (lhs != null) { - FieldDescriptor[] fields = compiler.getScriptFields(); - for (FieldDescriptor field : fields) { - if (field.getName().equals(lhs)) { - //lhs.substring(lhs.lastIndexOf(".") + 1); - node.firstToken.image = "jaxx.runtime.Util.assignment(" + node.firstToken.image; - String outputClassName = compiler.getOutputClassName(); - node.lastToken.image = node.lastToken.image + ", \"" + lhs + "\", " + outputClassName + ".this)"; - } - } - } - } - } - - - /** - * Examines a Line to determine its real type. As all tokens returned by the parser are Lines, and - * they are just a tiny wrapper around the real node, this method strips off the wrapper layers to identify - * the real type of a node. - * - * @param line line to scan - * @return the line type - */ - private int getLineType(SimpleNode line) { - if (line.jjtGetNumChildren() == 1) { - SimpleNode node = line.getChild(0); - if (node.getId() == JavaParserTreeConstants.JJTBLOCKSTATEMENT) { - if (node.jjtGetNumChildren() == 1) { - return node.getChild(0).getId(); - } - } else - if (node.getId() == JavaParserTreeConstants.JJTCLASSORINTERFACEBODYDECLARATION) { - int id = node.getChild(0).getId(); - if (id == JavaParserTreeConstants.JJTMODIFIERS) { - return node.getChild(1).getId(); - } - if (id == JavaParserTreeConstants.JJTINITIALIZER) { - return id; - } - } - return node.getId(); - } - return JavaParserTreeConstants.JJTLINE; // generic value implying that it's okay to put into the initializer block - } - - - private SimpleNode findExplicitConstructorInvocation(SimpleNode parent) { - if (parent.getId() == JavaParserTreeConstants.JJTEXPLICITCONSTRUCTORINVOCATION) { - return parent; - } - - int count = parent.jjtGetNumChildren(); - for (int i = 0; i < count; i++) { - SimpleNode result = findExplicitConstructorInvocation(parent.getChild(i)); - if (result != null) { - return result; - } - } - return null; - } - - - private void processConstructor(String modifiers, SimpleNode node) { - assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; - assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; - String code = ""; - if (node.getChild(0).jjtGetNumChildren() == 0) { - compiler.reportError("The default no-argument constructor may not be redefined"); - } - else { - SimpleNode explicitConstructorInvocation = findExplicitConstructorInvocation(node); - if (explicitConstructorInvocation == null || explicitConstructorInvocation.getText().trim().startsWith("super(")) { - code = "$initialize();" + JAXXCompiler.getLineSeparator(); - if (explicitConstructorInvocation == null) { - node.getChild(1).firstToken.image = node.getChild(1).firstToken.image; - } - else { - explicitConstructorInvocation.lastToken.image += code; - } - } - } - - compiler.bodyCode.append(modifiers).append(" ").append(node.getText().substring(0,node.getText().length()-1) + code + "}"); - //compiler.bodyCode.append(";\n"); - } - - - private void scanScriptNode(SimpleNode node) throws CompilerException { - int nodeType = getLineType(node); - if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { // have to handle imports early so the preprocessing takes them into account - String text = node.getChild(0).getText().trim(); - if (text.startsWith("import")) { - text = text.substring("import".length()).trim(); - } - if (text.endsWith(";")) { - text = text.substring(0, text.length() - 1); - } - compiler.addImport(text); - } - - preprocessScriptNode(node, false); - - if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { - // do nothing, already handled above - } else if (nodeType == JavaParserTreeConstants.JJTMETHODDECLARATION) { - String returnType = null; - String name = null; - List<String> parameterTypes = new ArrayList<String>(); - //List<String> parameterNames = new ArrayList<String>(); - SimpleNode methodDeclaration = node.getChild(0).getChild(1); - assert methodDeclaration.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION; - for (int i = 0; i < methodDeclaration.jjtGetNumChildren(); i++) { - SimpleNode child = methodDeclaration.getChild(i); - int type = child.getId(); - if (type == JavaParserTreeConstants.JJTRESULTTYPE) { - String rawReturnType = child.getText().trim(); - returnType = TagManager.resolveClassName(rawReturnType, compiler); - // FIXME: this check fails for inner classes defined in this file - //if (returnType == null) - // throw new CompilerException("could not find class '" + rawReturnType + "'"); - } else - if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { - name = child.firstToken.image.trim(); - SimpleNode formalParameters = child.getChild(0); - assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; - for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) - { - SimpleNode parameter = formalParameters.getChild(j); - String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); - String parameterType = TagManager.resolveClassName(rawParameterType, compiler); - // FIXME: this check fails for inner classes defined in this file - //if (parameterType == null) - // throw new CompilerException("could not find class '" + rawParameterType + "'"); - parameterTypes.add(parameterType); - //parameterNames.add(parameter.getChild(2).getText().trim()); - } - } - } - compiler.bodyCode.append(node.getText()); - //compiler.bodyCode.append(";\n"); - compiler.addScriptMethod(new MethodDescriptor(name, Modifier.PUBLIC, returnType, parameterTypes.toArray(new String[parameterTypes.size()]), compiler.getClassLoader())); - } else - if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION || - nodeType == JavaParserTreeConstants.JJTINITIALIZER) { - String str = node.getText().trim(); - if (str.endsWith(";")) { - str+=";"; - } - compiler.bodyCode.append(str); - //compiler.bodyCode.append(";\n"); - } else - if (nodeType == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION) { - processConstructor(node.getChild(0).getChild(0).getText(), node.getChild(0).getChild(1)); - } else - if (nodeType == JavaParserTreeConstants.JJTLOCALVARIABLEDECLARATION || nodeType == JavaParserTreeConstants.JJTFIELDDECLARATION) { - // the "local" variable declarations in this expression aren't actually local -- they are flagged local - // just because there isn't an enclosing class scope visible to the parser. "Real" local variable - // declarations won't show up here, because they will be buried inside of methods. - String text = node.getText().trim(); - if (!text.endsWith(";")) { - text+=";"; - } - String declaration = text; - int equals = text.indexOf("="); - if (equals != -1) { - declaration = declaration.substring(0, equals); - } - declaration = declaration.trim(); - String[] declarationTokens = declaration.split("\\s"); - boolean isFinal = Arrays.asList(declarationTokens).contains("final"); - boolean isStatic = Arrays.asList(declarationTokens).contains("static"); - String name = declarationTokens[declarationTokens.length - 1]; - if (name.endsWith(";")) { - name = name.substring(0, name.length() - 1).trim(); - } - String className = declarationTokens[declarationTokens.length - 2]; - String type = TagManager.resolveClassName(className, compiler); - compiler.addScriptField(new FieldDescriptor(name, Modifier.PUBLIC, type, compiler.getClassLoader())); // TODO: determine the actual modifiers - if (equals != -1 && !isFinal && !isStatic) { // declare the field in the class body, but wait to actually initialize it - //compiler.bodyCode.append(text.substring(0, equals).trim()); - compiler.bodyCode.append(text.substring(0, equals).trim()).append(";"); - String initializer = text.substring(equals + 1).trim(); - if (type.endsWith("[]")) { - initializer = "new " + type + " " + initializer; - } - final String finalInitializer = name + " = " + initializer; - compiler.registerInitializer(new Runnable() { - public void run() { - compiler.registerCompiledObject(new ScriptInitializer(finalInitializer, compiler)); - } - }); - } else { - compiler.bodyCode.append(text); - } - compiler.bodyCode.append("\n"); - //compiler.bodyCode.append(";\n"); - } else { - String text = node.getText().trim(); - if (text.length() > 0) { - if (!text.endsWith(";")) { - text += ";"; - } - compiler.initializer.append(text); - //compiler.initializer.append(";\n"); - } - } - } - - - public void registerScript(String script) throws CompilerException { - JavaParser p = new JavaParser(new StringReader(script)); - //JavaParser p = new JavaParser(new StringReader(script + ";")); - while (!p.Line()) { - SimpleNode node = p.popNode(); - if (node != null) { - scanScriptNode(node); - } - } - } -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/compiler/ScriptManager.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,336 @@ +package jaxx.compiler; + +import jaxx.CompilerException; +import jaxx.parser.JavaParser; +import jaxx.parser.JavaParserTreeConstants; +import jaxx.parser.SimpleNode; +import jaxx.reflect.FieldDescriptor; +import jaxx.reflect.MethodDescriptor; +import jaxx.tags.TagManager; + +import java.io.StringReader; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ScriptManager { + private JAXXCompiler compiler; + + + ScriptManager(JAXXCompiler compiler) { + this.compiler = compiler; + } + + + /** + * Strips unnecessary curly braces from around the script, generating a warning if they are found. + * + * @param script script to trim + * @return the trimed script + */ + public String trimScript(String script) { + script = script.trim(); + if (script.startsWith("{") && script.endsWith("}")) { + compiler.reportWarning("curly braces are unnecessary for script '" + script + "'"); + script = script.substring(1, script.length() - 1); + } + return script; + } + + + public void checkParse(String script) throws CompilerException { + script = trimScript(script); + JavaParser p = new JavaParser(new StringReader(script)); + while (!p.Line()) { + // ??? + } + } + + + public String preprocessScript(String script) throws CompilerException { + script = trimScript(script); + StringBuffer result = new StringBuffer(); + JavaParser p = new JavaParser(new StringReader(script)); + //JavaParser p = new JavaParser(new StringReader(script + ";")); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + preprocessScriptNode(node, false); + result.append(node.getText()); + } + } + return result.toString(); + } + + + /** + * Scans through a compound symbol (foo.bar.baz) to identify and compile the JAXX class it refers to, if any. + * + * @param symbol symbol to scan + */ + private void scanCompoundSymbol(String symbol) { + String[] tokens = symbol.split("\\."); + StringBuffer currentSymbol = new StringBuffer(); + for (String token : tokens) { + if (currentSymbol.length() > 0) + currentSymbol.append('.'); + currentSymbol.append(token.trim()); + + String contextClass = TagManager.resolveClassName(currentSymbol.toString(), compiler); + if (contextClass != null) { + compiler.addDependencyClass(contextClass); + } + } + } + + + private void preprocessScriptNode(SimpleNode node, boolean staticContext) throws CompilerException { + // identify static methods and initializers -- we can't fire events statically + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION) { + if (node.getParent().getChild(0).getText().indexOf("static") != -1) { + staticContext = true; + } + } else if (node.getId() == JavaParserTreeConstants.JJTINITIALIZER) + if (node.getText().trim().startsWith("static")) { + staticContext = true; + } + + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + preprocessScriptNode(node.getChild(i), staticContext); + } + + int id = node.getId(); + if (id == JavaParserTreeConstants.JJTNAME || id == JavaParserTreeConstants.JJTCLASSORINTERFACETYPE) { + scanCompoundSymbol(node.getText()); + } + if (!staticContext) { + String lhs = null; + if (id == JavaParserTreeConstants.JJTASSIGNMENTEXPRESSION || (id == JavaParserTreeConstants.JJTPOSTFIXEXPRESSION && node.jjtGetNumChildren() == 2)) { + lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); + } + else + if (id == JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION || id == JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION) { + lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); + } + if (lhs != null) { + FieldDescriptor[] fields = compiler.getScriptFields(); + for (FieldDescriptor field : fields) { + if (field.getName().equals(lhs)) { + //lhs.substring(lhs.lastIndexOf(".") + 1); + node.firstToken.image = "jaxx.runtime.Util.assignment(" + node.firstToken.image; + String outputClassName = compiler.getOutputClassName(); + node.lastToken.image = node.lastToken.image + ", \"" + lhs + "\", " + outputClassName + ".this)"; + } + } + } + } + } + + + /** + * Examines a Line to determine its real type. As all tokens returned by the parser are Lines, and + * they are just a tiny wrapper around the real node, this method strips off the wrapper layers to identify + * the real type of a node. + * + * @param line line to scan + * @return the line type + */ + private int getLineType(SimpleNode line) { + if (line.jjtGetNumChildren() == 1) { + SimpleNode node = line.getChild(0); + if (node.getId() == JavaParserTreeConstants.JJTBLOCKSTATEMENT) { + if (node.jjtGetNumChildren() == 1) { + return node.getChild(0).getId(); + } + } else + if (node.getId() == JavaParserTreeConstants.JJTCLASSORINTERFACEBODYDECLARATION) { + int id = node.getChild(0).getId(); + if (id == JavaParserTreeConstants.JJTMODIFIERS) { + return node.getChild(1).getId(); + } + if (id == JavaParserTreeConstants.JJTINITIALIZER) { + return id; + } + } + return node.getId(); + } + return JavaParserTreeConstants.JJTLINE; // generic value implying that it's okay to put into the initializer block + } + + + private SimpleNode findExplicitConstructorInvocation(SimpleNode parent) { + if (parent.getId() == JavaParserTreeConstants.JJTEXPLICITCONSTRUCTORINVOCATION) { + return parent; + } + + int count = parent.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + SimpleNode result = findExplicitConstructorInvocation(parent.getChild(i)); + if (result != null) { + return result; + } + } + return null; + } + + + private void processConstructor(String modifiers, SimpleNode node) { + assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; + assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; + String code = ""; + if (node.getChild(0).jjtGetNumChildren() == 0) { + compiler.reportError("The default no-argument constructor may not be redefined"); + } + else { + SimpleNode explicitConstructorInvocation = findExplicitConstructorInvocation(node); + if (explicitConstructorInvocation == null || explicitConstructorInvocation.getText().trim().startsWith("super(")) { + code = "$initialize();" + JAXXCompiler.getLineSeparator(); + if (explicitConstructorInvocation == null) { + node.getChild(1).firstToken.image = node.getChild(1).firstToken.image; + } + else { + explicitConstructorInvocation.lastToken.image += code; + } + } + } + + compiler.appendBodyCode(modifiers + " "+ node.getText().substring(0,node.getText().length()-1) + code + "}"); + //compiler.bodyCode.append(";\n"); + } + + + private void scanScriptNode(SimpleNode node) throws CompilerException { + int nodeType = getLineType(node); + if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { // have to handle imports early so the preprocessing takes them into account + String text = node.getChild(0).getText().trim(); + if (text.startsWith("import")) { + text = text.substring("import".length()).trim(); + } + if (text.endsWith(";")) { + text = text.substring(0, text.length() - 1); + } + compiler.addImport(text); + } + + preprocessScriptNode(node, false); + + if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { + // do nothing, already handled above + } else if (nodeType == JavaParserTreeConstants.JJTMETHODDECLARATION) { + String returnType = null; + String name = null; + List<String> parameterTypes = new ArrayList<String>(); + //List<String> parameterNames = new ArrayList<String>(); + SimpleNode methodDeclaration = node.getChild(0).getChild(1); + assert methodDeclaration.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION; + for (int i = 0; i < methodDeclaration.jjtGetNumChildren(); i++) { + SimpleNode child = methodDeclaration.getChild(i); + int type = child.getId(); + if (type == JavaParserTreeConstants.JJTRESULTTYPE) { + String rawReturnType = child.getText().trim(); + returnType = TagManager.resolveClassName(rawReturnType, compiler); + // FIXME: this check fails for inner classes defined in this file + //if (returnType == null) + // throw new CompilerException("could not find class '" + rawReturnType + "'"); + } else + if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { + name = child.firstToken.image.trim(); + SimpleNode formalParameters = child.getChild(0); + assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; + for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) + { + SimpleNode parameter = formalParameters.getChild(j); + String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); + String parameterType = TagManager.resolveClassName(rawParameterType, compiler); + // FIXME: this check fails for inner classes defined in this file + //if (parameterType == null) + // throw new CompilerException("could not find class '" + rawParameterType + "'"); + parameterTypes.add(parameterType); + //parameterNames.add(parameter.getChild(2).getText().trim()); + } + } + } + compiler.appendBodyCode(node.getText()); + //compiler.bodyCode.append(";\n"); + compiler.addScriptMethod(new MethodDescriptor(name, Modifier.PUBLIC, returnType, parameterTypes.toArray(new String[parameterTypes.size()]), compiler.getClassLoader())); + } else + if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION || + nodeType == JavaParserTreeConstants.JJTINITIALIZER) { + String str = node.getText().trim(); + if (str.endsWith(";")) { + str+=";"; + } + compiler.appendBodyCode(str); + //compiler.bodyCode.append(";\n"); + } else + if (nodeType == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION) { + processConstructor(node.getChild(0).getChild(0).getText(), node.getChild(0).getChild(1)); + } else + if (nodeType == JavaParserTreeConstants.JJTLOCALVARIABLEDECLARATION || nodeType == JavaParserTreeConstants.JJTFIELDDECLARATION) { + // the "local" variable declarations in this expression aren't actually local -- they are flagged local + // just because there isn't an enclosing class scope visible to the parser. "Real" local variable + // declarations won't show up here, because they will be buried inside of methods. + String text = node.getText().trim(); + if (!text.endsWith(";")) { + text+=";"; + } + String declaration = text; + int equals = text.indexOf("="); + if (equals != -1) { + declaration = declaration.substring(0, equals); + } + declaration = declaration.trim(); + String[] declarationTokens = declaration.split("\\s"); + boolean isFinal = Arrays.asList(declarationTokens).contains("final"); + boolean isStatic = Arrays.asList(declarationTokens).contains("static"); + String name = declarationTokens[declarationTokens.length - 1]; + if (name.endsWith(";")) { + name = name.substring(0, name.length() - 1).trim(); + } + String className = declarationTokens[declarationTokens.length - 2]; + String type = TagManager.resolveClassName(className, compiler); + compiler.addScriptField(new FieldDescriptor(name, Modifier.PUBLIC, type, compiler.getClassLoader())); // TODO: determine the actual modifiers + if (equals != -1 && !isFinal && !isStatic) { // declare the field in the class body, but wait to actually initialize it + //compiler.bodyCode.append(text.substring(0, equals).trim()); + compiler.appendBodyCode(text.substring(0, equals).trim() + ";"); + String initializer = text.substring(equals + 1).trim(); + if (type.endsWith("[]")) { + initializer = "new " + type + " " + initializer; + } + final String finalInitializer = name + " = " + initializer; + compiler.registerInitializer(new Runnable() { + public void run() { + compiler.registerCompiledObject(new ScriptInitializer(finalInitializer, compiler)); + } + }); + } else { + compiler.appendBodyCode(text); + } + compiler.appendBodyCode("\n"); + //compiler.bodyCode.append(";\n"); + } else { + String text = node.getText().trim(); + if (text.length() > 0) { + if (!text.endsWith(";")) { + text += ";"; + } + compiler.appendInitializerCode(text); + //compiler.initializer.append(";\n"); + } + } + } + + + public void registerScript(String script) throws CompilerException { + JavaParser p = new JavaParser(new StringReader(script)); + //JavaParser p = new JavaParser(new StringReader(script + ";")); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + scanScriptNode(node); + } + } + } +} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/css/Stylesheet.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/css/Stylesheet.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/css/Stylesheet.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,447 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.css; - -import jaxx.CompilerException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.DataBinding; -import jaxx.compiler.DataSource; -import jaxx.compiler.JAXXCompiler; -import jaxx.parser.JavaParser; -import jaxx.parser.JavaParserTreeConstants; -import jaxx.parser.SimpleNode; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.reflect.MethodDescriptor; -import jaxx.tags.DefaultObjectHandler; -import jaxx.tags.TagManager; -import jaxx.types.TypeManager; - -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.io.Serializable; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -public class Stylesheet implements Serializable { - private Rule[] rules; - private static final long serialVersionUID = 1135373056555320671L; - - - public Stylesheet() { - rules = new Rule[0]; - } - - - public Stylesheet(Rule[] rules) { - this.rules = rules; - Arrays.sort(rules); - } - - - public Rule[] getRules() { - return rules; - } - - - public void add(Rule newRule) { - Rule[] oldRules = rules; - rules = new Rule[oldRules.length + 1]; - System.arraycopy(oldRules, 0, rules, 0, oldRules.length); - rules[rules.length - 1] = newRule; - Arrays.sort(rules); - } - - - public void add(Rule[] newRules) { - Rule[] oldRules = rules; - rules = new Rule[oldRules.length + newRules.length]; - System.arraycopy(oldRules, 0, rules, 0, oldRules.length); - System.arraycopy(newRules, 0, rules, oldRules.length, newRules.length); - Arrays.sort(rules); - } - - - public void applyTo(CompiledObject object, JAXXCompiler compiler, Stylesheet overrides) throws CompilerException { - Map<String, String> overriddenProperties; - if (overrides != null) - overriddenProperties = overrides.getApplicableProperties(object); - else - overriddenProperties = null; - - Map<String, String> properties = getApplicableProperties(object); - if (properties != null) { - if (overriddenProperties != null) - properties.keySet().removeAll(overriddenProperties.keySet()); - DefaultObjectHandler handler = TagManager.getTagHandler(object.getObjectClass()); - for (Map.Entry<String, String> e : properties.entrySet()) { - String value = e.getValue(); - if (value.equals(Rule.INLINE_ATTRIBUTE) || value.equals(Rule.DATA_BINDING)) - continue; - handler.setAttribute(object, e.getKey(), e.getValue(), false, compiler); - } - } - - Rule[] pseudoClasses = getApplicablePseudoClasses(object); - if (pseudoClasses != null) { - Map<String, Map<String, String>> combinedPseudoClasses = new LinkedHashMap<String, Map<String, String>>(); - for (Rule pseudoClass1 : pseudoClasses) { - Selector[] selectors = pseudoClass1.getSelectors(); - for (Selector selector : selectors) { - if (selector.appliesTo(object) == Selector.PSEUDOCLASS_APPLIES) { - properties = pseudoClass1.getProperties(); - String pseudoClass = selector.getPseudoClass(); - // TODO: overrides by downstream pseudoclasses are not handled - Map<String, String> combinedProperties = combinedPseudoClasses.get(pseudoClass); - if (combinedProperties == null) { - combinedProperties = new HashMap<String, String>(); - combinedPseudoClasses.put(pseudoClass, combinedProperties); - } - combinedProperties.putAll(properties); - } - } - } - - int count = 0; - for (Map.Entry<String, Map<String, String>> e : combinedPseudoClasses.entrySet()) { - applyPseudoClass(e.getKey(), e.getValue(), object, compiler, count++); - } - } - } - - - /** - * Replaces all references to the variable "object" with the actual object ID. - * - * @param code ? - * @param id ? - * @return ? - * @throws jaxx.CompilerException ? - */ - private String replaceObjectReferences(String code, String id) throws CompilerException { - JavaParser p = new JavaParser(new StringReader(code + ";")); - p.Expression(); - SimpleNode node = p.popNode(); - scanNode(node, id); - return node.getText(); - } - - - private void scanNode(SimpleNode node, String id) { - if (node.getId() == JavaParserTreeConstants.JJTNAME) { - String name = node.getText(); - if (name.equals("object") || (name.indexOf(".") != -1 && name.substring(0, name.indexOf(".")).trim().equals("object"))) - node.firstToken.image = id; - } else { - int count = node.jjtGetNumChildren(); - for (int i = 0; i < count; i++) - scanNode(node.getChild(i), id); - } - } - - - private void compilePseudoClassAdd(String pseudoClass, CompiledObject object, String propertyCode, JAXXCompiler compiler) throws CompilerException { - if (pseudoClass.equals("mouseover")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseEntered", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - } - catch (NoSuchMethodException e) { - compiler.reportError("mouseover pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.equals("mouseout")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseExited", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - compiler.initDataBindings.append("{").append(propertyCode).append("}"); - } - catch (NoSuchMethodException e) { - compiler.reportError("mouseout pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.equals("mousedown")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mousePressed", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - } - catch (NoSuchMethodException e) { - compiler.reportError("mousedown pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.equals("mouseup")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseReleased", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - compiler.initDataBindings.append("{").append(propertyCode).append("}"); - } - catch (NoSuchMethodException e) { - compiler.reportError("mouseup pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.startsWith("{")) { - pseudoClass = pseudoClass.substring(1, pseudoClass.length() - 1).trim(); - pseudoClass = replaceObjectReferences(pseudoClass, object.getJavaCode()); - String dest = object.getId() + ".style." + pseudoClass + ".add"; - String destCode = TypeManager.getJavaCode(dest); - if (compiler.processDataBinding.length() > 0) - compiler.processDataBinding.append("else "); - compiler.processDataBinding.append("if ($dest.equals(").append(destCode).append(")) { if (").append(pseudoClass).append(") { ").append(propertyCode).append("} }"); - new DataSource(dest, pseudoClass, compiler).compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + destCode + ")"); - compiler.initDataBindings.append("applyDataBinding(").append(destCode).append(");"); - } else - throw new IllegalArgumentException("unrecognized pseudoclass: " + pseudoClass); - } - - - private void compilePseudoClassRemove(String pseudoClass, CompiledObject object, String propertyCode, JAXXCompiler compiler) throws CompilerException { - if (pseudoClass.equals("mouseover")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseExited", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - } - catch (NoSuchMethodException e) { - compiler.reportError("mouseover pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.equals("mouseout")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseEntered", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - } - catch (NoSuchMethodException e) { - compiler.reportError("mouseout pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.equals("mousedown")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseReleased", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - } - catch (NoSuchMethodException e) { - compiler.reportError("mousedown pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.equals("mouseup")) { - try { - MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); - object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, - ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mousePressed", - new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), - propertyCode, compiler); - } - catch (NoSuchMethodException e) { - compiler.reportError("mouseup pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); - } - } else if (pseudoClass.startsWith("{")) { - pseudoClass = pseudoClass.substring(1, pseudoClass.length() - 1).trim(); - pseudoClass = replaceObjectReferences(pseudoClass, object.getJavaCode()); - String dest = object.getId() + ".style." + pseudoClass + ".remove"; - String destCode = TypeManager.getJavaCode(dest); - if (compiler.processDataBinding.length() > 0) - compiler.processDataBinding.append("else "); - compiler.processDataBinding.append("if ($dest.equals(").append(destCode).append(")) { if (").append(invert(pseudoClass)).append(") { ").append(propertyCode).append("} }"); - new DataSource(dest, pseudoClass, compiler).compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + destCode + ")"); - compiler.initDataBindings.append("applyDataBinding(").append(destCode).append(");"); - } else - throw new IllegalArgumentException("unrecognized pseudoclass: " + pseudoClass); - } - - - private String invert(String javaCode) { - javaCode = javaCode.trim(); - if (javaCode.startsWith("!")) - return javaCode.substring(1); - else - return "!(" + javaCode + ")"; - } - - - private String unwrap(ClassDescriptor type, String valueCode) { - if (type == ClassDescriptorLoader.getClassDescriptor(boolean.class)) - return "((java.lang.Boolean) " + valueCode + ").booleanValue()"; - else if (type == ClassDescriptorLoader.getClassDescriptor(byte.class)) - return "((java.lang.Byte) " + valueCode + ").byteValue()"; - else if (type == ClassDescriptorLoader.getClassDescriptor(short.class)) - return "((java.lang.Short) " + valueCode + ").shortValue()"; - else if (type == ClassDescriptorLoader.getClassDescriptor(int.class)) - return "((java.lang.Integer) " + valueCode + ").intValue()"; - else if (type == ClassDescriptorLoader.getClassDescriptor(long.class)) - return "((java.lang.Long) " + valueCode + ").longValue()"; - else if (type == ClassDescriptorLoader.getClassDescriptor(float.class)) - return "((java.lang.Float) " + valueCode + ").floatValue()"; - else if (type == ClassDescriptorLoader.getClassDescriptor(double.class)) - return "((java.lang.Double) " + valueCode + ").doubleValue()"; - else if (type == ClassDescriptorLoader.getClassDescriptor(char.class)) - return "((java.lang.Character) " + valueCode + ").charValue()"; - else - return valueCode; - } - - - protected void applyPseudoClass(String pseudoClass, Map<String, String> properties, - CompiledObject object, JAXXCompiler compiler, int priority) throws CompilerException { - if (pseudoClass.indexOf("[") != -1) - pseudoClass = pseudoClass.substring(0, pseudoClass.indexOf("[")); - final StringBuffer buffer = new StringBuffer(); - /*CompiledObject bufferObject = new CompiledObject(object.getId(), object.getJavaCode(), object.getObjectClass(), compiler, true) { - public void appendInitializationCode(String code) { - buffer.append(code); - } - public void registerDataBinding(String src, String property, String assignment, JAXXCompiler compiler) throws CompilerException { - buffer.append(assignment); - } - };*/ - - DefaultObjectHandler handler = TagManager.getTagHandler(object.getObjectClass()); - boolean valueDeclared = false; - for (Map.Entry<String, String> e : properties.entrySet()) { - String property = e.getKey(); - ClassDescriptor type = handler.getPropertyType(object, property, compiler); - String dataBinding = compiler.processDataBindings(e.getValue(), type); - String valueCode; - if (dataBinding != null) { - valueCode = "new jaxx.runtime.css.DataBinding(" + TypeManager.getJavaCode(object.getId() + "." + property + "." + priority) + ")"; - new DataBinding(dataBinding, object.getId() + "." + property + "." + priority, handler.getSetPropertyCode(object.getJavaCode(), - property, "(" + JAXXCompiler.getCanonicalName(type) + ") " + dataBinding, compiler), compiler).compile(false); - } else { - try { - Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; - valueCode = TypeManager.getJavaCode(TypeManager.convertFromString(e.getValue(), typeClass)); - } - catch (ClassNotFoundException ex) { - compiler.reportError("could not find class " + type.getName()); - return; - } - } - if (!valueDeclared) { - buffer.append("java.lang.Object "); - valueDeclared = true; - } - buffer.append("value = jaxx.runtime.css.Pseudoclasses.applyProperty(").append(compiler.getOutputClassName()).append(".this, ").append(object.getJavaCode()).append(", ").append(TypeManager.getJavaCode(property)).append(", ").append(valueCode).append(", jaxx.runtime.css.Pseudoclasses.wrap(").append(handler.getGetPropertyCode(object.getJavaCode(), property, compiler)).append("), ").append(priority).append(");").append(JAXXCompiler.getLineSeparator()); - buffer.append("if (!(value instanceof jaxx.runtime.css.DataBinding)) {").append(JAXXCompiler.getLineSeparator()); - String unwrappedValue = unwrap(type, "value"); - buffer.append(" ").append(handler.getSetPropertyCode(object.getJavaCode(), property, "(" + JAXXCompiler.getCanonicalName(type) + - ") " + unwrappedValue, compiler)).append(JAXXCompiler.getLineSeparator()); - buffer.append("}").append(JAXXCompiler.getLineSeparator()); - } - - if (pseudoClass.equals("focused")) { - pseudoClass = "{ object.hasFocus() }"; - } else if (pseudoClass.equals("unfocused")) { - pseudoClass = "{ !object.hasFocus() }"; - } else if (pseudoClass.equals("enabled")) { - pseudoClass = "{ object.isEnabled() }"; - } else if (pseudoClass.equals("disabled")) { - pseudoClass = "{ !object.isEnabled() }"; - } else if (pseudoClass.equals("selected")) { - pseudoClass = "{ object.isSelected() }"; - } else if (pseudoClass.equals("deselected")) { - pseudoClass = "{ !object.isSelected() }"; - } - - compilePseudoClassAdd(pseudoClass, object, buffer.toString(), compiler); - - buffer.setLength(0); - valueDeclared = false; - for (Map.Entry<String, String> e : properties.entrySet()) { - String property = e.getKey(); - ClassDescriptor type = handler.getPropertyType(object, property, compiler); - String dataBinding = compiler.processDataBindings(e.getValue(), type); - String valueCode; - if (dataBinding != null) { - valueCode = "new jaxx.runtime.css.DataBinding(" + TypeManager.getJavaCode(object.getId() + "." + property + "." + priority) + ")"; - new jaxx.compiler.DataBinding(dataBinding, object.getId() + "." + property + "." + priority, handler.getSetPropertyCode(object.getJavaCode(), - property, "(" + JAXXCompiler.getCanonicalName(type) + ") " + dataBinding, compiler), compiler).compile(false); - } else { - try { - Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; - valueCode = TypeManager.getJavaCode(TypeManager.convertFromString(e.getValue(), typeClass)); - } - catch (ClassNotFoundException ex) { - compiler.reportError("could not find class " + type.getName()); - return; - } - } - if (!valueDeclared) { - buffer.append("java.lang.Object "); - valueDeclared = true; - } - buffer.append("value = jaxx.runtime.css.Pseudoclasses.removeProperty(").append(compiler.getOutputClassName()).append(".this, ").append(object.getJavaCode()).append(", ").append(TypeManager.getJavaCode(property)).append(", ").append(valueCode).append(", jaxx.runtime.css.Pseudoclasses.wrap(").append(handler.getGetPropertyCode(object.getJavaCode(), property, compiler)).append("), ").append(priority).append(");").append(JAXXCompiler.getLineSeparator()); - buffer.append("if (!(value instanceof jaxx.runtime.css.DataBinding)) {").append(JAXXCompiler.getLineSeparator()); - String unwrappedValue = unwrap(type, "value"); - buffer.append(" ").append(handler.getSetPropertyCode(object.getJavaCode(), property, "(" + JAXXCompiler.getCanonicalName(type) + - ") " + unwrappedValue, compiler)).append(JAXXCompiler.getLineSeparator()); - buffer.append("}").append(JAXXCompiler.getLineSeparator()); - } - compilePseudoClassRemove(pseudoClass, object, buffer.toString(), compiler); - } - - - public Map<String, String> getApplicableProperties(CompiledObject object) throws CompilerException { - DefaultObjectHandler handler = TagManager.getTagHandler(object.getObjectClass()); - Map<String, String> result = null; - for (Rule rule : rules) { - int apply = rule.appliesTo(object); - if (apply == Selector.ALWAYS_APPLIES || apply == Selector.ALWAYS_APPLIES_INHERIT_ONLY) { - if (result == null) - result = new HashMap<String, String>(); - for (Map.Entry<String, String> entry : rule.getProperties().entrySet()) { - String property = entry.getKey(); - if (apply == Selector.ALWAYS_APPLIES || handler.isPropertyInherited(property)) { - result.put(property, entry.getValue()); - } - } - } - } - return result; - } - - - public Rule[] getApplicablePseudoClasses(CompiledObject object) throws CompilerException { - List<Rule> result = null; - for (Rule rule : rules) { - if (rule.appliesTo(object) == Selector.PSEUDOCLASS_APPLIES) { - if (result == null) { - result = new ArrayList<Rule>(); - } - result.add(rule); - } - } - return result != null ? result.toArray(new Rule[result.size()]) : null; - } - - @Override - public String toString() { - return "Stylesheet" + Arrays.asList(rules); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/css/Stylesheet.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/css/Stylesheet.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/css/Stylesheet.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/css/Stylesheet.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,449 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.css; + +import jaxx.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.DataBinding; +import jaxx.compiler.DataSource; +import jaxx.compiler.JAXXCompiler; +import jaxx.parser.JavaParser; +import jaxx.parser.JavaParserTreeConstants; +import jaxx.parser.SimpleNode; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.MethodDescriptor; +import jaxx.tags.DefaultObjectHandler; +import jaxx.tags.TagManager; +import jaxx.types.TypeManager; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.Serializable; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class Stylesheet implements Serializable { + private Rule[] rules; + private static final long serialVersionUID = 1135373056555320671L; + + + public Stylesheet() { + rules = new Rule[0]; + } + + + public Stylesheet(Rule[] rules) { + this.rules = rules; + Arrays.sort(rules); + } + + + public Rule[] getRules() { + return rules; + } + + + public void add(Rule newRule) { + Rule[] oldRules = rules; + rules = new Rule[oldRules.length + 1]; + System.arraycopy(oldRules, 0, rules, 0, oldRules.length); + rules[rules.length - 1] = newRule; + Arrays.sort(rules); + } + + + public void add(Rule[] newRules) { + Rule[] oldRules = rules; + rules = new Rule[oldRules.length + newRules.length]; + System.arraycopy(oldRules, 0, rules, 0, oldRules.length); + System.arraycopy(newRules, 0, rules, oldRules.length, newRules.length); + Arrays.sort(rules); + } + + + public void applyTo(CompiledObject object, JAXXCompiler compiler, Stylesheet overrides) throws CompilerException { + Map<String, String> overriddenProperties; + if (overrides != null) + overriddenProperties = overrides.getApplicableProperties(object); + else + overriddenProperties = null; + + Map<String, String> properties = getApplicableProperties(object); + if (properties != null) { + if (overriddenProperties != null) + properties.keySet().removeAll(overriddenProperties.keySet()); + DefaultObjectHandler handler = TagManager.getTagHandler(object.getObjectClass()); + for (Map.Entry<String, String> e : properties.entrySet()) { + String value = e.getValue(); + if (value.equals(Rule.INLINE_ATTRIBUTE) || value.equals(Rule.DATA_BINDING)) + continue; + handler.setAttribute(object, e.getKey(), e.getValue(), false, compiler); + } + } + + Rule[] pseudoClasses = getApplicablePseudoClasses(object); + if (pseudoClasses != null) { + Map<String, Map<String, String>> combinedPseudoClasses = new LinkedHashMap<String, Map<String, String>>(); + for (Rule pseudoClass1 : pseudoClasses) { + Selector[] selectors = pseudoClass1.getSelectors(); + for (Selector selector : selectors) { + if (selector.appliesTo(object) == Selector.PSEUDOCLASS_APPLIES) { + properties = pseudoClass1.getProperties(); + String pseudoClass = selector.getPseudoClass(); + // TODO: overrides by downstream pseudoclasses are not handled + Map<String, String> combinedProperties = combinedPseudoClasses.get(pseudoClass); + if (combinedProperties == null) { + combinedProperties = new HashMap<String, String>(); + combinedPseudoClasses.put(pseudoClass, combinedProperties); + } + combinedProperties.putAll(properties); + } + } + } + + int count = 0; + for (Map.Entry<String, Map<String, String>> e : combinedPseudoClasses.entrySet()) { + applyPseudoClass(e.getKey(), e.getValue(), object, compiler, count++); + } + } + } + + + /** + * Replaces all references to the variable "object" with the actual object ID. + * + * @param code ? + * @param id ? + * @return ? + * @throws jaxx.CompilerException ? + */ + private String replaceObjectReferences(String code, String id) throws CompilerException { + JavaParser p = new JavaParser(new StringReader(code + ";")); + p.Expression(); + SimpleNode node = p.popNode(); + scanNode(node, id); + return node.getText(); + } + + + private void scanNode(SimpleNode node, String id) { + if (node.getId() == JavaParserTreeConstants.JJTNAME) { + String name = node.getText(); + if (name.equals("object") || (name.indexOf(".") != -1 && name.substring(0, name.indexOf(".")).trim().equals("object"))) + node.firstToken.image = id; + } else { + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) + scanNode(node.getChild(i), id); + } + } + + + private void compilePseudoClassAdd(String pseudoClass, CompiledObject object, String propertyCode, JAXXCompiler compiler) throws CompilerException { + if (pseudoClass.equals("mouseover")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseEntered", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + } + catch (NoSuchMethodException e) { + compiler.reportError("mouseover pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.equals("mouseout")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseExited", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + compiler.appendInitDataBindings("{" + propertyCode + "}"); + } + catch (NoSuchMethodException e) { + compiler.reportError("mouseout pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.equals("mousedown")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mousePressed", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + } + catch (NoSuchMethodException e) { + compiler.reportError("mousedown pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.equals("mouseup")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".add", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseReleased", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + compiler.appendInitDataBindings("{" + propertyCode + "}"); + } + catch (NoSuchMethodException e) { + compiler.reportError("mouseup pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.startsWith("{")) { + pseudoClass = pseudoClass.substring(1, pseudoClass.length() - 1).trim(); + pseudoClass = replaceObjectReferences(pseudoClass, object.getJavaCode()); + String dest = object.getId() + ".style." + pseudoClass + ".add"; + String destCode = TypeManager.getJavaCode(dest); + if (compiler.haveProcessDataBinding()) { + compiler.appendProcessDataBinding("else "); + } + compiler.appendProcessDataBinding("if ($dest.equals(" + destCode + ")) { if (" + pseudoClass + ") { "+ propertyCode + "} }"); + new DataSource(dest, pseudoClass, compiler).compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + destCode + ")"); + compiler.appendInitDataBindings("applyDataBinding("+ destCode + ");"); + } else + throw new IllegalArgumentException("unrecognized pseudoclass: " + pseudoClass); + } + + + private void compilePseudoClassRemove(String pseudoClass, CompiledObject object, String propertyCode, JAXXCompiler compiler) throws CompilerException { + if (pseudoClass.equals("mouseover")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseExited", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + } + catch (NoSuchMethodException e) { + compiler.reportError("mouseover pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.equals("mouseout")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseEntered", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + } + catch (NoSuchMethodException e) { + compiler.reportError("mouseout pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.equals("mousedown")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mouseReleased", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + } + catch (NoSuchMethodException e) { + compiler.reportError("mousedown pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.equals("mouseup")) { + try { + MethodDescriptor addMouseListener = object.getObjectClass().getMethodDescriptor("addMouseListener", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseListener.class)}); + object.addEventHandler("style." + pseudoClass + ".remove", addMouseListener, + ClassDescriptorLoader.getClassDescriptor(MouseListener.class).getMethodDescriptor("mousePressed", + new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(MouseEvent.class)}), + propertyCode, compiler); + } + catch (NoSuchMethodException e) { + compiler.reportError("mouseup pseudoclass cannot be applied to object " + object.getObjectClass().getName() + " (no addMouseListener method)"); + } + } else if (pseudoClass.startsWith("{")) { + pseudoClass = pseudoClass.substring(1, pseudoClass.length() - 1).trim(); + pseudoClass = replaceObjectReferences(pseudoClass, object.getJavaCode()); + String dest = object.getId() + ".style." + pseudoClass + ".remove"; + String destCode = TypeManager.getJavaCode(dest); + if (compiler.haveProcessDataBinding()) { + compiler.appendProcessDataBinding("else "); + } + compiler.appendProcessDataBinding("if ($dest.equals(" + destCode + ")) { if (" + invert(pseudoClass) + ") { " + propertyCode + "} }"); + new DataSource(dest, pseudoClass, compiler).compile("new jaxx.runtime.DataBindingListener(" + compiler.getRootObject().getJavaCode() + ", " + destCode + ")"); + compiler.appendInitDataBindings("applyDataBinding(" + destCode + ");"); + } else + throw new IllegalArgumentException("unrecognized pseudoclass: " + pseudoClass); + } + + + private String invert(String javaCode) { + javaCode = javaCode.trim(); + if (javaCode.startsWith("!")) + return javaCode.substring(1); + else + return "!(" + javaCode + ")"; + } + + + private String unwrap(ClassDescriptor type, String valueCode) { + if (type == ClassDescriptorLoader.getClassDescriptor(boolean.class)) + return "((java.lang.Boolean) " + valueCode + ").booleanValue()"; + else if (type == ClassDescriptorLoader.getClassDescriptor(byte.class)) + return "((java.lang.Byte) " + valueCode + ").byteValue()"; + else if (type == ClassDescriptorLoader.getClassDescriptor(short.class)) + return "((java.lang.Short) " + valueCode + ").shortValue()"; + else if (type == ClassDescriptorLoader.getClassDescriptor(int.class)) + return "((java.lang.Integer) " + valueCode + ").intValue()"; + else if (type == ClassDescriptorLoader.getClassDescriptor(long.class)) + return "((java.lang.Long) " + valueCode + ").longValue()"; + else if (type == ClassDescriptorLoader.getClassDescriptor(float.class)) + return "((java.lang.Float) " + valueCode + ").floatValue()"; + else if (type == ClassDescriptorLoader.getClassDescriptor(double.class)) + return "((java.lang.Double) " + valueCode + ").doubleValue()"; + else if (type == ClassDescriptorLoader.getClassDescriptor(char.class)) + return "((java.lang.Character) " + valueCode + ").charValue()"; + else + return valueCode; + } + + + protected void applyPseudoClass(String pseudoClass, Map<String, String> properties, + CompiledObject object, JAXXCompiler compiler, int priority) throws CompilerException { + if (pseudoClass.indexOf("[") != -1) + pseudoClass = pseudoClass.substring(0, pseudoClass.indexOf("[")); + final StringBuffer buffer = new StringBuffer(); + /*CompiledObject bufferObject = new CompiledObject(object.getId(), object.getJavaCode(), object.getObjectClass(), compiler, true) { + public void appendInitializationCode(String code) { + buffer.append(code); + } + public void registerDataBinding(String src, String property, String assignment, JAXXCompiler compiler) throws CompilerException { + buffer.append(assignment); + } + };*/ + + DefaultObjectHandler handler = TagManager.getTagHandler(object.getObjectClass()); + boolean valueDeclared = false; + for (Map.Entry<String, String> e : properties.entrySet()) { + String property = e.getKey(); + ClassDescriptor type = handler.getPropertyType(object, property, compiler); + String dataBinding = compiler.processDataBindings(e.getValue(), type); + String valueCode; + if (dataBinding != null) { + valueCode = "new jaxx.runtime.css.DataBinding(" + TypeManager.getJavaCode(object.getId() + "." + property + "." + priority) + ")"; + new DataBinding(dataBinding, object.getId() + "." + property + "." + priority, handler.getSetPropertyCode(object.getJavaCode(), + property, "(" + JAXXCompiler.getCanonicalName(type) + ") " + dataBinding, compiler), compiler).compile(false); + } else { + try { + Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; + valueCode = TypeManager.getJavaCode(TypeManager.convertFromString(e.getValue(), typeClass)); + } + catch (ClassNotFoundException ex) { + compiler.reportError("could not find class " + type.getName()); + return; + } + } + if (!valueDeclared) { + buffer.append("java.lang.Object "); + valueDeclared = true; + } + buffer.append("value = jaxx.runtime.css.Pseudoclasses.applyProperty(").append(compiler.getOutputClassName()).append(".this, ").append(object.getJavaCode()).append(", ").append(TypeManager.getJavaCode(property)).append(", ").append(valueCode).append(", jaxx.runtime.css.Pseudoclasses.wrap(").append(handler.getGetPropertyCode(object.getJavaCode(), property, compiler)).append("), ").append(priority).append(");").append(JAXXCompiler.getLineSeparator()); + buffer.append("if (!(value instanceof jaxx.runtime.css.DataBinding)) {").append(JAXXCompiler.getLineSeparator()); + String unwrappedValue = unwrap(type, "value"); + buffer.append(" ").append(handler.getSetPropertyCode(object.getJavaCode(), property, "(" + JAXXCompiler.getCanonicalName(type) + + ") " + unwrappedValue, compiler)).append(JAXXCompiler.getLineSeparator()); + buffer.append("}").append(JAXXCompiler.getLineSeparator()); + } + + if (pseudoClass.equals("focused")) { + pseudoClass = "{ object.hasFocus() }"; + } else if (pseudoClass.equals("unfocused")) { + pseudoClass = "{ !object.hasFocus() }"; + } else if (pseudoClass.equals("enabled")) { + pseudoClass = "{ object.isEnabled() }"; + } else if (pseudoClass.equals("disabled")) { + pseudoClass = "{ !object.isEnabled() }"; + } else if (pseudoClass.equals("selected")) { + pseudoClass = "{ object.isSelected() }"; + } else if (pseudoClass.equals("deselected")) { + pseudoClass = "{ !object.isSelected() }"; + } + + compilePseudoClassAdd(pseudoClass, object, buffer.toString(), compiler); + + buffer.setLength(0); + valueDeclared = false; + for (Map.Entry<String, String> e : properties.entrySet()) { + String property = e.getKey(); + ClassDescriptor type = handler.getPropertyType(object, property, compiler); + String dataBinding = compiler.processDataBindings(e.getValue(), type); + String valueCode; + if (dataBinding != null) { + valueCode = "new jaxx.runtime.css.DataBinding(" + TypeManager.getJavaCode(object.getId() + "." + property + "." + priority) + ")"; + new jaxx.compiler.DataBinding(dataBinding, object.getId() + "." + property + "." + priority, handler.getSetPropertyCode(object.getJavaCode(), + property, "(" + JAXXCompiler.getCanonicalName(type) + ") " + dataBinding, compiler), compiler).compile(false); + } else { + try { + Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; + valueCode = TypeManager.getJavaCode(TypeManager.convertFromString(e.getValue(), typeClass)); + } + catch (ClassNotFoundException ex) { + compiler.reportError("could not find class " + type.getName()); + return; + } + } + if (!valueDeclared) { + buffer.append("java.lang.Object "); + valueDeclared = true; + } + buffer.append("value = jaxx.runtime.css.Pseudoclasses.removeProperty(").append(compiler.getOutputClassName()).append(".this, ").append(object.getJavaCode()).append(", ").append(TypeManager.getJavaCode(property)).append(", ").append(valueCode).append(", jaxx.runtime.css.Pseudoclasses.wrap(").append(handler.getGetPropertyCode(object.getJavaCode(), property, compiler)).append("), ").append(priority).append(");").append(JAXXCompiler.getLineSeparator()); + buffer.append("if (!(value instanceof jaxx.runtime.css.DataBinding)) {").append(JAXXCompiler.getLineSeparator()); + String unwrappedValue = unwrap(type, "value"); + buffer.append(" ").append(handler.getSetPropertyCode(object.getJavaCode(), property, "(" + JAXXCompiler.getCanonicalName(type) + + ") " + unwrappedValue, compiler)).append(JAXXCompiler.getLineSeparator()); + buffer.append("}").append(JAXXCompiler.getLineSeparator()); + } + compilePseudoClassRemove(pseudoClass, object, buffer.toString(), compiler); + } + + + public Map<String, String> getApplicableProperties(CompiledObject object) throws CompilerException { + DefaultObjectHandler handler = TagManager.getTagHandler(object.getObjectClass()); + Map<String, String> result = null; + for (Rule rule : rules) { + int apply = rule.appliesTo(object); + if (apply == Selector.ALWAYS_APPLIES || apply == Selector.ALWAYS_APPLIES_INHERIT_ONLY) { + if (result == null) + result = new HashMap<String, String>(); + for (Map.Entry<String, String> entry : rule.getProperties().entrySet()) { + String property = entry.getKey(); + if (apply == Selector.ALWAYS_APPLIES || handler.isPropertyInherited(property)) { + result.put(property, entry.getValue()); + } + } + } + } + return result; + } + + + public Rule[] getApplicablePseudoClasses(CompiledObject object) throws CompilerException { + List<Rule> result = null; + for (Rule rule : rules) { + if (rule.appliesTo(object) == Selector.PSEUDOCLASS_APPLIES) { + if (result == null) { + result = new ArrayList<Rule>(); + } + result.add(rule); + } + } + return result != null ? result.toArray(new Rule[result.size()]) : null; + } + + @Override + public String toString() { + return "Stylesheet" + Arrays.asList(rules); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/BeanValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,490 +0,0 @@ -/* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - *##%*/ - -package jaxx.runtime; - - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ValidationAwareSupport; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationManager; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.ValueStackFactory; -import com.opensymphony.xwork2.validator.ActionValidatorManager; -import com.opensymphony.xwork2.validator.DelegatingValidatorContext; -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.jxlayer.JXLayer; -import org.jdesktop.jxlayer.plaf.AbstractLayerUI; - -import javax.swing.BorderFactory; -import javax.swing.DefaultListModel; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.SwingUtilities; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * <p/> - * Permet d'ajouter facilement le support de la validation des champs d'un - * bean et de le relier a une interface graphique. - * Utilise xwork pour la validation et JXLayer pour la visualisation. - * <p/> - * <p/> - * Le mieux pour son integration dans Jaxx est de faire de la generation pour - * force la compilation du code suivant: - * <p/> - * <pre> - * myValidor.getBean().get<field>(); - * </pre> - * <p/> - * et ceci pour chaque field ajoute a la map fieldRepresentation. De cette - * facon meme si le champs field est en texte on a une verification de son - * existance a la compilation. - * <p/> - * <p/> - * La representation en tag pourrait etre - * <pre> - * <validator id="myValidator" beanClass="{Personne.class}" errorList="$list"> - * <field name="name" component="$name"/> - * <field name="firstName" component="$firstName"/> - * <field name="birthDate" component="$birthDate"/> - * </validator> - * <validator beanClass="{Personne.class}" autoField="true" errorList="$list"> - * <fieldRepresentation name="name" component="$lastName"/> - * </validator> - * </pre> - * <p/> - * dans le premier exemple on fait un mapping explicite des champs, mais on voit - * que le nom du composant graphique est le meme que celui du champs. Pour eviter - * de longue saisie, il est possible d'utiliser le flag <b>autoField</b> - * qui pour chaque champs du ayant une methode get du bean recherche un composant - * avec cet Id. Il est aussi possible de surcharge un champs explicitement - * comme ici name, dans le cas ou le composant qui porterait ce nom serait - * utilise pour autre chose. - * <p/> - * <p/> - * Il faut un handler particulier pour ce composant car les attributs - * <b>beanClass</b> et <b>autoField</b> ne sont present que dans le XML jaxx et - * servent a la generation. Il faut aussi prendre en compte les elements - * fieldRepresentation fils du tag validator. - * <p/> - * <p/> - * Voici ce que pourrait etre le code genere par jaxx - * <pre> - * // declaration du bean - * BeanValidator<beanClass> $myValidator; - * // init du bean - * protected void createMyValidator() { - * $myValidator = new BeanValidator<beanClass>(); - * // genere seulement si autoField = true - * for (Method m : beanClass.getMethod()) { - * if (m.getName().startsWith("get")) { - * String fieldName = m.getName().substring(3).toLowerCase(); - * $myValidator.setFieldRepresentation(fieldName, $objectMap.get(fieldName)); - * } - * } - * // pour chaque tag fieldRepresentation - * myValidator.setFieldRepresentation("name", $lastName); - * // si beanClass est specifie et n'est pas Object, on force l'acces au champs - * // pour validation a la compilation - * $myValidator.getBean().getName(); - * $objectMap.put("myValidator", $myValidator); - * } - * </pre> - * - * @author poussin - * @version $Revision$ - * <p/> - * Last update: $Date$ - * by : $Author$ - */ -public class BeanValidator<T> { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(BeanValidator.class); - - protected PropertyChangeSupport pcs; - - protected ValidationAwareSupport validationSupport; - protected DelegatingValidatorContext validationContext; - - protected transient ActionValidatorManager validator; - - /** indique si le bean a ete modifie depuis son arrivee */ - protected boolean changed = false; - - /** le bean a surveiller */ - protected T bean = null; - - /** l'objet qui recoit les notifications de modification du bean */ - protected Listener l = new Listener(); - - /** permet de faire le lien en un champs du bean et l'objet qui permet de l'editer */ - protected Map<String, JComponent> fieldRepresentation; - - /** Objet servant a afficher toutes les erreurs */ - protected JList errorList = null; - - /** Object servant a contenir la liste des erreurs */ - protected DefaultListModel errorListModel; - - public BeanValidator() { - pcs = new PropertyChangeSupport(this); - validationSupport = new ValidationAwareSupport(); - validationContext = new DelegatingValidatorContext(validationSupport); - fieldRepresentation = new HashMap<String, JComponent>(); - } - - /** - * Permet de modifier l'objet permettant d'afficher toutes les errors - * - * @param errorList si null arrete d'afficher les errors - */ - public void setErrorList(JList errorList) { - this.errorList = errorList; - } - - public JList getErrorList() { - return errorList; - } - - public DefaultListModel getErrorListModel() { - return errorListModel; - } - - public void setErrorListModel(DefaultListModel errorListModel) { - this.errorListModel = errorListModel; - } - - /** - * Permet d'indiquer le composant graphique responsable de l'affichage - * d'un attribut du bean - * - * @param fieldname the field name in the bean - * @param c the editor component for the field - */ - public void setFieldRepresentation(String fieldname, JComponent c) { - JComponent old = fieldRepresentation.put(fieldname, c); - setErrorRepresentation(fieldname, old, c); - } - - public void setFieldRepresentation(Map<String, JComponent> fieldRepresentation) { - for (Map.Entry<String, JComponent> e : fieldRepresentation.entrySet()) { - setFieldRepresentation(e.getKey(), e.getValue()); - } - } - - public JComponent getFieldRepresentation(String fieldname) { - return fieldRepresentation.get(fieldname); - } - - /** - * Retourne vrai si l'objet bean a ete modifie depuis le dernier - * {@link #setBean} - * - * @return <code>true</code> if bean was modify since last {@link #setBean(Object)} invocation - */ - public boolean isChanged() { - return changed; - } - - /** - * Permet de force la remise a false de l'etat de changement du bean - * - * @param changed flag to force reset of property {@link #changed} - */ - public void setChanged(boolean changed) { - boolean oldChanged = this.changed; - this.changed = changed; - pcs.firePropertyChange("changed", oldChanged, changed); - } - - public T getBean() { - return bean; - } - - public void setBean(T bean) { - T oldBean = this.bean; - if (this.bean != null) { - try { - Method method = this.bean.getClass().getMethod("removePropertyChangeListener", PropertyChangeListener.class); - method.invoke(this.bean, l); - } catch (Exception eee) { - log.info("Can't register as listener", eee); - } - } - this.bean = bean; - if (this.bean != null) { - try { - Method method = this.bean.getClass().getMethod("addPropertyChangeListener", PropertyChangeListener.class); - method.invoke(this.bean, l); - } catch (Exception eee) { - log.info("Can't register as listener", eee); - } - } - validate(); - pcs.firePropertyChange("bean", oldBean, bean); - } - - /** install layers on required components */ - public void installLayers() { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - for (String fieldname : fieldRepresentation.keySet()) { - JComponent c = fieldRepresentation.get(fieldname); - setErrorRepresentation(fieldname, null, c); - } - } - }); - - } - - protected ActionValidatorManager getValidator() { - if (validator == null) { - ConfigurationManager confManager = new ConfigurationManager(); - Configuration conf = confManager.getConfiguration(); - - ValueStackFactory vsf = conf.getContainer().getInstance( - ValueStackFactory.class); - ValueStack vs = vsf.createValueStack(); - ActionContext context = new ActionContext(vs.getContext()); - ActionContext.setContext(context); - - validator = conf.getContainer().getInstance( - ActionValidatorManager.class, "no-annotations"); - } - return validator; - } - - /** - * il faut eviter le code re-intrant (durant une validation, une autre est - * demandee). Pour cela on fait la validation dans un thread, et tant - * que la premiere validation n'est pas fini, on ne repond pas aux - * solicitations. - * Cette method est public pour permettre de force une validation par - * programmation, ce qui est utile par exemple si le bean ne supporte - * pas les {@link PropertyChangeListener} - */ - public void validate() { - // on ne valide que si il y a un bean et que le resultat de la validation - // pourra etre affiche quelque part - if (bean == null || getErrorListModel() == null || fieldRepresentation.size() == 0) { - return; - } - - try { - List<String> newErrors = new ArrayList<String>(); - - Enumeration enumeration = getErrorListModel().elements(); - while (enumeration.hasMoreElements()) { - Object o = enumeration.nextElement(); - newErrors.add((String) o); - } - for (Object o : validationContext.getFieldErrors().entrySet()) { - Map.Entry<?, ?> r = (Map.Entry<?, ?>) o; - String field = (String) r.getKey(); - List<String> errors = (List<String>) r.getValue(); - JComponent component = fieldRepresentation.get(field); - for (String error : errors) { - newErrors.remove(component.getName() + " : " + error); - } - } - - validationSupport.clearErrorsAndMessages(); - - getValidator().validate(bean, null, validationContext); - - if (log.isDebugEnabled()) { - log.debug("Action errors: " + validationContext.getActionErrors()); - log.debug("Action messages: " + validationContext.getActionMessages()); - log.debug("Field errors: " + validationContext.getFieldErrors()); - } - - log.info(this + " : " + validationContext.getFieldErrors()); - - for (Object o : validationContext.getFieldErrors().entrySet()) { - Map.Entry<?, ?> r = (Map.Entry<?, ?>) o; - String field = (String) r.getKey(); - List<String> errors = (List<String>) r.getValue(); - JComponent component = fieldRepresentation.get(field); - for (String error : errors) { - newErrors.add(component.getName() + " : " + error); - } - } - - getErrorListModel().clear(); - for (String newError : newErrors) { - getErrorListModel().addElement(newError); - } - - for (String fieldname : fieldRepresentation.keySet()) { - JComponent c = fieldRepresentation.get(fieldname); - //todo: a supprimer mais actuellemnt le layer ne se repaint pas bien, cela n'est pas normal - c.getParent().repaint(); - } - } catch (ValidationException eee) { - log.warn("Error during validation", eee); - } - } - - protected void setErrorRepresentation(String fieldname, JComponent old, JComponent c) { - if (old != c) { - if (old != null) { - // suppression du jxlayer sous l'ancien composant - Container container = old.getParent(); - if (container instanceof JXLayer) { - JXLayer<?> jx = (JXLayer<?>) container; - jx.setUI(null); - } - } - if (c != null) { - // ajout du jxlayer sous ce composant - Container container = c.getParent(); - if (container instanceof JXLayer) { - IconValidationUI ui = new IconValidationUI(fieldname, c.getName(), validationSupport); - // TranslucentValidationUI ui = new TranslucentValidationUI(fieldname, validationSupport.getFieldErrors()); - ui.setEnabled(true); - JXLayer<JComponent> jx = (JXLayer<JComponent>) container; - jx.setUI(ui); - } - } - } - } - - protected class Listener implements PropertyChangeListener { - - public void propertyChange(PropertyChangeEvent evt) { - validate(); - setChanged(true); - } - } - - - public static class TranslucentValidationUI extends AbstractLayerUI<JComponent> { - - protected String field = null; - protected Map resultValidation = null; - - public TranslucentValidationUI(String field, Map resultValidation) { - this.field = field; - this.resultValidation = resultValidation; - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<JComponent> l) { - // paints the layer as is - super.paintLayer(g2, l); - - // to be in sync with the view if the layer has a border - Insets layerInsets = l.getInsets(); - g2.translate(layerInsets.left, layerInsets.top); - - JComponent view = l.getView(); - // To prevent painting on view's border - Insets insets = view.getInsets(); - g2.clip(new Rectangle(insets.left, insets.top, - view.getWidth() - insets.left - insets.right, - view.getHeight() - insets.top - insets.bottom)); - - g2.setColor(!resultValidation.containsKey(field) ? - Color.GREEN : Color.RED); - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f)); - g2.fillRect(0, 0, l.getWidth(), l.getHeight()); - } - } - - public static class IconValidationUI extends AbstractLayerUI<JComponent> { - - // The red icon to be shown at the layer's corner - private final static BufferedImage INVALID_ICON; - - static { - int width = 7; - int height = 8; - INVALID_ICON = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g2 = (Graphics2D) INVALID_ICON.getGraphics(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - g2.setColor(Color.RED); - g2.fillRect(0, 0, width, height); - g2.setColor(Color.WHITE); - g2.drawLine(0, 0, width, height); - g2.drawLine(0, height, width, 0); - g2.dispose(); - } - - /** bean validation field */ - protected String field = null; - - /** component id */ - protected String componentId = null; - protected ValidationAwareSupport resultValidation = null; - - public IconValidationUI(String field, String componentId, ValidationAwareSupport resultValidation) { - this.field = field; - this.resultValidation = resultValidation; - this.componentId = componentId; - log.info("install " + this + "<field:" + field + ", componentId:" + componentId + ">"); - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - c.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 3)); - } - - @Override - public void uninstallUI(JComponent c) { - super.uninstallUI(c); - c.setBorder(null); - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<JComponent> l) { - super.paintLayer(g2, l); - Component component = l.getComponent(1); - // There is no need to take insets into account for this painter - if (resultValidation.getFieldErrors().containsKey(field)) { - log.info("requiredId : " + componentId + " : componentName : " + component.getName()); - g2.drawImage(INVALID_ICON, l.getWidth() - INVALID_ICON.getWidth() - 1, 0, null); - // g2.drawImage(INVALID_ICON, 0, 0, null); - } - } - } - -} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,65 +0,0 @@ -package jaxx.runtime; - -import java.awt.Container; - -/** - * todo (make javadoc :) ) - * - * @author letellier - */ -interface JAXXContext { - - /** - * Map actions objects used by JAXX interface. - * - * @param o todo - */ - public void setContextValue(Object o); - - /** - * Map actions objects used by JAXX interface and their names. - * - * @param o todo - * @param name todo - */ - public void setContextValue(Object o, String name); - - /** - * Return action object used by JAXX interface. - * This is an exemple to call a method in JAXX : - * - * <code> - * <JButton onActionPerformed='{getContextValue(Action.class).method(args[])}'/> - * </code> - * - * @param clazz todo - * @return todo - */ - public <T> T getContextValue(Class<T> clazz); - - /** - * Return action object used by JAXX interface. - * - * @param clazz todo - * @param name todo - * @return todo - */ - public <T> T getContextValue(Class<T> clazz, String name); - - /** - * Return parent's container corresponding to the Class clazz - * - * @param clazz clazz desired - * @return parent's container - */ - public <O extends Container> O getParentContainer(Class<O> clazz); - - /** - * Return parent's container corresponding to the Class clazz - * - * @param top todo - * @param clazz desired - * @return parent's container - */ - public <O extends Container> O getParentContainer(Object top, Class<O> clazz); -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java (from rev 954, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,65 @@ +package jaxx.runtime; + +import java.awt.Container; + +/** + * todo (make javadoc :) ) + * + * @author letellier + */ +public interface JAXXContext { + + /** + * Map actions objects used by JAXX interface. + * + * @param o todo + */ + public void setContextValue(Object o); + + /** + * Map actions objects used by JAXX interface and their names. + * + * @param o todo + * @param name todo + */ + public void setContextValue(Object o, String name); + + /** + * Return action object used by JAXX interface. + * This is an exemple to call a method in JAXX : + * + * <code> + * <JButton onActionPerformed='{getContextValue(Action.class).method(args[])}'/> + * </code> + * + * @param clazz todo + * @return todo + */ + public <T> T getContextValue(Class<T> clazz); + + /** + * Return action object used by JAXX interface. + * + * @param clazz todo + * @param name todo + * @return todo + */ + public <T> T getContextValue(Class<T> clazz, String name); + + /** + * Return parent's container corresponding to the Class clazz + * + * @param clazz clazz desired + * @return parent's container + */ + public <O extends Container> O getParentContainer(Class<O> clazz); + + /** + * Return parent's container corresponding to the Class clazz + * + * @param top todo + * @param clazz desired + * @return parent's container + */ + public <O extends Container> O getParentContainer(Object top, Class<O> clazz); +} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,50 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.runtime; - -/** The <code>JAXXObject</code> interface is implemented by all classes produced by the JAXX compiler. */ -public interface JAXXObject extends JAXXContext{ - /** - * Retrieves an object defined in an XML tag by its ID. - * - * @param id the id of the component to retrieve - * @return the object - */ - public Object getObjectById(String id); - - /** - * Pretrieves the dictonary of knwon objects indexed by their ids. - * @return the dictonary of objects. - */ - public java.util.Map<String,Object> get$objectMap(); - - public void applyDataBinding(String id); - - - public void removeDataBinding(String id); - - - /** - * Processes a data binding by name. Data binding names are comprised of an object ID and a property name: - * for example, the data binding in the tag <code><JLabel id='label' text='{foo.getText()}'/></code> is - * named <code>"label.text"</code>. Processing a data binding causes it to reevaluate its expression, in this - * case <code>foo.getText()</code>. - * - * @param dest the name of the data binding to run - */ - public void processDataBinding(String dest); - - - /** - * All <code>JAXXObject</code> implements are capable of broadcasting <code>PropertyChangeEvent</code>, and - * furthermore (for technical reasons) must allow code in outside packages, specifically the JAXX runtime, - * to trigger these events. - * - * @param name the name of the property which changed - * @param oldValue the old value of the property - * @param newValue the new value of the property - */ - public void firePropertyChange(String name, Object oldValue, Object newValue); -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java (from rev 955, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,51 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.runtime; + +/** The <code>JAXXObject</code> interface is implemented by all classes produced by the JAXX compiler. */ +public interface JAXXObject extends JAXXContext, JAXXValidator { + /** + * Retrieves an object defined in an XML tag by its ID. + * + * @param id the id of the component to retrieve + * @return the object + */ + public Object getObjectById(String id); + + /** + * Pretrieves the dictonary of knwon objects indexed by their ids. + * + * @return the dictonary of objects. + */ + public java.util.Map<String, Object> get$objectMap(); + + public void applyDataBinding(String id); + + + public void removeDataBinding(String id); + + + /** + * Processes a data binding by name. Data binding names are comprised of an object ID and a property name: + * for example, the data binding in the tag <code><JLabel id='label' text='{foo.getText()}'/></code> is + * named <code>"label.text"</code>. Processing a data binding causes it to reevaluate its expression, in this + * case <code>foo.getText()</code>. + * + * @param dest the name of the data binding to run + */ + public void processDataBinding(String dest); + + + /** + * All <code>JAXXObject</code> implements are capable of broadcasting <code>PropertyChangeEvent</code>, and + * furthermore (for technical reasons) must allow code in outside packages, specifically the JAXX runtime, + * to trigger these events. + * + * @param name the name of the property which changed + * @param oldValue the old value of the property + * @param newValue the new value of the property + */ + public void firePropertyChange(String name, Object oldValue, Object newValue); +} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXValidator.java (from rev 958, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXValidator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXValidator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/JAXXValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,25 @@ +package jaxx.runtime; + +import jaxx.runtime.validator.BeanValidator; + +import java.util.List; + +/** + * The contract of a validator-able object. + * + * @author chemit + */ +public interface JAXXValidator { + + /** + * Obtain a validator from his id + * + * @param validatorId validator id + * @return the associated validator, or <code>null</code> if not find + */ + BeanValidator<?> getValidator(String validatorId); + + /** @return the list of ids of all registred validator */ + List<String> getValidatorIds(); + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/Util.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,334 +0,0 @@ -package jaxx.runtime; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JComponent; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.lang.ref.WeakReference; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EventListener; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.zip.GZIPInputStream; - -public class Util { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(Util.class); - - - // Maps root objects to lists of event listeners - private static Map<Object, WeakReference<List<EventListenerDescriptor>>> eventListeners = new WeakHashMap<Object, WeakReference<List<EventListenerDescriptor>>>(); - private static Map<JAXXObject, WeakReference<List<DataBindingUpdateListener>>> dataBindingUpdateListeners = new WeakHashMap<JAXXObject, WeakReference<List<DataBindingUpdateListener>>>(); - - - private static class EventListenerDescriptor { - Class listenerClass; - String listenerMethodName; - String methodName; - Object eventListener; - } - - - /** - * Decodes the serialized representation of a JAXXObjectDescriptor. The string must be a byte-to-character mapping - * of the binary serialization data for a JAXXObjectDescriptor. See the comments in JAXXCompiler.createJAXXObjectDescriptorField - * for the rationale behind this (admittedly ugly) approach. - * - * @param descriptor descriptor to decode - * @return the dedoced descriptor - */ - public static JAXXObjectDescriptor decodeJAXXObjectDescriptor(String descriptor) { - try { - byte[] data = new byte[descriptor.length()]; - // copy low-order bytes into the array. The high-order bytes should all be zero. - System.arraycopy(descriptor.getBytes(), 0, data, 0, data.length); - //descriptor.getBytes(0, descriptor.length(), data, 0); - ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data)); - return (JAXXObjectDescriptor) in.readObject(); - } - catch (IOException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - catch (ClassNotFoundException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - } - - - public static JAXXObjectDescriptor decodeCompressedJAXXObjectDescriptor(String descriptor) { - try { - byte[] data = new byte[descriptor.length()]; - // copy low-order bytes into the array. The high-order bytes should all be zero. - System.arraycopy(descriptor.getBytes(), 0, data, 0, data.length); - //descriptor.getBytes(0, descriptor.length(), data, 0); - ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new ByteArrayInputStream(data))); - return (JAXXObjectDescriptor) in.readObject(); - } - catch (IOException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - catch (ClassNotFoundException e) { - throw new RuntimeException("Internal error: can't-happen error", e); - } - } - - - public static Object getEventListener(Class<? extends EventListener> listenerClass, final String listenerMethodName, final Object methodContainer, final String methodName) { - WeakReference<List<EventListenerDescriptor>> ref = eventListeners.get(methodContainer); - List<EventListenerDescriptor> descriptors = ref != null ? ref.get() : null; - if (descriptors == null) { - descriptors = new ArrayList<EventListenerDescriptor>(); - eventListeners.put(methodContainer, new WeakReference<List<EventListenerDescriptor>>(descriptors)); - } else { - for (EventListenerDescriptor descriptor : descriptors) { - if (listenerClass == descriptor.listenerClass && - (listenerMethodName == null ? descriptor.listenerMethodName == null : listenerMethodName.equals(descriptor.listenerMethodName)) && - methodName.equals(descriptor.methodName)) { - return descriptor.eventListener; - } - } - } - - // else we need to create a new listener - final EventListenerDescriptor descriptor = new EventListenerDescriptor(); - descriptor.listenerClass = listenerClass; - descriptor.listenerMethodName = listenerMethodName; - descriptor.methodName = methodName; - try { - final List<Method> listenerMethods = Arrays.asList(listenerClass.getMethods()); - Method listenerMethod = null; - if (listenerMethodName != null) { - for (Method listenerMethod1 : listenerMethods) { - if ((listenerMethod1).getName().equals(listenerMethodName)) { - listenerMethod = listenerMethod1; - break; - } - } - } - if (listenerMethodName != null && listenerMethod == null) { - throw new IllegalArgumentException("no method named " + listenerMethodName + " found in class " + listenerClass.getName()); - } - Class[] parameterTypes = listenerMethods.get(0).getParameterTypes(); - Class<?> methodContainerClass = methodContainer.getClass(); - final Method targetMethod = methodContainerClass.getMethod(methodName, parameterTypes); - descriptor.eventListener = Proxy.newProxyInstance(listenerClass.getClassLoader(), - new Class[]{listenerClass}, - new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) { - String methodName = method.getName(); - if ((listenerMethodName == null && listenerMethods.contains(method)) || methodName.equals(listenerMethodName)) { - try { - return targetMethod.invoke(methodContainer, args); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - if (methodName.equals("toString")) { - return toString(); - } - if (methodName.equals("equals")) { - return descriptor.eventListener == args[0]; - } - if (methodName.equals("hashCode")) { - return hashCode(); - } - return null; - } - }); - descriptors.add(descriptor); - return descriptor.eventListener; - } - catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - - public static Object getEventListener(Class<? extends EventListener> listenerClass, final Object methodContainer, final String methodName) { - return getEventListener(listenerClass, null, methodContainer, methodName); - } - - - public static DataBindingUpdateListener getDataBindingUpdateListener(JAXXObject object, String bindingName) { - WeakReference<List<DataBindingUpdateListener>> ref = dataBindingUpdateListeners.get(object); - List<DataBindingUpdateListener> listeners = ref == null ? null : ref.get(); - if (listeners == null) { - listeners = new ArrayList<DataBindingUpdateListener>(); - dataBindingUpdateListeners.put(object, new WeakReference<List<DataBindingUpdateListener>>(listeners)); - } else { - for (DataBindingUpdateListener listener : listeners) { - if (bindingName.equals(listener.getBindingName())) { - return listener; - } - } - } - DataBindingUpdateListener listener = new DataBindingUpdateListener(object, bindingName); - listeners.add(listener); - return listener; - } - - - public static void setComponentWidth(Component component, int width) { - component.setSize(width, component.getHeight()); - if (component instanceof JComponent) { - JComponent jcomponent = (JComponent) component; - jcomponent.setPreferredSize(new Dimension(width, jcomponent.getPreferredSize().height)); - jcomponent.setMinimumSize(new Dimension(width, jcomponent.getPreferredSize().height)); - if (jcomponent.isDisplayable()) { - jcomponent.revalidate(); - } - } - } - - - public static void setComponentHeight(Component component, int height) { - component.setSize(component.getWidth(), height); - if (component instanceof JComponent) { - JComponent jcomponent = (JComponent) component; - jcomponent.setPreferredSize(new Dimension(jcomponent.getPreferredSize().width, height)); - jcomponent.setMinimumSize(new Dimension(jcomponent.getPreferredSize().width, height)); - if (jcomponent.isDisplayable()) { - jcomponent.revalidate(); - } - } - } - - - public static boolean assignment(boolean value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static byte assignment(byte value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static short assignment(short value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static int assignment(int value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static long assignment(long value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static float assignment(float value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static double assignment(double value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static char assignment(char value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - - public static java.lang.Object assignment(java.lang.Object value, String name, JAXXObject src) { - src.firePropertyChange(name.trim(), null, "dummy value"); - return value; - } - - /** - * recherche les composants portant le meme nom que les champs de la classe - * clazz. Cette methode est statique pour pouvoir eventuellement l'utiliser - * dans un autre context (je pense par exemple a la generation jaxx). - * <p/> - * <p/> - * Si la recherche echoue pour quelque raison que se soit, aucune exception - * n'est leve, et la map retournee est tout simplement vide ou incomplete - * - * @param clazz la classe ou recherche les champs - * @param container le container ou rechercher les composants d'edition - * @return - */ - public static Map<String, JComponent> lookingForEditor(Class clazz, Container container) { - Map<String, JComponent> result = new HashMap<String, JComponent>(); - try { - // looking for all component with name set - Map<String, JComponent> allNamedComponent = new HashMap<String, JComponent>(); - List<Container> todo = new LinkedList<Container>(); - todo.add(container); - while (todo.size() > 0) { - for (ListIterator<Container> i = todo.listIterator(); i.hasNext();) { - Container parent = i.next(); - i.remove(); - for (Component c : parent.getComponents()) { - if (c instanceof Container) { - i.add((Container) c); - String name = c.getName(); - if (c instanceof JComponent && - name != null && !"".equals(name)) { - allNamedComponent.put(name, (JComponent) c); - } - } - } - } - } - - // looking for all properties on class - BeanInfo info = Introspector.getBeanInfo(clazz); - PropertyDescriptor[] props = info.getPropertyDescriptors(); - - // find if one properties have same name that component - for (PropertyDescriptor prop : props) { - String name = prop.getName(); - if (allNamedComponent.containsKey(name)) { - result.put(name, allNamedComponent.get(name)); - } - } - - } catch (IntrospectionException eee) { - log.warn("Can't introspect bean", eee); - } - - if (log.isDebugEnabled()) { - log.debug("Result: " + result); - } - - return result; - } - -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/Util.java (from rev 961, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/Util.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,346 @@ +package jaxx.runtime; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.JComponent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EventListener; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.zip.GZIPInputStream; + +public class Util { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(Util.class); + + + // Maps root objects to lists of event listeners + private static Map<Object, WeakReference<List<EventListenerDescriptor>>> eventListeners = new WeakHashMap<Object, WeakReference<List<EventListenerDescriptor>>>(); + private static Map<JAXXObject, WeakReference<List<DataBindingUpdateListener>>> dataBindingUpdateListeners = new WeakHashMap<JAXXObject, WeakReference<List<DataBindingUpdateListener>>>(); + + + private static class EventListenerDescriptor { + Class listenerClass; + String listenerMethodName; + String methodName; + Object eventListener; + } + + + /** + * Decodes the serialized representation of a JAXXObjectDescriptor. The string must be a byte-to-character mapping + * of the binary serialization data for a JAXXObjectDescriptor. See the comments in JAXXCompiler.createJAXXObjectDescriptorField + * for the rationale behind this (admittedly ugly) approach. + * + * @param descriptor descriptor to decode + * @return the dedoced descriptor + */ + public static JAXXObjectDescriptor decodeJAXXObjectDescriptor(String descriptor) { + try { + byte[] data = new byte[descriptor.length()]; + // copy low-order bytes into the array. The high-order bytes should all be zero. + System.arraycopy(descriptor.getBytes(), 0, data, 0, data.length); + //descriptor.getBytes(0, descriptor.length(), data, 0); + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data)); + return (JAXXObjectDescriptor) in.readObject(); + } + catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + catch (ClassNotFoundException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + } + + + public static JAXXObjectDescriptor decodeCompressedJAXXObjectDescriptor(String descriptor) { + try { + byte[] data = new byte[descriptor.length()]; + // copy low-order bytes into the array. The high-order bytes should all be zero. + System.arraycopy(descriptor.getBytes(), 0, data, 0, data.length); + //descriptor.getBytes(0, descriptor.length(), data, 0); + ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new ByteArrayInputStream(data))); + return (JAXXObjectDescriptor) in.readObject(); + } + catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + catch (ClassNotFoundException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + } + + + public static Object getEventListener(Class<? extends EventListener> listenerClass, final String listenerMethodName, final Object methodContainer, final String methodName) { + WeakReference<List<EventListenerDescriptor>> ref = eventListeners.get(methodContainer); + List<EventListenerDescriptor> descriptors = ref != null ? ref.get() : null; + if (descriptors == null) { + descriptors = new ArrayList<EventListenerDescriptor>(); + eventListeners.put(methodContainer, new WeakReference<List<EventListenerDescriptor>>(descriptors)); + } else { + for (EventListenerDescriptor descriptor : descriptors) { + if (listenerClass == descriptor.listenerClass && + (listenerMethodName == null ? descriptor.listenerMethodName == null : listenerMethodName.equals(descriptor.listenerMethodName)) && + methodName.equals(descriptor.methodName)) { + return descriptor.eventListener; + } + } + } + + // else we need to create a new listener + final EventListenerDescriptor descriptor = new EventListenerDescriptor(); + descriptor.listenerClass = listenerClass; + descriptor.listenerMethodName = listenerMethodName; + descriptor.methodName = methodName; + try { + final List<Method> listenerMethods = Arrays.asList(listenerClass.getMethods()); + Method listenerMethod = null; + if (listenerMethodName != null) { + for (Method listenerMethod1 : listenerMethods) { + if ((listenerMethod1).getName().equals(listenerMethodName)) { + listenerMethod = listenerMethod1; + break; + } + } + } + if (listenerMethodName != null && listenerMethod == null) { + throw new IllegalArgumentException("no method named " + listenerMethodName + " found in class " + listenerClass.getName()); + } + Class[] parameterTypes = listenerMethods.get(0).getParameterTypes(); + Class<?> methodContainerClass = methodContainer.getClass(); + final Method targetMethod = methodContainerClass.getMethod(methodName, parameterTypes); + descriptor.eventListener = Proxy.newProxyInstance(listenerClass.getClassLoader(), + new Class[]{listenerClass}, + new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) { + String methodName = method.getName(); + if ((listenerMethodName == null && listenerMethods.contains(method)) || methodName.equals(listenerMethodName)) { + try { + return targetMethod.invoke(methodContainer, args); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + if (methodName.equals("toString")) { + return toString(); + } + if (methodName.equals("equals")) { + return descriptor.eventListener == args[0]; + } + if (methodName.equals("hashCode")) { + return hashCode(); + } + return null; + } + }); + descriptors.add(descriptor); + return descriptor.eventListener; + } + catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + + public static Object getEventListener(Class<? extends EventListener> listenerClass, final Object methodContainer, final String methodName) { + return getEventListener(listenerClass, null, methodContainer, methodName); + } + + + public static DataBindingUpdateListener getDataBindingUpdateListener(JAXXObject object, String bindingName) { + WeakReference<List<DataBindingUpdateListener>> ref = dataBindingUpdateListeners.get(object); + List<DataBindingUpdateListener> listeners = ref == null ? null : ref.get(); + if (listeners == null) { + listeners = new ArrayList<DataBindingUpdateListener>(); + dataBindingUpdateListeners.put(object, new WeakReference<List<DataBindingUpdateListener>>(listeners)); + } else { + for (DataBindingUpdateListener listener : listeners) { + if (bindingName.equals(listener.getBindingName())) { + return listener; + } + } + } + DataBindingUpdateListener listener = new DataBindingUpdateListener(object, bindingName); + listeners.add(listener); + return listener; + } + + + public static void setComponentWidth(Component component, int width) { + component.setSize(width, component.getHeight()); + if (component instanceof JComponent) { + JComponent jcomponent = (JComponent) component; + jcomponent.setPreferredSize(new Dimension(width, jcomponent.getPreferredSize().height)); + jcomponent.setMinimumSize(new Dimension(width, jcomponent.getPreferredSize().height)); + if (jcomponent.isDisplayable()) { + jcomponent.revalidate(); + } + } + } + + + public static void setComponentHeight(Component component, int height) { + component.setSize(component.getWidth(), height); + if (component instanceof JComponent) { + JComponent jcomponent = (JComponent) component; + jcomponent.setPreferredSize(new Dimension(jcomponent.getPreferredSize().width, height)); + jcomponent.setMinimumSize(new Dimension(jcomponent.getPreferredSize().width, height)); + if (jcomponent.isDisplayable()) { + jcomponent.revalidate(); + } + } + } + + + public static boolean assignment(boolean value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static byte assignment(byte value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static short assignment(short value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static int assignment(int value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static long assignment(long value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static float assignment(float value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static double assignment(double value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static char assignment(char value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + + public static java.lang.Object assignment(java.lang.Object value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** + * recherche les composants portant le meme nom que les champs de la classe + * clazz. Cette methode est statique pour pouvoir eventuellement l'utiliser + * dans un autre context (je pense par exemple a la generation jaxx). + * <p/> + * <p/> + * Si la recherche echoue pour quelque raison que se soit, aucune exception + * n'est leve, et la map retournee est tout simplement vide ou incomplete + * + * @param clazz la classe ou recherche les champs + * @param container le container ou rechercher les composants d'edition + * @return le dictionnaire des composants recherches. + */ + public static Map<String, JComponent> lookingForEditor(Class clazz, Container container) { + Map<String, JComponent> result = new HashMap<String, JComponent>(); + try { + // looking for all component with name set + Map<String, JComponent> allNamedComponent = new HashMap<String, JComponent>(); + List<Container> todo = new LinkedList<Container>(); + todo.add(container); + while (todo.size() > 0) { + for (ListIterator<Container> i = todo.listIterator(); i.hasNext();) { + Container parent = i.next(); + i.remove(); + for (Component c : parent.getComponents()) { + if (c instanceof Container) { + i.add((Container) c); + String name = c.getName(); + if (c instanceof JComponent && + name != null && !"".equals(name)) { + allNamedComponent.put(name, (JComponent) c); + } + } + } + } + } + + // looking for all properties on class + BeanInfo info = Introspector.getBeanInfo(clazz); + PropertyDescriptor[] props = info.getPropertyDescriptors(); + + // find if one properties have same name that component + for (PropertyDescriptor prop : props) { + String name = prop.getName(); + if (allNamedComponent.containsKey(name)) { + result.put(name, allNamedComponent.get(name)); + } + } + + } catch (IntrospectionException eee) { + log.warn("Can't introspect bean", eee); + } + + if (log.isDebugEnabled()) { + log.debug("Result: " + result); + } + + return result; + } + + /** + * Box a component in a {@link org.jdesktop.jxlayer.JXLayer}. + * + * @param component the component to box + * @return the {@link org.jdesktop.jxlayer.JXLayer} boxing the component + */ + public static JXLayer boxComponentWithJxLayer(JComponent component) { + JXLayer layer = new org.jdesktop.jxlayer.JXLayer(); + layer.add(component); + return layer; + } +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator (from rev 957, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator) Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java (from rev 980, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,402 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package jaxx.runtime.validator; + + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ValidationAware; +import com.opensymphony.xwork2.ValidationAwareSupport; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.ConfigurationManager; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.ValueStackFactory; +import com.opensymphony.xwork2.validator.ActionValidatorManager; +import com.opensymphony.xwork2.validator.DelegatingValidatorContext; +import com.opensymphony.xwork2.validator.ValidationException; +import jaxx.runtime.validator.ui.AbstractBeanValidatorUI; +import jaxx.runtime.validator.ui.IconValidationUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import java.awt.Container; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * <p/> + * Permet d'ajouter facilement le support de la validation des champs d'un + * bean et de le relier a une interface graphique. + * Utilise xwork pour la validation et JXLayer pour la visualisation. + * <p/> + * <p/> + * Le mieux pour son integration dans Jaxx est de faire de la generation pour + * force la compilation du code suivant: + * <p/> + * <pre> + * myValidor.getBean().get<field>(); + * </pre> + * <p/> + * et ceci pour chaque field ajoute a la map fieldRepresentation. De cette + * facon meme si le champs field est en texte on a une verification de son + * existance a la compilation. + * <p/> + * <p/> + * La representation en tag pourrait etre + * <pre> + * <validator id="myValidator" beanClass="{Personne.class}" errorList="$list"> + * <field name="name" component="$name"/> + * <field name="firstName" component="$firstName"/> + * <field name="birthDate" component="$birthDate"/> + * </validator> + * <validator beanClass="{Personne.class}" autoField="true" errorList="$list"> + * <fieldRepresentation name="name" component="$lastName"/> + * </validator> + * </pre> + * <p/> + * dans le premier exemple on fait un mapping explicite des champs, mais on voit + * que le nom du composant graphique est le meme que celui du champs. Pour eviter + * de longue saisie, il est possible d'utiliser le flag <b>autoField</b> + * qui pour chaque champs du ayant une methode get du bean recherche un composant + * avec cet Id. Il est aussi possible de surcharge un champs explicitement + * comme ici name, dans le cas ou le composant qui porterait ce nom serait + * utilise pour autre chose. + * <p/> + * <p/> + * Il faut un handler particulier pour ce composant car les attributs + * <b>beanClass</b> et <b>autoField</b> ne sont present que dans le XML jaxx et + * servent a la generation. Il faut aussi prendre en compte les elements + * fieldRepresentation fils du tag validator. + * <p/> + * <p/> + * Voici ce que pourrait etre le code genere par jaxx + * <pre> + * // declaration du bean + * BeanValidator<beanClass> $myValidator; + * // init du bean + * protected void createMyValidator() { + * $myValidator = new BeanValidator<beanClass>(); + * // genere seulement si autoField = true + * for (Method m : beanClass.getMethod()) { + * if (m.getName().startsWith("get")) { + * String fieldName = m.getName().substring(3).toLowerCase(); + * $myValidator.setFieldRepresentation(fieldName, $objectMap.get(fieldName)); + * } + * } + * // pour chaque tag fieldRepresentation + * myValidator.setFieldRepresentation("name", $lastName); + * // si beanClass est specifie et n'est pas Object, on force l'acces au champs + * // pour validation a la compilation + * $myValidator.getBean().getName(); + * $objectMap.put("myValidator", $myValidator); + * } + * </pre> + * + * @author poussin + * @version $Revision$ + * <p/> + * Last update: $Date$ + * by : $Author$ + */ +public class BeanValidator<T> { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final Log log = LogFactory.getLog(BeanValidator.class); + + static private final Class<? extends AbstractBeanValidatorUI> DEFAULT_UI_CLASS = IconValidationUI.class; + + protected PropertyChangeSupport pcs; + + protected ValidationAwareSupport validationSupport; + protected DelegatingValidatorContext validationContext; + + protected transient ActionValidatorManager validator; + + /** indique si le bean a ete modifie depuis son arrivee */ + protected boolean changed = false; + + /** le bean a surveiller */ + protected T bean = null; + + /** l'objet qui recoit les notifications de modification du bean */ + protected Listener l = new Listener(); + + /** permet de faire le lien en un champs du bean et l'objet qui permet de l'editer */ + protected Map<String, JComponent> fieldRepresentation; + + /** Object servant a contenir la liste des erreurs */ + protected BeanValidatorErrorListModel errorListModel; + + protected Class<? extends AbstractBeanValidatorUI> uiClass; + + public BeanValidator() { + pcs = new PropertyChangeSupport(this); + validationSupport = new ValidationAwareSupport(); + validationContext = new DelegatingValidatorContext(validationSupport); + fieldRepresentation = new HashMap<String, JComponent>(); + } + + public BeanValidatorErrorListModel getErrorListModel() { + return errorListModel; + } + + public void setErrorListModel(BeanValidatorErrorListModel errorListModel) { + this.errorListModel = errorListModel; + if (errorListModel != null) { + errorListModel.registerValidator(this); + } + } + + /** + * Permet d'indiquer le composant graphique responsable de l'affichage + * d'un attribut du bean + * + * @param fieldname the field name in the bean + * @param c the editor component for the field + */ + public void setFieldRepresentation(String fieldname, JComponent c) { + fieldRepresentation.put(fieldname, c); + //todo we do not want at this moment to add something in ui, since ui is perharps not useable + //todo prefer to use the method installUIs + //JComponent old = fieldRepresentation.put(fieldname, c); + //setErrorRepresentation(fieldname, old, c, uiClass); + } + + public void setFieldRepresentation(Map<String, JComponent> fieldRepresentation) { + for (Map.Entry<String, JComponent> e : fieldRepresentation.entrySet()) { + setFieldRepresentation(e.getKey(), e.getValue()); + } + } + + public JComponent getFieldRepresentation(String fieldname) { + return fieldRepresentation.get(fieldname); + } + + /** + * Retourne vrai si l'objet bean a ete modifie depuis le dernier + * {@link #setBean} + * + * @return <code>true</code> if bean was modify since last {@link #setBean(Object)} invocation + */ + public boolean isChanged() { + return changed; + } + + /** + * Permet de force la remise a false de l'etat de changement du bean + * + * @param changed flag to force reset of property {@link #changed} + */ + public void setChanged(boolean changed) { + boolean oldChanged = this.changed; + this.changed = changed; + pcs.firePropertyChange("changed", oldChanged, changed); + } + + public T getBean() { + return bean; + } + + public void setBean(T bean) { + T oldBean = this.bean; + if (this.bean != null) { + try { + Method method = this.bean.getClass().getMethod("removePropertyChangeListener", PropertyChangeListener.class); + method.invoke(this.bean, l); + } catch (Exception eee) { + log.info("Can't register as listener", eee); + } + } + this.bean = bean; + if (this.bean != null) { + try { + Method method = this.bean.getClass().getMethod("addPropertyChangeListener", PropertyChangeListener.class); + method.invoke(this.bean, l); + } catch (Exception eee) { + log.info("Can't register as listener", eee); + } + } + validate(); + pcs.firePropertyChange("bean", oldBean, bean); + } + + public Class<? extends AbstractBeanValidatorUI> getUiClass() { + return uiClass; + } + + public void setUiClass(Class<? extends AbstractBeanValidatorUI> uiClass) { + this.uiClass = uiClass; + } + + /** @return <code>true</code> if errors are detected, <code>false</code> otherwise */ + public boolean hasErrors() { + //todo should also detecte actionErrors ? + return validationContext.hasFieldErrors(); + //return validationContext.hasFieldErrors() || validationContext.hasActionErrors(); + } + + public Map getFieldErrors() { + return validationContext.getFieldErrors(); + } + + public Collection getActionErrors() { + return validationContext.getActionErrors(); + } + + public Collection getActionMessages() { + return validationContext.getActionMessages(); + } + + /** install ui on required components */ + public void installUIs() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (uiClass == null) { + // use the default one + uiClass = DEFAULT_UI_CLASS; + } + for (String fieldname : fieldRepresentation.keySet()) { + try { + setErrorRepresentation(fieldname, null, fieldRepresentation.get(fieldname), uiClass); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + }); + + } + + /** + * il faut eviter le code re-intrant (durant une validation, une autre est + * demandee). Pour cela on fait la validation dans un thread, et tant + * que la premiere validation n'est pas fini, on ne repond pas aux + * solicitations. + * Cette method est public pour permettre de force une validation par + * programmation, ce qui est utile par exemple si le bean ne supporte + * pas les {@link PropertyChangeListener} + */ + public void validate() { + // on ne valide que si il y a un bean et que le resultat de la validation + // pourra etre affiche quelque part + if (bean == null || getErrorListModel() == null || fieldRepresentation.size() == 0) { + return; + } + + try { + + validationSupport.clearErrorsAndMessages(); + + getValidator().validate(bean, null, validationContext); + + if (log.isDebugEnabled()) { + log.debug("Action errors: " + validationContext.getActionErrors()); + log.debug("Action messages: " + validationContext.getActionMessages()); + log.debug("Field errors: " + validationContext.getFieldErrors()); + } + + log.info(this + " : " + validationContext.getFieldErrors()); + + // add errors + errorListModel.addErrors(this); + + for (String fieldname : fieldRepresentation.keySet()) { + JComponent c = fieldRepresentation.get(fieldname); + //todo: a supprimer mais actuellemnt le layer ne se repaint pas bien, cela n'est pas normal + if (c.getParent() != null) { + c.getParent().repaint(); + } + } + } catch (ValidationException eee) { + log.warn("Error during validation", eee); + } + } + + protected ActionValidatorManager getValidator() { + if (validator == null) { + ConfigurationManager confManager = new ConfigurationManager(); + Configuration conf = confManager.getConfiguration(); + + ValueStackFactory vsf = conf.getContainer().getInstance( + ValueStackFactory.class); + ValueStack vs = vsf.createValueStack(); + ActionContext context = new ActionContext(vs.getContext()); + ActionContext.setContext(context); + + validator = conf.getContainer().getInstance( + ActionValidatorManager.class, "no-annotations"); + } + return validator; + } + + protected void setErrorRepresentation(String fieldname, JComponent old, JComponent c, Class<? extends AbstractBeanValidatorUI> uiClass) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { + if (old != c) { + if (old != null) { + // suppression du jxlayer sous l'ancien composant + Container container = old.getParent(); + if (container instanceof JXLayer) { + JXLayer<?> jx = (JXLayer<?>) container; + jx.setUI(null); + } + } + if (c != null) { + // ajout du jxlayer sous ce composant + Container container = c.getParent(); + if (container instanceof JXLayer) { + Constructor<? extends AbstractBeanValidatorUI> cons = uiClass.getConstructor(String.class, String.class, ValidationAware.class); + AbstractBeanValidatorUI ui = cons.newInstance(fieldname, c.getName(), validationSupport); + ui.setEnabled(true); + JXLayer<JComponent> jx = (JXLayer<JComponent>) container; + jx.setUI(ui); + } + } + } + } + + protected class Listener implements PropertyChangeListener { + + public void propertyChange(PropertyChangeEvent evt) { + // only validate if the property has really changed... + Object oldValue = evt.getOldValue(); + Object newValue = evt.getNewValue(); + if (oldValue == null && newValue == null) { + return; + } + if ((oldValue != null && oldValue.equals(newValue)) || (newValue != null && newValue.equals(oldValue))) { + return; + } + if (log.isDebugEnabled()) { + log.debug("launch validation from event [name:" + evt.getPropertyName() + " <old:" + oldValue + ", new:" + newValue + ">]"); + } + validate(); + setChanged(true); + } + } + +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java (from rev 958, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,83 @@ +package jaxx.runtime.validator; + +import org.codelutin.i18n.I18n; + +import javax.swing.JComponent; + +/** + * The model of an error. + * + * @author chemit + */ +public class BeanValidatorError<T> { + + protected BeanValidator<T> validator; + + protected String fieldName; + + protected String error; + + protected JComponent component; + + public BeanValidator<T> getValidator() { + return validator; + } + + public String getFieldName() { + return fieldName; + } + + public String getError() { + return error; + } + + public JComponent getComponent() { + return component; + } + + public void setValidator(BeanValidator<T> validator) { + this.validator = validator; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public void setError(String error) { + this.error = error; + } + + public void setComponent(JComponent component) { + this.component = component; + } + + @Override + public String toString() { + return component.getName() + " : " + I18n._(error); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof BeanValidatorError)) { + return false; + } + + BeanValidatorError that = (BeanValidatorError) o; + + return component.equals(that.component) && error.equals(that.error) && fieldName.equals(that.fieldName) && validator.equals(that.validator); + + } + + @Override + public int hashCode() { + int result; + result = validator.hashCode(); + result = 31 * result + fieldName.hashCode(); + result = 31 * result + error.hashCode(); + result = 31 * result + component.hashCode(); + return result; + } +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java (from rev 958, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,140 @@ +package jaxx.runtime.validator; + +import javax.swing.DefaultListModel; +import javax.swing.JComponent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; + +/** + * The model of the list of errors + * + * @author chemit + */ +public class BeanValidatorErrorListModel extends DefaultListModel { + private static final long serialVersionUID = 1L; + + /** list of registred validators */ + protected transient List<BeanValidator<?>> validators; + + /** comporatorof errors */ + protected transient Comparator<BeanValidatorError> comparator; + + public BeanValidatorErrorListModel() { + validators = new ArrayList<BeanValidator<?>>(); + } + + public void registerValidator(BeanValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException("the validator " + validator + " is already registred in " + this); + } + validators.add(validator); + } + + public <T> void addErrors(BeanValidator<T> validator) { + if (!validators.contains(validator)) { + throw new IllegalArgumentException("the validator " + validator + " is not registred in " + this); + } + + // new errors for the given validator + List<BeanValidatorError> newErrors = new ArrayList<BeanValidatorError>(); + // old errors for the given validator + List<BeanValidatorError> oldErrors = new ArrayList<BeanValidatorError>(); + // old errors for other validators + List<BeanValidatorError> oldOtherErrors = new ArrayList<BeanValidatorError>(); + + // split old errors from other validators + splitOldErrors(validator, oldErrors, oldOtherErrors); + + // fill new errors + fillNewErrors(validator, newErrors); + + // check if something has changed for the given validator + if (hasChanged(oldErrors, newErrors)) { + + // reinject other errors + newErrors.addAll(oldOtherErrors); + + // sort errors + Collections.sort(newErrors, getComparator()); + + // clean errors in model + clear(); + + // reinject in list model, all the errors + for (BeanValidatorError error : newErrors) { + addElement(error); + } + + // notify thaht the model has changed + fireContentsChanged(this, 0, getSize() - 1); + } + } + + protected boolean hasChanged(List<BeanValidatorError> oldErrors, List<BeanValidatorError> newErrors) { + if (oldErrors.size() != newErrors.size()) { + return true; + } + for (BeanValidatorError oldError : oldErrors) { + if (!newErrors.contains(oldError)) { + return true; + } + } + return false; + } + + protected <T> void fillNewErrors(BeanValidator<T> validator, List<BeanValidatorError> newErrors) { + if (validator.hasErrors()) { + // inject this validator errors + for (Object o : validator.getFieldErrors().entrySet()) { + Map.Entry<?, ?> r = (Map.Entry<?, ?>) o; + BeanValidatorError<T> error; + String field = (String) r.getKey(); + + JComponent component = validator.getFieldRepresentation(field); + if (component!=null) { + for (Object errorString : (List<?>) r.getValue()) { + String error1 = (String) errorString; + error = new BeanValidatorError<T>(); + error.setComponent(component); + error.setValidator(validator); + error.setError(error1); + error.setFieldName(field); + newErrors.add(error); + } + } + } + //todo should also do actionErrors + } + } + + protected <T> void splitOldErrors(BeanValidator<T> validator, List<BeanValidatorError> oldErrors, List<BeanValidatorError> oldOtherErrors) { + Enumeration enumeration = elements(); + + while (enumeration.hasMoreElements()) { + Object o = enumeration.nextElement(); + BeanValidatorError<?> error = (BeanValidatorError) o; + if (!error.getValidator().equals(validator)) { + // error from another validator, keep it + oldOtherErrors.add(error); + } else { + oldErrors.add(error); + } + } + } + + protected Comparator<BeanValidatorError> getComparator() { + if (comparator == null) { + comparator = new Comparator<BeanValidatorError>() { + public int compare(BeanValidatorError o1, BeanValidatorError o2) { + return o1.toString().compareTo(o2.toString()); + } + }; + } + return comparator; + } + +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingDirectoryFieldValidator.java (from rev 981, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingDirectoryFieldValidator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingDirectoryFieldValidator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingDirectoryFieldValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,72 @@ +package jaxx.runtime.validator; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * ExistingDirectoryFieldValidator checks that a File field exists and is a directory. + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="existingDirectory"> + * <param name="fieldName">tmp</param> + * <message>tmp is not an existing directory</message> + * </validator> + * <p/> + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="existingDirectory"> + * <message>tmp is not an existing directory</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author chemit + */ +public class ExistingDirectoryFieldValidator extends FieldValidatorSupport { + + public void validate(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = this.getFieldValue(fieldName, object); + if (value==null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (!(f.isDirectory() && f.exists())) { + // f is not a directory, nor exists + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "existingDirectory"; + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingFileFieldValidator.java (from rev 981, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingFileFieldValidator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingFileFieldValidator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ExistingFileFieldValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,72 @@ +package jaxx.runtime.validator; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * ExistingFileFieldValidator checks that a File field exists. * + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="fileExisting"> + * <param name="fieldName">tmp</param> + * <message>tmp is not an existing file</message> + * </validator> + * <p/> + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="fileExisting"> + * <message>tmp is not an existing file</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author chemit + */ +public class ExistingFileFieldValidator extends FieldValidatorSupport { + + public void validate(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = this.getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (!(f.isFile() && f.exists())) { + // f is not a file nor exists + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "existingFile"; + } +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingDirectoryFieldValidator.java (from rev 981, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingDirectoryFieldValidator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingDirectoryFieldValidator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingDirectoryFieldValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,72 @@ +package jaxx.runtime.validator; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * NotExistingDirectoryFieldValidator checks that a File field as a directory does not exist. * + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="notExistingDirectory"> + * <param name="fieldName">tmp</param> + * <message>tmp is an existing directory</message> + * </validator> + * <p/> + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="notExistingDirectory"> + * <message>tmp is an existing directory</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author chemit + */ +public class NotExistingDirectoryFieldValidator extends FieldValidatorSupport { + + @Override + public void validate(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = this.getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (f.exists() || f.isFile()) { + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "notExistingDirectory"; + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingFileFieldValidator.java (from rev 981, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingFileFieldValidator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingFileFieldValidator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/NotExistingFileFieldValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,73 @@ +package jaxx.runtime.validator; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * NotExistingFileFieldValidator checks that a File field as a file does not exist. * + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="notExistingFile"> + * <param name="fieldName">tmp</param> + * <message>tmp is an existing file</message> + * </validator> + * <p/> + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="notExistingFile"> + * <message>tmp is an existing file</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author chemit + */ +public class NotExistingFileFieldValidator extends FieldValidatorSupport { + + @Override + public void validate(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = this.getFieldValue(fieldName, object); + if (value==null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (f.exists() || f.isDirectory()) { + // f is not a file and exist + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "notExistingFile"; + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/RequiredFileFieldValidator.java (from rev 983, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/RequiredFileFieldValidator.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/RequiredFileFieldValidator.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/RequiredFileFieldValidator.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,72 @@ +package jaxx.runtime.validator; + +import com.opensymphony.xwork2.validator.ValidationException; +import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; + +import java.io.File; + +/** + * <!-- START SNIPPET: javadoc --> + * RequiredFileFieldValidator checks that a File field is not null nor have an empty filename. + * <!-- END SNIPPET: javadoc --> + * <p/> + * <p/> + * <!-- START SNIPPET: parameters --> + * <ul> + * <li>fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required</li> + * </ul> + * <!-- END SNIPPET: parameters --> + * <p/> + * <p/> + * <pre> + * <!-- START SNIPPET: examples --> + * <validators> + * <!-- Plain-Validator Syntax --> + * <validator type="requiredFile"> + * <param name="fieldName">tmp</param> + * <message>tmp is required</message> + * </validator> + * <p/> + * <!-- Field-Validator Syntax --> + * <field name="tmp"> + * <field-validator type="requiredFile"> + * <message>tmp is required</message> + * </field-validator> + * </field> + * </validators> + * <!-- END SNIPPET: examples --> + * </pre> + * + * @author chemit + */ +public class RequiredFileFieldValidator extends FieldValidatorSupport { + + public void validate(Object object) throws ValidationException { + String fieldName = getFieldName(); + Object value = this.getFieldValue(fieldName, object); + if (value == null) { + // no value defined + addFieldError(fieldName, object); + return; + } + File f; + if (value instanceof File) { + f = (File) value; + } else if (value instanceof String) { + f = new File((String) value); + } else { + addFieldError(fieldName, object); + return; + } + + if (f.getPath().trim().isEmpty()) { + // f is not a directory nor exists + addFieldError(fieldName, object); + } + } + + @Override + public String getValidatorType() { + return "requiredFile"; + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui (from rev 958, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ui) Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java 2008-10-17 20:55:15 UTC (rev 958) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,33 +0,0 @@ -package jaxx.runtime.validator.ui; - -import com.opensymphony.xwork2.ValidationAware; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.jxlayer.plaf.AbstractLayerUI; - -/** - * Abstract renderer - * - * @author chemit - */ -public abstract class AbstractBeanValidatorUI extends AbstractLayerUI<javax.swing.JComponent> { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - protected static Log log = LogFactory.getLog(AbstractBeanValidatorUI.class); - - /** bean field */ - protected String field; - - /** component id */ - protected String componentId; - - /** validation context */ - protected ValidationAware validationContext; - - public AbstractBeanValidatorUI(String field,String componentId, ValidationAware validationContext) { - this.componentId = componentId; - this.field = field; - this.validationContext = validationContext; - log.info("install " + this + "<field:" + field + ", componentId:" + componentId + ">"); - } -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java (from rev 960, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/AbstractBeanValidatorUI.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,33 @@ +package jaxx.runtime.validator.ui; + +import com.opensymphony.xwork2.ValidationAware; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.plaf.AbstractLayerUI; + +/** + * Abstract renderer + * + * @author chemit + */ +public abstract class AbstractBeanValidatorUI extends AbstractLayerUI<javax.swing.JComponent> { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + protected static Log log = LogFactory.getLog(AbstractBeanValidatorUI.class); + + /** bean field */ + protected String field; + + /** component id */ + protected String componentId; + + /** validation context */ + protected ValidationAware validationContext; + + public AbstractBeanValidatorUI(String field, String componentId, ValidationAware validationContext) { + this.componentId = componentId; + this.field = field; + this.validationContext = validationContext; + log.info("install " + this + "<field:" + field + ", componentId:" + componentId + ">"); + } +} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java 2008-10-17 20:55:15 UTC (rev 958) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,42 +0,0 @@ -package jaxx.runtime.validator.ui; - -import com.opensymphony.xwork2.ValidationAware; -import org.jdesktop.jxlayer.JXLayer; - -import javax.swing.JComponent; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Rectangle; - -/** @author chemit */ -public class TranslucentValidationUI extends AbstractBeanValidatorUI { - - public TranslucentValidationUI(String field, String componentId, ValidationAware validationContext) { - super(componentId, field, validationContext); - - } - - @Override - protected void paintLayer(Graphics2D g2, JXLayer<JComponent> l) { - // paints the layer as is - super.paintLayer(g2, l); - - // to be in sync with the view if the layer has a border - Insets layerInsets = l.getInsets(); - g2.translate(layerInsets.left, layerInsets.top); - - JComponent view = l.getView(); - // To prevent painting on view's border - Insets insets = view.getInsets(); - g2.clip(new Rectangle(insets.left, insets.top, - view.getWidth() - insets.left - insets.right, - view.getHeight() - insets.top - insets.bottom)); - - g2.setColor(!validationContext.getFieldErrors().containsKey(field) ? - Color.GREEN : Color.RED); - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f)); - g2.fillRect(0, 0, l.getWidth(), l.getHeight()); - } -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java (from rev 960, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/runtime/validator/ui/TranslucentValidationUI.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,41 @@ +package jaxx.runtime.validator.ui; + +import com.opensymphony.xwork2.ValidationAware; +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.JComponent; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; + +/** @author chemit */ +public class TranslucentValidationUI extends AbstractBeanValidatorUI { + + public TranslucentValidationUI(String field, String componentId, ValidationAware validationContext) { + super(field, componentId, validationContext); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<JComponent> l) { + // paints the layer as is + super.paintLayer(g2, l); + + // to be in sync with the view if the layer has a border + Insets layerInsets = l.getInsets(); + g2.translate(layerInsets.left, layerInsets.top); + + JComponent view = l.getView(); + // To prevent painting on view's border + Insets insets = view.getInsets(); + g2.clip(new Rectangle(insets.left, insets.top, + view.getWidth() - insets.left - insets.right, + view.getHeight() - insets.top - insets.bottom)); + + g2.setColor(!validationContext.getFieldErrors().containsKey(field) ? + Color.GREEN : Color.RED); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f)); + g2.fillRect(0, 0, l.getWidth(), l.getHeight()); + } +} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,275 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags; - -import jaxx.CompilerException; -import jaxx.UnsupportedAttributeException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.I18nHelper; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.awt.Component; -import java.awt.Container; -import java.awt.event.ComponentListener; -import java.awt.event.ContainerListener; -import java.awt.event.FocusListener; -import java.beans.IntrospectionException; -import java.io.IOException; -import java.lang.reflect.Field; - -public class DefaultComponentHandler extends DefaultObjectHandler { - /** log */ - protected static final Log log = LogFactory.getLog(DefaultComponentHandler.class); - - private String containerDelegate; - - public DefaultComponentHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, Component.class); - /*if (!ClassDescriptorLoader.getClassDescriptor(Component.class).isAssignableFrom(beanClass)) { - throw new IllegalArgumentException(getClass().getName() + " does not support the class " + beanClass.getName()); - }*/ - } - - @Override - protected void init() throws IntrospectionException { - if (jaxxBeanInfo == null) { - super.init(); - - containerDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("containerDelegate"); - if (containerDelegate == null && ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass().getSuperclass())) { - DefaultObjectHandler tagHandler = TagManager.getTagHandler(getBeanClass().getSuperclass()); - if (tagHandler instanceof DefaultComponentHandler) { - containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); - } else { - /*tagHandler = TagManager.getTagHandler(getBeanClass()); - if (tagHandler instanceof DefaultComponentHandler) { - containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); - } else {*/ - log.warn("could not find componentHandler for " + getBeanClass()); - //} - } - } - } - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("hasFocus", FocusListener.class); - addProxyEventInfo("isVisible", ComponentListener.class); - addProxyEventInfo("getBounds", ComponentListener.class); - addProxyEventInfo("getLocation", ComponentListener.class); - addProxyEventInfo("getLocationOnScreen", ComponentListener.class); - addProxyEventInfo("getSize", ComponentListener.class); - addProxyEventInfo("getX", ComponentListener.class); - addProxyEventInfo("getY", ComponentListener.class); - addProxyEventInfo("getWidth", ComponentListener.class); - addProxyEventInfo("getHeight", ComponentListener.class); - if (ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass())) { - addProxyEventInfo("getComponentCount", ContainerListener.class); - } - } - - @Override - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - setAttribute(object, "name", object.getId(), false, compiler); - openComponent(object, tag, compiler); - } - - @Override - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - super.compileFirstPass(tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - super.compileSecondPass(tag, compiler); - closeComponent(compiler.getOpenComponent(), tag, compiler); - } - - - protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - String constraints = tag.getAttribute("constraints"); - if (constraints != null && constraints.length() > 0) { - compiler.openComponent(object, constraints); - } else { - compiler.openComponent(object); - } - } - - protected void closeComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - compiler.closeComponent(object); - } - - @Override - public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { - return property.equals("font") || property.startsWith("font-") || property.equals("foreground") || property.equals("enabled"); - } - - @Override - public ClassDescriptor getPropertyType(CompiledObject object, String propertyName, JAXXCompiler compiler) throws CompilerException { - if (propertyName.equals("x") || propertyName.equals("y") || propertyName.equals("width") || propertyName.equals("height") || - "font-size".equals(propertyName)) - return ClassDescriptorLoader.getClassDescriptor(Integer.class); - if (propertyName.equals("font-face") || propertyName.equals("font-style") || propertyName.equals("font-weight")) { - return ClassDescriptorLoader.getClassDescriptor(String.class); - } - return super.getPropertyType(object, propertyName, compiler); - } - - @Override - public String getGetPropertyCode(String id, String name, JAXXCompiler compiler) throws CompilerException { - if (name.equals("font-face")) { - return id + ".getFont().getFontName()"; - } - if (name.equals("font-size")) { - return id + ".getFont().getSize()"; - } - if (name.equals("font-weight")) { - return "(" + id + ".getFont().getStyle() & Font.BOLD) != 0 ? \"bold\" : \"normal\""; - } - if (name.equals("font-style")) { - return "(" + id + ".getFont().getStyle() & Font.ITALIC) != 0 ? \"italic\" : \"normal\""; - } - return super.getGetPropertyCode(id, name, compiler); - } - - @Override - public String getSetPropertyCode(String id, String name, String valueCode, JAXXCompiler compiler) throws CompilerException { - if (name.equals("x")) { - return id + ".setLocation(" + valueCode + ", " + id + ".getY());"; - } - if (name.equals("y")) { - return id + ".setLocation(" + id + ".getX(), " + valueCode + ");"; - } - if (name.equals("width")) { // need to optimize case when both width and height are being assigned - return "jaxx.runtime.Util.setComponentWidth(" + id + "," + valueCode + ");\n"; - } - if (name.equals("height")) { - return "jaxx.runtime.Util.setComponentHeight(" + id + "," + valueCode + ");\n"; - } - if (name.equals("font-face")) { - return "if (" + id + ".getFont() != null) " + id + ".setFont(new Font(" + valueCode + ", " + id + ".getFont().getStyle(), " + id + ".getFont().getSize()));"; - } - if (name.equals("font-size")) { - return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont((float) " + valueCode + "));"; - } - if (name.equals("font-weight")) { - if (valueCode.equals("\"bold\"")) { - return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.BOLD));"; - } - if (valueCode.equals("\"normal\"")) { - return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.BOLD));"; - } - if (!valueCode.startsWith("\"")) { - return "if (" + id + ".getFont() != null) { if ((" + valueCode + ").equals(\"bold\")) " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.BOLD)); else " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.BOLD)); }"; - } - compiler.reportError("font-weight must be either \"normal\" or \"bold\", found " + valueCode); - return ""; - } - if (name.equals("font-style")) { - if (valueCode.equals("\"italic\"")) { - return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.ITALIC));"; - } - if (valueCode.equals("\"normal\"")) { - return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.ITALIC));"; - } - if (!valueCode.startsWith("\"")) { - return "if (" + id + ".getFont() != null) { if ((" + valueCode + ").equals(\"italic\")) " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.ITALIC)); else " + - id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.ITALIC)); }"; - } - compiler.reportError("font-style must be either \"normal\" or \"italic\", found " + valueCode); - return ""; - } - if (ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()) && name.equals("layout")) { // handle containerDelegate (e.g. contentPane on JFrame) - String containerDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("containerDelegate"); - if (containerDelegate != null) { - return id + '.' + containerDelegate + "().setLayout(" + valueCode + ");"; - } - } - // ajout du support i18n - if (I18nHelper.isI18nableAttribute(name,compiler)) { - valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); - } - - return super.getSetPropertyCode(id, name, valueCode, compiler); - } - - - /** - * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For - * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and - * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. - * <p/> - * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an - * int-valued property has a value which is not a valid number. By default, this method looks at the - * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. - * - * @param key the name of the int-typed property - * @param value the non-numeric value that was specified for the property - * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid - * @throws NumberFormatException if the property is not an enumeration - */ - protected int constantValue(String key, String value) { - if ((key.equals("mnemonic") || key.equals("displayedMnemonic"))) { - if (value.length() == 1) { - return value.charAt(0); - } - try { - Field vk = java.awt.event.KeyEvent.class.getField(value); - return (Integer) vk.get(null); - } catch (NoSuchFieldException e) { - throw new IllegalArgumentException("mnemonics must be either a single character or the name of a field in KeyEvent (found: '" + value + "')"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - return super.constantValue(key, value); - } - - - /** - * Returns <code>true</code> if this component can contain other components. For children to be - * allowed, the component must be a subclass of <code>Container</code> and its <code>JAXXBeanInfo</code> - * must not have the value <code>false</code> for its <code>isContainer</code> value. - * - * @return <code>true</code> if children are allowed - */ - public boolean isContainer() { - boolean container = ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()); - if (container) { - try { - init(); - if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { - container = false; - } - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - } - return container; - } - - - public String getContainerDelegate() { - try { - init(); - return containerDelegate; - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java (from rev 987, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultComponentHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,275 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags; + +import jaxx.CompilerException; +import jaxx.UnsupportedAttributeException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.I18nHelper; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + +import java.awt.Component; +import java.awt.Container; +import java.awt.event.ComponentListener; +import java.awt.event.ContainerListener; +import java.awt.event.FocusListener; +import java.beans.IntrospectionException; +import java.io.IOException; +import java.lang.reflect.Field; + +public class DefaultComponentHandler extends DefaultObjectHandler { + /** log */ + protected static final Log log = LogFactory.getLog(DefaultComponentHandler.class); + + private String containerDelegate; + + public DefaultComponentHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, Component.class); + /*if (!ClassDescriptorLoader.getClassDescriptor(Component.class).isAssignableFrom(beanClass)) { + throw new IllegalArgumentException(getClass().getName() + " does not support the class " + beanClass.getName()); + }*/ + } + + @Override + protected void init() throws IntrospectionException { + if (jaxxBeanInfo == null) { + super.init(); + + containerDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("containerDelegate"); + if (containerDelegate == null && ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass().getSuperclass())) { + DefaultObjectHandler tagHandler = TagManager.getTagHandler(getBeanClass().getSuperclass()); + if (tagHandler instanceof DefaultComponentHandler) { + containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); + } else { + /*tagHandler = TagManager.getTagHandler(getBeanClass()); + if (tagHandler instanceof DefaultComponentHandler) { + containerDelegate = ((DefaultComponentHandler) tagHandler).getContainerDelegate(); + } else {*/ + log.warn("could not find componentHandler for " + getBeanClass().getSuperclass()); + //} + } + } + } + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("hasFocus", FocusListener.class); + addProxyEventInfo("isVisible", ComponentListener.class); + addProxyEventInfo("getBounds", ComponentListener.class); + addProxyEventInfo("getLocation", ComponentListener.class); + addProxyEventInfo("getLocationOnScreen", ComponentListener.class); + addProxyEventInfo("getSize", ComponentListener.class); + addProxyEventInfo("getX", ComponentListener.class); + addProxyEventInfo("getY", ComponentListener.class); + addProxyEventInfo("getWidth", ComponentListener.class); + addProxyEventInfo("getHeight", ComponentListener.class); + if (ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass())) { + addProxyEventInfo("getComponentCount", ContainerListener.class); + } + } + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, "name", object.getId(), false, compiler); + openComponent(object, tag, compiler); + } + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileSecondPass(tag, compiler); + closeComponent(compiler.getOpenComponent(), tag, compiler); + } + + + protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + String constraints = tag.getAttribute("constraints"); + if (constraints != null && constraints.length() > 0) { + compiler.openComponent(object, constraints); + } else { + compiler.openComponent(object); + } + } + + protected void closeComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + compiler.closeComponent(object); + } + + @Override + public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { + return property.equals("font") || property.startsWith("font-") || property.equals("foreground") || property.equals("enabled"); + } + + @Override + public ClassDescriptor getPropertyType(CompiledObject object, String propertyName, JAXXCompiler compiler) throws CompilerException { + if (propertyName.equals("x") || propertyName.equals("y") || propertyName.equals("width") || propertyName.equals("height") || + "font-size".equals(propertyName)) + return ClassDescriptorLoader.getClassDescriptor(Integer.class); + if (propertyName.equals("font-face") || propertyName.equals("font-style") || propertyName.equals("font-weight")) { + return ClassDescriptorLoader.getClassDescriptor(String.class); + } + return super.getPropertyType(object, propertyName, compiler); + } + + @Override + public String getGetPropertyCode(String id, String name, JAXXCompiler compiler) throws CompilerException { + if (name.equals("font-face")) { + return id + ".getFont().getFontName()"; + } + if (name.equals("font-size")) { + return id + ".getFont().getSize()"; + } + if (name.equals("font-weight")) { + return "(" + id + ".getFont().getStyle() & Font.BOLD) != 0 ? \"bold\" : \"normal\""; + } + if (name.equals("font-style")) { + return "(" + id + ".getFont().getStyle() & Font.ITALIC) != 0 ? \"italic\" : \"normal\""; + } + return super.getGetPropertyCode(id, name, compiler); + } + + @Override + public String getSetPropertyCode(String id, String name, String valueCode, JAXXCompiler compiler) throws CompilerException { + if (name.equals("x")) { + return id + ".setLocation(" + valueCode + ", " + id + ".getY());"; + } + if (name.equals("y")) { + return id + ".setLocation(" + id + ".getX(), " + valueCode + ");"; + } + if (name.equals("width")) { // need to optimize case when both width and height are being assigned + return "jaxx.runtime.Util.setComponentWidth(" + id + "," + valueCode + ");\n"; + } + if (name.equals("height")) { + return "jaxx.runtime.Util.setComponentHeight(" + id + "," + valueCode + ");\n"; + } + if (name.equals("font-face")) { + return "if (" + id + ".getFont() != null) " + id + ".setFont(new Font(" + valueCode + ", " + id + ".getFont().getStyle(), " + id + ".getFont().getSize()));"; + } + if (name.equals("font-size")) { + return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont((float) " + valueCode + "));"; + } + if (name.equals("font-weight")) { + if (valueCode.equals("\"bold\"")) { + return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.BOLD));"; + } + if (valueCode.equals("\"normal\"")) { + return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.BOLD));"; + } + if (!valueCode.startsWith("\"")) { + return "if (" + id + ".getFont() != null) { if ((" + valueCode + ").equals(\"bold\")) " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.BOLD)); else " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.BOLD)); }"; + } + compiler.reportError("font-weight must be either \"normal\" or \"bold\", found " + valueCode); + return ""; + } + if (name.equals("font-style")) { + if (valueCode.equals("\"italic\"")) { + return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.ITALIC));"; + } + if (valueCode.equals("\"normal\"")) { + return "if (" + id + ".getFont() != null) " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.ITALIC));"; + } + if (!valueCode.startsWith("\"")) { + return "if (" + id + ".getFont() != null) { if ((" + valueCode + ").equals(\"italic\")) " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | Font.ITALIC)); else " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~Font.ITALIC)); }"; + } + compiler.reportError("font-style must be either \"normal\" or \"italic\", found " + valueCode); + return ""; + } + if (ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()) && name.equals("layout")) { // handle containerDelegate (e.g. contentPane on JFrame) + String containerDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("containerDelegate"); + if (containerDelegate != null) { + return id + '.' + containerDelegate + "().setLayout(" + valueCode + ");"; + } + } + // ajout du support i18n + if (I18nHelper.isI18nableAttribute(name,compiler)) { + valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); + } + + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + + + /** + * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For + * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and + * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. + * <p/> + * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an + * int-valued property has a value which is not a valid number. By default, this method looks at the + * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. + * + * @param key the name of the int-typed property + * @param value the non-numeric value that was specified for the property + * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid + * @throws NumberFormatException if the property is not an enumeration + */ + protected int constantValue(String key, String value) { + if ((key.equals("mnemonic") || key.equals("displayedMnemonic"))) { + if (value.length() == 1) { + return value.charAt(0); + } + try { + Field vk = java.awt.event.KeyEvent.class.getField(value); + return (Integer) vk.get(null); + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException("mnemonics must be either a single character or the name of a field in KeyEvent (found: '" + value + "')"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + return super.constantValue(key, value); + } + + + /** + * Returns <code>true</code> if this component can contain other components. For children to be + * allowed, the component must be a subclass of <code>Container</code> and its <code>JAXXBeanInfo</code> + * must not have the value <code>false</code> for its <code>isContainer</code> value. + * + * @return <code>true</code> if children are allowed + */ + public boolean isContainer() { + boolean container = ClassDescriptorLoader.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()); + if (container) { + try { + init(); + if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { + container = false; + } + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } + return container; + } + + + public String getContainerDelegate() { + try { + init(); + return containerDelegate; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,1121 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags; - -import jaxx.CompilerException; -import jaxx.UnsupportedAttributeException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.JavaArgument; -import jaxx.compiler.JavaMethod; -import jaxx.css.Stylesheet; -import jaxx.introspection.JAXXBeanInfo; -import jaxx.introspection.JAXXEventSetDescriptor; -import jaxx.introspection.JAXXIntrospector; -import jaxx.introspection.JAXXPropertyDescriptor; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.reflect.FieldDescriptor; -import jaxx.reflect.MethodDescriptor; -import jaxx.runtime.ComponentDescriptor; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; -import jaxx.types.TypeManager; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyChangeListener; -import java.io.IOException; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * Default handler for class tags. Class tags are tags which represent instances of Java classes, - * such as <code><JButton label='Close'/></code>. <code>DefaultObjectHandler</code> - * provides support for attributes and events which adhere to JavaBeans naming conventions as - * well as basic JAXX features like the <code>id</code> attribute and data binding by means of - * curly braces. - * <p/> - * Throughout this class, the word "member" refers to the name of a field or method (e.g. - * <code>"getDocument"</code>) and the word "property" refers to the JavaBeans-style simple - * name of a property (e.g. <code>"document"</code>). - */ -public class DefaultObjectHandler implements TagHandler { - /** The class that this handler provides support for. */ - private ClassDescriptor beanClass; - - /** The JAXXBeanInfo for the beanClass. */ - protected JAXXBeanInfo jaxxBeanInfo; - - /** Maps property names to their respective JAXXPropertyDescriptors. */ - private Map<String, JAXXPropertyDescriptor> properties; - - /** Maps event names to their respective JAXXEventSetDescriptors. */ - private Map<String, JAXXEventSetDescriptor> events; - - /** Maps property names to their respective ProxyEventInfos. */ - private Map<String, ProxyEventInfo> eventInfos; - - /** Maps XML tags to the CompiledObjects created from them. */ - protected static Map<Element, CompiledObject> objectMap = new WeakHashMap<Element, CompiledObject>(); - - /** - * Encapsulates information about a "proxy event handler", which is an event handler that - * fires PropertyChangeEvents when it is triggered. ProxyEventInfos simplify the data binding - * system by allowing all dependencies to fire the same kind of event even if they would - * normally throw something else, like <code>DocumentEvent</code>. - */ - private class ProxyEventInfo { - /** The name of the method or field being proxied, e.g. "getText". */ - String memberName; - - /** The "actual" event listener for the property in question, e.g. DocumentListener. */ - ClassDescriptor listenerClass; - - /** - * In cases where a different object (such as a model) is more directly responsible for - * managing the property, this is the name of the property where that object can be - * found, e.g. "document" (which is turned into a call to "getDocument()"). This property - * is also treated as a dependency of the data binding expression, and any updates to it - * (assuming it is bound) will cause the listener to be removed from the old value and - * attached to the new value, and the data binding to be processed. - */ - String modelName; - - /** The name of the method used to add the "native" event listener, e.g. "addDocumentListener". */ - String addMethod; - - /** The name of the method used to remove the "native" event listener, e.g. "removeDocumentListener". */ - String removeMethod; - } - - - /** - * Creates a new <code>DefaultObjectHandler</code> which provides support for the specified class. The - * class is not actually introspected until the {@link #compileFirstPass} method is invoked. - * - * @param beanClass the class which this handler supports - */ - public DefaultObjectHandler(ClassDescriptor beanClass) { - this.beanClass = beanClass; - } - - - /** - * Performs introspection on the beanClass and stores the results. - * - * @throws java.beans.IntrospectionException - * TODO - */ - protected void init() throws IntrospectionException { - if (jaxxBeanInfo == null) { - // perform introspection & cache the results - jaxxBeanInfo = getJAXXBeanInfo(beanClass); - - JAXXPropertyDescriptor[] propertiesArray = jaxxBeanInfo.getJAXXPropertyDescriptors(); - properties = new HashMap<String, JAXXPropertyDescriptor>(); - for (int i = propertiesArray.length - 1; i >= 0; i--) { - properties.put(propertiesArray[i].getName(), propertiesArray[i]); - } - - JAXXEventSetDescriptor[] eventsArray = jaxxBeanInfo.getJAXXEventSetDescriptors(); - events = new HashMap<String, JAXXEventSetDescriptor>(); - for (int i = eventsArray.length - 1; i >= 0; i--) { - MethodDescriptor[] methods = eventsArray[i].getListenerMethods(); - for (MethodDescriptor method : methods) { - events.put(method.getName(), eventsArray[i]); - } - } - - configureProxyEventInfo(); - } - } - - - /** - * Returns - * - * @return the class which this <code>DefaultObjectHandler</code> supports. - */ - public ClassDescriptor getBeanClass() { - return beanClass; - } - - - /** - * @return the <code>JAXXBeanInfo</code> for the class which this <code>DefaultObjectHandler</code> - * supports. - */ - public JAXXBeanInfo getJAXXBeanInfo() { - try { - init(); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - return jaxxBeanInfo; - } - - - /** - * Returns the <code>JAXXBeanInfo</code> for the specified class. - * - * @param beanClass the bean class for which to retrieve <code>JAXXBeanInfo</code> - * @return the class' <code>JAXXBeanInfo</code> - * @throws java.beans.IntrospectionException - * ? - */ - public static JAXXBeanInfo getJAXXBeanInfo(ClassDescriptor beanClass) throws IntrospectionException { - return JAXXIntrospector.getJAXXBeanInfo(beanClass); - } - - - /** - * Returns the type of the named property. This is the return type of the property's <code>get</code> method; - * for instance <code>JLabel</code>'s <code>text</code> property is a <code>String</code>. - * - * @param object the object being compiled - * @param propertyName the simple JavaBeans-style name of the property - * @param compiler the current <code>JAXXCompiler</code> - * @return the property's type - * @throws CompilerException if the type cannot be determined - */ - public ClassDescriptor getPropertyType(CompiledObject object, String propertyName, JAXXCompiler compiler) { - try { - init(); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - - JAXXPropertyDescriptor property = properties.get(propertyName); - if (property != null) { - return property.getPropertyType(); - } - throw new UnsupportedAttributeException("property '" + propertyName + "' not found in " + object); - } - - - /** - * @param name ? - * @return <code>true</code> if the named member is <i>bound</i> (fires <code>PropertyChangeEvent</code> - * when modified). Members are either fields (represented by the simple name of the field) or <code>get/is</code> - * methods (represented by the simple name of the method, <b>not</b> the simplified JavaBeans-style name). - * Methods which are not actually bound in their native class, but for which proxy events have been - * configured (such as <code>JTextField.getText</code>, return <code>true</code>. - * @throws jaxx.UnsupportedAttributeException - * ? - */ - public boolean isMemberBound(String name) throws UnsupportedAttributeException { - try { - init(); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - - if (eventInfos != null && eventInfos.containsKey(name)) { - return true; - } - - if (name.equals("getClass")) { - return false; - } - - String propertyName = null; - if (name.startsWith("get")) { - propertyName = Introspector.decapitalize(name.substring("get".length())); - } else if (name.startsWith("is")) { - propertyName = Introspector.decapitalize(name.substring("is".length())); - } - JAXXPropertyDescriptor property = propertyName != null ? properties.get(propertyName) : null; - if (property != null) { - return property.isBound(); - } - try { - FieldDescriptor field = getBeanClass().getFieldDescriptor(name); - return Modifier.isFinal(field.getModifiers()); // final fields might as well be considered bound -- they can't be modified anyway - } catch (NoSuchFieldException e) { - throw new UnsupportedAttributeException("cannot find property '" + name + "' of " + getBeanClass()); - } - } - - - private static ClassDescriptor getEventClass(ClassDescriptor listenerClass) { - return listenerClass.getMethodDescriptors()[0].getParameterTypes()[0]; - } - - - /** - * @param memberName name of the member - * @return an array of members on which the given property depends. For - * example, the JTextField.getText() member depends upon the getModel() - * member. Returns <code>null</code> if there are no dependencies. - */ - public String[] getMemberDependencies(String memberName) { - ProxyEventInfo eventInfo = eventInfos != null ? eventInfos.get(memberName) : null; - return eventInfo == null ? null : new String[]{eventInfo.modelName}; - } - - - /** - * Returns a snippet of Java code which will cause a <code>PropertyChangeListener</code> to be notified - * when the member's value changes. The <code>PropertyChangeListener</code> is provided in the form - * of a Java code snippet that evaluates to a listener object. - * <p/> - * For ordinary bound JavaBeans properties, the Java code returned is a simple call to - * <code>addPropertyChangeListener</code>. Fields and methods which do not actually fire - * <code>PropertyChangeEvents</code> when they change necessitate more complex code. - * - * @param objectCode Java code which evaluates to the object to which to add the listener - * *@param dataBinding the name of the data binding this listener is a part of - * @param dataBinding databinding - * @param memberName the name of the field or method to listen to - * @param propertyChangeListenerCode Java code which evaluates to a <code>PropertyChangeListener</code> - * @param compiler the current <code>JAXXCompiler</code> - * @return Java code snippet which causes the listener to be added to the object - */ - public String getAddMemberListenerCode(String objectCode, String dataBinding, String memberName, String propertyChangeListenerCode, JAXXCompiler compiler) { - if ("getClass".equals(memberName)) { - return null; - } - - ProxyEventInfo eventInfo = eventInfos != null ? eventInfos.get(memberName) : null; - if (eventInfo != null) { // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents - StringBuffer result = new StringBuffer(); - String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode); - boolean methodExists = false; - JavaMethod[] methods = compiler.getJavaFile().getMethods(); - for (JavaMethod method : methods) { - if (method.getName().equals(methodName)) { - methodExists = true; - break; - } - } - ClassDescriptor eventClass = getEventClass(eventInfo.listenerClass); - if (!methodExists) { - compiler.getJavaFile().addMethod(new JavaMethod(Modifier.PUBLIC, "void", methodName, - new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, - propertyChangeListenerCode + ".propertyChange(null);")); - } - String code = objectCode + (eventInfo.modelName != null ? ".get" + JAXXCompiler.capitalize(eventInfo.modelName) + "()" : ""); - result.append("$bindingSources.put(\"").append(code).append("\", ").append(code).append(");").append(JAXXCompiler.getLineSeparator()); - result.append(code).append('.').append(eventInfo.addMethod).append("((").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(") jaxx.runtime.Util.getEventListener(").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(".class, ").append(compiler.getRootObject().getJavaCode()).append(", ").append(TypeManager.getJavaCode(methodName)).append("));\n"); - if (eventInfo.modelName != null) { - result.append(getAddMemberListenerCode(objectCode, dataBinding, "get" + JAXXCompiler.capitalize(eventInfo.modelName), - "jaxx.runtime.Util.getDataBindingUpdateListener(this , \"" + dataBinding + "\")", - compiler)); - } - return result.toString(); - } else { - String propertyName = null; - if (memberName.startsWith("get")) { - propertyName = Introspector.decapitalize(memberName.substring("get".length())); - } else if (memberName.startsWith("is")) { - propertyName = Introspector.decapitalize(memberName.substring("is".length())); - } - else { - try { - getBeanClass().getFieldDescriptor(memberName); - propertyName = memberName; - } catch (NoSuchFieldException e) { - // ignore ? - } - } - if (propertyName != null) { - try { - // check for property-specific addPropertyChangeListener method - getBeanClass().getMethodDescriptor("addPropertyChangeListener", new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(String.class), - ClassDescriptorLoader.getClassDescriptor(PropertyChangeListener.class)}); - return objectCode + ".addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; - } catch (NoSuchMethodException e) { - // no property-specific method, use general one - return objectCode + ".addPropertyChangeListener(" + propertyChangeListenerCode + ");\n"; - } - } - return null; - } - } - - - public String getRemoveMemberListenerCode(String objectCode, String dataBinding, String memberName, String propertyChangeListenerCode, JAXXCompiler compiler) { - if ("getClass".equals(memberName)) { - return null; - } - - ProxyEventInfo eventInfo = eventInfos != null ? eventInfos.get(memberName) : null; - if (eventInfo != null) { // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents - StringBuffer result = new StringBuffer(); - String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode); - boolean methodExists = false; - JavaMethod[] methods = compiler.getJavaFile().getMethods(); - for (JavaMethod method : methods) { - if (method.getName().equals(methodName)) { - methodExists = true; - break; - } - } - ClassDescriptor eventClass = getEventClass(eventInfo.listenerClass); - if (!methodExists) { - compiler.getJavaFile().addMethod(new JavaMethod(Modifier.PUBLIC, "void", methodName, - new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, - propertyChangeListenerCode + ".propertyChange(null);")); - } - try { - String modelMemberName = eventInfo.modelName != null ? "get" + JAXXCompiler.capitalize(eventInfo.modelName) : null; - String modelClassName = modelMemberName != null ? getBeanClass().getMethodDescriptor(modelMemberName, new ClassDescriptor[0]).getReturnType().getName() : JAXXCompiler.getCanonicalName(getBeanClass()); - String code = objectCode + (eventInfo.modelName != null ? "." + modelMemberName + "()" : ""); - result.append("((").append(modelClassName).append(") $bindingSources.remove(\"").append(code).append("\")).").append(eventInfo.removeMethod).append("((").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(") jaxx.runtime.Util.getEventListener(").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(".class, ").append(compiler.getRootObject().getJavaCode()).append(", ").append(TypeManager.getJavaCode(methodName)).append("));\n"); - if (eventInfo.modelName != null) { - result.append(getRemoveMemberListenerCode(objectCode, dataBinding, "get" + JAXXCompiler.capitalize(eventInfo.modelName), - "jaxx.runtime.Util.getDataBindingUpdateListener(this, \"" + dataBinding + "\")", - compiler)); - } - return result.toString(); - } - catch (NoSuchMethodException e) { - throw new CompilerException("Internal error: " + e); - } - } else { - String propertyName = null; - if (memberName.startsWith("get")) { - propertyName = Introspector.decapitalize(memberName.substring("get".length())); - } else if (memberName.startsWith("is")) { - propertyName = Introspector.decapitalize(memberName.substring("is".length())); - } else { - try { - getBeanClass().getFieldDescriptor(memberName); - propertyName = memberName; - } catch (NoSuchFieldException e) { - // ignore ? - } - } - if (propertyName != null) { - try { - // check for property-specific removePropertyChangeListener method - getBeanClass().getMethodDescriptor("removePropertyChangeListener", new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(String.class), - ClassDescriptorLoader.getClassDescriptor(PropertyChangeListener.class)}); - return objectCode + ".removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; - } catch (NoSuchMethodException e) { - // no property-specific method, use general one - return objectCode + ".removePropertyChangeListener(" + propertyChangeListenerCode + ");\n"; - } - } - return null; - } - } - - - /** - * Configures the event handling for members which do not fire <code>PropertyChangeEvent</code> when - * modified. The default implementation does nothing. Subclasses should override this method to call - * <code>addProxyEventInfo</code> for each member which requires special handling. - */ - protected void configureProxyEventInfo() { - } - - - /** - * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound - * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are - * not bound property <code>get</code> methods. The proxy event handler will attach the specified kind - * of listener to the class and fire a <code>PropertyChangeEvent</code> whenever the listener receives - * any kind of event. - * <p/> - * Even though this method can theoretically be applied to fields (in addition to methods), it would be an - * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would - * be difficult to have a listener that was always notified when a field value changed. - * - * @param memberName the name of the field or method being proxied - * @param listenerClass the type of listener which receives events when the field or method is updated - */ - public void addProxyEventInfo(String memberName, Class listenerClass) { - addProxyEventInfo(memberName, listenerClass, null); - } - - - /** - * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound - * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are - * not bound property <code>get</code> methods. This variant attaches a listener to a property of the - * object (such as <code>model</code>) and not the object itself, which is useful when there is a model - * that is the "real" container of the information. The proxy event handler will attach the specified kind - * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire - * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. - * <p/> - * If the property is itself bound (typically the case with models), any updates to the property's value will - * cause the listener to be removed from the old property value and reattached to the new property value, - * as well as cause a <code>PropertyChangeEvent</code> to be fired. - * <p/> - * Even though this method can theoretically be applied to fields (in addition to methods), it would be an - * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would - * be difficult to have a listener that was always notified when a field value changed. - * - * @param memberName the name of the field or method being proxied - * @param listenerClass the type of listener which receives events when the field or method is updated - * @param modelName the JavaBeans-style name of the model property - */ - public void addProxyEventInfo(String memberName, Class listenerClass, String modelName) { - String listenerName = listenerClass.getName(); - listenerName = listenerName.substring(listenerName.lastIndexOf(".") + 1); - addProxyEventInfo(memberName, listenerClass, modelName, "add" + listenerName, "remove" + listenerName); - } - - - // TODO: remove this temporary method, complete switchover to ClassDescriptors - public void addProxyEventInfo(String memberName, Class listenerClass, - String modelName, String addMethod, String removeMethod) { - try { - addProxyEventInfo(memberName, ClassDescriptorLoader.getClassDescriptor(listenerClass.getName()), modelName, addMethod, removeMethod); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - - /** - * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound - * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are - * not bound property <code>get</code> methods. This variant attaches a listener to a property of the - * object (such as <code>model</code>) and not the object itself, which is useful when there is a model - * that is the "real" container of the information. The proxy event handler will attach the specified kind - * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire - * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. - * <p/> - * If the property is itself bound (typically the case with models), any updates to the property's value will - * cause the listener to be removed from the old property value and reattached to the new property value, - * as well as cause a <code>PropertyChangeEvent</code> to be fired. - * <p/> - * This variant of <code>addProxyEventInfo</code> allows the names of the methods that add and remove - * the event listener to be specified, in cases where the names are not simply <code>add<listenerClassName></code> - * and <code>remove<listenerClassName></code>. - * <p/> - * Even though this method can theoretically be applied to fields (in addition to methods), it would be an - * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would - * be difficult to have a listener that was always notified when a field value changed. - * - * @param memberName the name of the field or method being proxied - * @param listenerClass the type of listener which receives events when the field or method is updated - * @param modelName the JavaBeans-style name of the model property - * @param addMethod add method name - * @param removeMethod remove method name - */ - public void addProxyEventInfo(String memberName, ClassDescriptor listenerClass, - String modelName, String addMethod, String removeMethod) { - ProxyEventInfo info = new ProxyEventInfo(); - info.memberName = memberName; - info.listenerClass = listenerClass; - info.modelName = modelName; - info.addMethod = addMethod; - info.removeMethod = removeMethod; - if (eventInfos == null) { - eventInfos = new HashMap<String, ProxyEventInfo>(); - } - eventInfos.put(memberName, info); - } - - - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - scanAttributesForDependencies(tag, compiler); - compileChildrenFirstPass(tag, compiler); - } - - - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - try { - init(); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - CompiledObject object = objectMap.get(tag); - if (object == null) { - throw new IllegalStateException("unable to find CompiledObject associated with tag <" + tag.getTagName() + ">; should have been registered before second pass"); - } - compiler.checkOverride(object); - String constructorParams = tag.getAttribute("constructorParams"); - if (constructorParams != null && constructorParams.length() > 0) { - object.setConstructorParams(compiler.getScriptManager().trimScript(constructorParams)); - } - - setDefaults(object, tag, compiler); - setAttributes(object, tag, compiler); - - compileChildrenSecondPass(tag, compiler); - } - - - public void registerCompiledObject(Element tag, JAXXCompiler compiler) { - String id = tag.getAttribute("id"); - if (id == null || id.length() == 0) { - id = compiler.getAutoId(getBeanClass()); - } - CompiledObject object = createCompiledObject(id, compiler); - objectMap.put(tag, object); - String styleClass = tag.getAttribute("styleClass").trim(); - if (styleClass.length() > 0) { - object.setStyleClass(styleClass); - } - compiler.registerCompiledObject(object); - } - - - /** - * Creates the <code>CompiledObject</code> which will represent the object created by this <code>TagHandler</code>. - * - * @param id the <code>CompiledObject's</code> ID. - * @param compiler compiler to use - * @return the <code>CompiledObject</code> to use - */ - protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) { - return new CompiledObject(id, getBeanClass(), compiler); - } - - - /** - * Initializes the default settings of the object, prior to setting its attribute values. The default - * implementation does nothing. - * - * @param object the object to initialize - * @param tag the tag being compiled - * @param compiler the current <code>JAXXCompiler</code> - */ - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) { - } - - - /** - * @param property property name to test - * @return <code>true</code> if the specified property should be inherited by child components when specified - * via CSS. - * @throws jaxx.UnsupportedAttributeException - * ? - */ - public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { - return false; - } - - - /** - * @param name name of event - * @return <code>true</code> if the specified name has the form of an event handler attribute - * (e.g. "onActionPerformed"). - */ - public boolean isEventHandlerName(String name) { - return name.length() > 2 && name.startsWith("on") && Character.isUpperCase(name.charAt(2)); - } - - - /** - * Scans all attributes for any dependency classes and adds them to the current compilation - * set. Called by <code>compileFirstPass()</code> (it is an error to add dependencies after - * pass 1 is complete). - * - * @param tag tag to scan - * @param compiler compiler to use - */ - protected void scanAttributesForDependencies(Element tag, JAXXCompiler compiler) { - List<Attr> attributes = new ArrayList<Attr>(); - NamedNodeMap children = tag.getAttributes(); - for (int i = 0; i < children.getLength(); i++) { - attributes.add((Attr) children.item(i)); - } - Collections.sort(attributes, getAttributeComparator()); - - for (Attr attribute : attributes) { - String name = attribute.getName(); - String value = attribute.getValue(); - if (name.equals("constraints") || isEventHandlerName(name)) { - compiler.preprocessScript(value); // adds dependencies as a side effect - } else if (name.equals("constructorParams")) { - for (String param : value.split("\\s*,\\s*")) { - compiler.preprocessScript(param); - } - } else if (value.startsWith("{") && value.endsWith("}")) { - compiler.preprocessScript(value.substring(1, value.length() - 1)); - } - } - } - - - /** - * Processes the attributes of an XML tag. Four kinds of attributes are supported: simple property values (of any - * datatype supported by {@link #convertFromString}), data binding expressions (attributes containing curly-brace - * pairs), event listeners (attributes starting with 'on', such as 'onActionPerformed'), and JAXX-defined properties - * such as 'id'. - * - * @param object the object to be modified - * @param tag the tag from which to pull attributes - * @param compiler the current <code>JAXXCompiler</code> - */ - public void setAttributes(CompiledObject object, Element tag, JAXXCompiler compiler) { - List<Attr> attributes = new ArrayList<Attr>(); - NamedNodeMap children = tag.getAttributes(); - for (int i = 0; i < children.getLength(); i++) { - attributes.add((Attr) children.item(i)); - } - Collections.sort(attributes, getAttributeComparator()); - - for (Attr attribute : attributes) { - String name = attribute.getName(); - String value = attribute.getValue().trim(); - if (name.equals("id") || name.equals("constraints") || name.equals("constructorParams") || name.equals("styleClass") || - name.startsWith("xmlns") || JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { - // ignore, already handled - } else if (isEventHandlerName(name)) { - if (!value.endsWith(";")) { - value+=";"; - } - addEventHandler(object, Introspector.decapitalize(name.substring(2)), value, compiler); - } else { - setAttribute(object, name, value, true, compiler); - } - } - } - - - /** - * Returns a <code>Comparator</code> which defines the ordering in which the tag's attributes should be processed. The - * default implementation sorts the attributes according to the order defined by the {@link #getAttributeOrdering} method. - * - * @return a <code>Comparator</code> defining the order of attribute processing - */ - protected Comparator<Attr> getAttributeComparator() { - return new Comparator<Attr>() { - public int compare(Attr a, Attr b) { - int aOrder = getAttributeOrdering(a); - int bOrder = getAttributeOrdering(b); - - return aOrder - bOrder; - } - }; - } - - - /** - * Returns the priority with which a particular attribute should be processed. Lower numbers should be processed before - * higher numbers. This value is used by the {@link #getAttributeComparator} method to define the sort ordering. - * - * @param attr the attribute to treate - * @return the attribute's priority - */ - protected int getAttributeOrdering(Attr attr) { - if (attr.getName().equals("displayedMnemonicIndex") || attr.getName().equals("displayedMnemonic") || attr.getName().equals("mnemonic")) { - return 1; - } - return 0; - } - - - public String getApplyPropertyOrDataBindingCode(CompiledObject object, String propertyName, String stringValue, JAXXCompiler compiler) { - ClassDescriptor type = getPropertyType(object, propertyName, compiler); - String binding = compiler.processDataBindings(stringValue, type); - if (binding != null) { - return ""; - } - try { - Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; - Object value = convertFromString(propertyName, stringValue, typeClass); - return getSetPropertyCode(object.getJavaCode(), propertyName, TypeManager.getJavaCode(value), compiler); - } catch (NumberFormatException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (IllegalArgumentException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (ClassNotFoundException e) { - compiler.reportError("could not find class " + type.getName()); - } - return ""; - } - - - /** - * Set a single property on an object. The value may be either a simple value or contain data binding expressions. - * Simple values are first converted to the property's type using {@link #convertFromString}. - * - * @param object the object on which to set the property - * @param propertyName the name of the property to set - * @param stringValue the raw string value of the property from the XML - * @param inline <code>true</code> if the value was directly specified as an inline class tag attribute, <code>false</code> otherwise (a default value, specified in CSS, etc.) - * @param compiler the current <code>JAXXCompiler</code> - */ - public void setAttribute(CompiledObject object, String propertyName, String stringValue, boolean inline, JAXXCompiler compiler) { - try { - if (ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(object.getObjectClass())) { - // check for data binding & remove if found - JAXXObjectDescriptor jaxxObjectDescriptor = object.getObjectClass().getJAXXObjectDescriptor(); - ComponentDescriptor root = jaxxObjectDescriptor.getComponentDescriptors()[0]; - object.appendInitializationCode(object.getJavaCode() + ".removeDataBinding(" + TypeManager.getJavaCode(root.getId() + "." + propertyName) + ");" + JAXXCompiler.getLineSeparator()); - } - object.addProperty(propertyName, stringValue); - ClassDescriptor type = getPropertyType(object, propertyName, compiler); - String binding = compiler.processDataBindings(stringValue, type); - if (binding != null) { - if (inline) { - compiler.addInlineStyle(object, propertyName, true); - } - ClassDescriptor propertyType = getPropertyType(object, propertyName, compiler); - if (propertyType != null && - propertyType != ClassDescriptorLoader.getClassDescriptor(Boolean.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Byte.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Short.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Integer.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Float.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Double.class) && - propertyType != ClassDescriptorLoader.getClassDescriptor(Character.class)) { - //binding = "((" + propertyType.getName() + ") " + binding + ")"; - } - if (propertyName.equals("layout")) { // handle containerDelegate (e.g. contentPane on JFrame) - // have to set layout early, before children are added - object.appendInitializationCode(getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler)); - } - object.registerDataBinding(binding, propertyName, getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler), compiler); - } else { // no bindings, convert from string - if (inline) { - compiler.addInlineStyle(object, propertyName, false); - } - try { - Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; - Object value = convertFromString(propertyName, stringValue, typeClass); - setProperty(object, propertyName, value, compiler); - } catch (NumberFormatException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (IllegalArgumentException e) { - compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); - } catch (ClassNotFoundException e) { - compiler.reportError("could not find class " + type.getName()); - } - } - } catch (UnsupportedAttributeException e) { - compiler.reportError("class " + object.getObjectClass().getName() + " does not support attribute '" + propertyName + "'"); - } - } - - - public void applyStylesheets(CompiledObject object, JAXXCompiler compiler) { - applyStylesheets(object, compiler, null); - } - - - private void applyStylesheets(final CompiledObject object, JAXXCompiler compiler, Stylesheet overrides) { - applyStylesheets(object, compiler, overrides, true); - } - - - private void applyStylesheets(final CompiledObject object, JAXXCompiler compiler, Stylesheet overrides, boolean recurse) { - try { - Stylesheet stylesheet = compiler.getStylesheet(); - ClassDescriptor objectClass = object.getObjectClass(); - if (recurse && ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(objectClass)) { - JAXXObjectDescriptor jaxxObjectDescriptor = objectClass.getJAXXObjectDescriptor(); - ComponentDescriptor[] descriptors = jaxxObjectDescriptor.getComponentDescriptors(); - for (ComponentDescriptor descriptor : descriptors) { - ClassDescriptor classDescriptor = ClassDescriptorLoader.getClassDescriptor(descriptor.getJavaClassName()); - boolean isRoot = classDescriptor != objectClass; - String id = isRoot ? object.getId() + ' ' + descriptor.getId() : "( " + object.getId() + " ) " + descriptor.getId(); - CompiledObject child = new CompiledObject(id, - "((" + JAXXCompiler.getCanonicalName(classDescriptor) + ") " + - object.getJavaCode() + ".getObjectById(" + TypeManager.getJavaCode(descriptor.getId()) + "))", - classDescriptor, - compiler, - true); - ComponentDescriptor parentDescriptor = descriptor.getParent(); - CompiledObject currentObject = child; - while (parentDescriptor != null) { - CompiledObject parent = new CompiledObject("internal", ClassDescriptorLoader.getClassDescriptor(parentDescriptor.getJavaClassName()), compiler); - currentObject.setParent(parent); - currentObject = parent; - parentDescriptor = parentDescriptor.getParent(); - } - currentObject.setParent(object); - String styleClass = object.getStyleClass(); - if (styleClass == null) { - styleClass = descriptor.getStyleClass(); - } - child.setStyleClass(styleClass); - Stylesheet mergedStylesheet = overrides; - Stylesheet childOverrides = jaxxObjectDescriptor.getStylesheet(); - if (childOverrides != null) { - if (mergedStylesheet == null) { - mergedStylesheet = childOverrides; - } else { - mergedStylesheet.add(childOverrides.getRules()); - } - } - TagManager.getTagHandler(objectClass).applyStylesheets(child, compiler, mergedStylesheet, isRoot); - object.appendInitializationCode(child.getInitializationCode(compiler)); - } - } else if (stylesheet != null) - stylesheet.applyTo(object, compiler, overrides); - } - catch (ClassNotFoundException e) { - throw new CompilerException(e); - } - } - - - /** - * Adds the necessary Java code to a <code>CompiledObject</code> to add an event listener at runtime. - * - * @param object the <code>CompiledObject</code> to which the event listener should be added - * @param name the name of the event listener, such as <code>"actionPerformed"</code> - * @param value the Java code snippet to execute when the event is fired - * @param compiler the current <code>JAXXCompiler</code> - */ - public void addEventHandler(CompiledObject object, String name, String value, JAXXCompiler compiler) { - JAXXEventSetDescriptor JAXXEventSetDescriptor = events.get(name); - if (JAXXEventSetDescriptor != null) { - MethodDescriptor[] listenerMethods = JAXXEventSetDescriptor.getListenerMethods(); - MethodDescriptor listenerMethod = null; - for (MethodDescriptor listenerMethod1 : listenerMethods) { - if (listenerMethod1.getName().equals(name)) { - listenerMethod = listenerMethod1; - break; - } - } - if (listenerMethod == null) { - throw new RuntimeException("expected to find method '" + name + "' in JAXXEventSetDescriptor.getListenerMethods()"); - } - try { - value = compiler.preprocessScript(value); - object.addEventHandler(name, JAXXEventSetDescriptor.getAddListenerMethod(), listenerMethod, value, compiler); - } catch (CompilerException e) { - compiler.reportError("While parsing event handler for '" + name + "': " + e.getMessage()); - } - } else - compiler.reportError("could not find event '" + name + "' for object " + object); - } - - - /** - * Returns a snippet of Java code which will retrieve an object property at runtime. Typically the code is - * just a call to the property's <code>get</code> method, but it can be arbitrarily complex. - * - * @param javaCode Java code for the object whose property is being retrieved - * @param name the name of the property to retrieve - * @param compiler the current <code>JAXXCompiler</code> - * @return the snippet - * @throws CompilerException if a compilation error occurs - */ - public String getGetPropertyCode(String javaCode, String name, JAXXCompiler compiler) { - try { - init(); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - - JAXXPropertyDescriptor property = properties.get(name); - if (property != null) { - if (property.getReadMethodDescriptor() != null) { - return javaCode + '.' + property.getReadMethodDescriptor().getName() + "()"; - } - throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " has no read method"); - } - throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); - } - - - /** - * Returns a snippet of Java code which will set an object property at runtime. Typically the code is - * just a call to the property's <code>set</code> method, but it can be arbitrarily complex. - * - * @param javaCode Java code for the object whose property is being set - * @param name the name of the property to set - * @param valueCode Java expression representing the value to set the property to - * @param compiler the current <code>JAXXCompiler</code> - * @return the snippet - * @throws CompilerException if a compilation error occurs - */ - public String getSetPropertyCode(String javaCode, String name, String valueCode, JAXXCompiler compiler) { - JAXXPropertyDescriptor property = properties.get(name); - if (property != null) { - if (property.getWriteMethodDescriptor() != null) { - return javaCode + '.' + property.getWriteMethodDescriptor().getName() + '(' + valueCode + ");"; - } - throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " is read-only"); - } - throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); - } - - - /** - * Appends Java code to a <code>CompiledObject</code> in order to implement a property assignment. - * <code>setProperty</code> is invoked in response to most XML attributes (those which are not more - * complicated cases, like data bindings or event handlers). - * <p/> - * By the time it reaches this method, the <code>value</code> has already been converted from its XML - * string representation to the appropriate destination type for the property (i.e. if - * <code>JLabel.foreground</code> is being set, <code>value</code> will be a <code>Color</code>). - * - * @param object the object being modified - * @param name the name of the property to set - * @param value the value to set the property to - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - */ - public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) { - object.appendInitializationCode(getSetPropertyCode(object.getJavaCode(), name, TypeManager.getJavaCode(value), compiler)); - } - - - /** - * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For - * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and - * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. - * <p/> - * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an - * int-valued property has a value which is not a valid number. By default, this method looks at the - * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. - * - * @param key the name of the int-typed property - * @param value the non-numeric value that was specified for the property - * @return the constant integer value - * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid - * @throws NumberFormatException if the property is not an enumeration - */ - protected int constantValue(String key, String value) { - JAXXBeanInfo JAXXBeanInfo = getJAXXBeanInfo(); - JAXXPropertyDescriptor[] properties = JAXXBeanInfo.getJAXXPropertyDescriptors(); - String lowercaseValue = value.toLowerCase(); - for (JAXXPropertyDescriptor property : properties) { - if (property.getName().equals(key)) { - Object[] values = (Object[]) property.getValue("enumerationValues"); - if (values != null) { - for (int j = 0; j < values.length - 2; j += 3) { - if (((String) values[j]).toLowerCase().equals(lowercaseValue)) { - return (Integer) values[j + 1]; - } - } - - StringBuffer message = new StringBuffer("value of '" + key + "' must be one of: ["); - for (int j = 0; j < values.length - 2; j += 3) { - if (j != 0) { - message.append(", "); - } - message.append(((String) values[j]).toLowerCase()); - } - message.append("] (found '").append(value).append("')"); - throw new IllegalArgumentException(message.toString()); - } - } - } - throw new NumberFormatException(value); - } - - - /** - * As {@link TypeManager#convertFromString(String, Class)}, except that it additionally supports constant names - * for <code>int</code>-valued types. - * - * @param key the name of the property whose value is being converted - * @param value the raw string value of the property as it appears in the XML - * @param type the datatype to convert the string into - * @return the converted object - * @see #constantValue - */ - protected Object convertFromString(String key, String value, Class type) { - if (type == null || type == Object.class) { - return value; - } - - try { - return TypeManager.convertFromString(value, type); - } catch (NumberFormatException e) { - if (type == int.class || type == Integer.class) { - return constantValue(key, value); - } - throw e; - } - } - - - /** - * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} - * for each child tag. - * - * @param tag the tag whose children to compile - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagFirstPass(child, compiler); - } - } - } - - - /** - * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} - * for each child tag. - * - * @param tag the tag whose children to compile - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - int nodeType = node.getNodeType(); - if (nodeType == Node.ELEMENT_NODE) { - Element child = (Element) node; - compileChildTagSecondPass(child, compiler); - } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { - String text = ((Text) node).getData().trim(); - if (text.length() > 0) { - compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); - } - } - } - } - - - /** - * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass - * JAXXCompiler.compileFirstPass}. - * - * @param tag the child tag to compile - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileFirstPass(tag); - } - - - /** - * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass - * JAXXCompiler.compileSecondPass}. - * - * @param tag the child tag to compile - * @param compiler the current <code>JAXXCompiler</code> - * @throws CompilerException if a compilation error occurs - * @throws IOException if an I/O error occurs - */ - protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - compiler.compileSecondPass(tag); - } - - @Override - public String toString() { - return getClass().getName() + "[" + getBeanClass().getName() + "]"; - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,1109 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags; + +import jaxx.CompilerException; +import jaxx.UnsupportedAttributeException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JavaArgument; +import jaxx.compiler.JavaMethod; +import jaxx.css.Stylesheet; +import jaxx.introspection.JAXXBeanInfo; +import jaxx.introspection.JAXXEventSetDescriptor; +import jaxx.introspection.JAXXIntrospector; +import jaxx.introspection.JAXXPropertyDescriptor; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.FieldDescriptor; +import jaxx.reflect.MethodDescriptor; +import jaxx.runtime.ComponentDescriptor; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.types.TypeManager; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +/** + * Default handler for class tags. Class tags are tags which represent instances of Java classes, + * such as <code><JButton label='Close'/></code>. <code>DefaultObjectHandler</code> + * provides support for attributes and events which adhere to JavaBeans naming conventions as + * well as basic JAXX features like the <code>id</code> attribute and data binding by means of + * curly braces. + * <p/> + * Throughout this class, the word "member" refers to the name of a field or method (e.g. + * <code>"getDocument"</code>) and the word "property" refers to the JavaBeans-style simple + * name of a property (e.g. <code>"document"</code>). + */ +public class DefaultObjectHandler implements TagHandler { + /** The class that this handler provides support for. */ + private ClassDescriptor beanClass; + + /** The JAXXBeanInfo for the beanClass. */ + protected JAXXBeanInfo jaxxBeanInfo; + + /** Maps property names to their respective JAXXPropertyDescriptors. */ + private Map<String, JAXXPropertyDescriptor> properties; + + /** Maps event names to their respective JAXXEventSetDescriptors. */ + private Map<String, JAXXEventSetDescriptor> events; + + /** Maps property names to their respective ProxyEventInfos. */ + private Map<String, ProxyEventInfo> eventInfos; + + /** Maps XML tags to the CompiledObjects created from them. */ + protected static Map<Element, CompiledObject> objectMap = new WeakHashMap<Element, CompiledObject>(); + + /** + * Encapsulates information about a "proxy event handler", which is an event handler that + * fires PropertyChangeEvents when it is triggered. ProxyEventInfos simplify the data binding + * system by allowing all dependencies to fire the same kind of event even if they would + * normally throw something else, like <code>DocumentEvent</code>. + */ + private class ProxyEventInfo { + /** The name of the method or field being proxied, e.g. "getText". */ + String memberName; + + /** The "actual" event listener for the property in question, e.g. DocumentListener. */ + ClassDescriptor listenerClass; + + /** + * In cases where a different object (such as a model) is more directly responsible for + * managing the property, this is the name of the property where that object can be + * found, e.g. "document" (which is turned into a call to "getDocument()"). This property + * is also treated as a dependency of the data binding expression, and any updates to it + * (assuming it is bound) will cause the listener to be removed from the old value and + * attached to the new value, and the data binding to be processed. + */ + String modelName; + + /** The name of the method used to add the "native" event listener, e.g. "addDocumentListener". */ + String addMethod; + + /** The name of the method used to remove the "native" event listener, e.g. "removeDocumentListener". */ + String removeMethod; + } + + + /** + * Creates a new <code>DefaultObjectHandler</code> which provides support for the specified class. The + * class is not actually introspected until the {@link #compileFirstPass} method is invoked. + * + * @param beanClass the class which this handler supports + */ + public DefaultObjectHandler(ClassDescriptor beanClass) { + this.beanClass = beanClass; + } + + + /** + * Performs introspection on the beanClass and stores the results. + * + * @throws java.beans.IntrospectionException + * TODO + */ + protected void init() throws IntrospectionException { + if (jaxxBeanInfo == null) { + // perform introspection & cache the results + jaxxBeanInfo = getJAXXBeanInfo(beanClass); + + JAXXPropertyDescriptor[] propertiesArray = jaxxBeanInfo.getJAXXPropertyDescriptors(); + properties = new HashMap<String, JAXXPropertyDescriptor>(); + for (int i = propertiesArray.length - 1; i >= 0; i--) { + properties.put(propertiesArray[i].getName(), propertiesArray[i]); + } + + JAXXEventSetDescriptor[] eventsArray = jaxxBeanInfo.getJAXXEventSetDescriptors(); + events = new HashMap<String, JAXXEventSetDescriptor>(); + for (int i = eventsArray.length - 1; i >= 0; i--) { + MethodDescriptor[] methods = eventsArray[i].getListenerMethods(); + for (MethodDescriptor method : methods) { + events.put(method.getName(), eventsArray[i]); + } + } + + configureProxyEventInfo(); + } + } + + + /** + * Returns + * + * @return the class which this <code>DefaultObjectHandler</code> supports. + */ + public ClassDescriptor getBeanClass() { + return beanClass; + } + + + /** + * @return the <code>JAXXBeanInfo</code> for the class which this <code>DefaultObjectHandler</code> + * supports. + */ + public JAXXBeanInfo getJAXXBeanInfo() { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + return jaxxBeanInfo; + } + + + /** + * Returns the <code>JAXXBeanInfo</code> for the specified class. + * + * @param beanClass the bean class for which to retrieve <code>JAXXBeanInfo</code> + * @return the class' <code>JAXXBeanInfo</code> + * @throws java.beans.IntrospectionException + * ? + */ + public static JAXXBeanInfo getJAXXBeanInfo(ClassDescriptor beanClass) throws IntrospectionException { + return JAXXIntrospector.getJAXXBeanInfo(beanClass); + } + + + /** + * Returns the type of the named property. This is the return type of the property's <code>get</code> method; + * for instance <code>JLabel</code>'s <code>text</code> property is a <code>String</code>. + * + * @param object the object being compiled + * @param propertyName the simple JavaBeans-style name of the property + * @param compiler the current <code>JAXXCompiler</code> + * @return the property's type + * @throws CompilerException if the type cannot be determined + */ + public ClassDescriptor getPropertyType(CompiledObject object, String propertyName, JAXXCompiler compiler) { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + + JAXXPropertyDescriptor property = properties.get(propertyName); + if (property != null) { + return property.getPropertyType(); + } + throw new UnsupportedAttributeException("property '" + propertyName + "' not found in " + object); + } + + + /** + * @param name ? + * @return <code>true</code> if the named member is <i>bound</i> (fires <code>PropertyChangeEvent</code> + * when modified). Members are either fields (represented by the simple name of the field) or <code>get/is</code> + * methods (represented by the simple name of the method, <b>not</b> the simplified JavaBeans-style name). + * Methods which are not actually bound in their native class, but for which proxy events have been + * configured (such as <code>JTextField.getText</code>, return <code>true</code>. + * @throws jaxx.UnsupportedAttributeException + * ? + */ + public boolean isMemberBound(String name) throws UnsupportedAttributeException { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + + if (eventInfos != null && eventInfos.containsKey(name)) { + return true; + } + + if (name.equals("getClass")) { + return false; + } + + String propertyName = null; + if (name.startsWith("get")) { + propertyName = Introspector.decapitalize(name.substring("get".length())); + } else if (name.startsWith("is")) { + propertyName = Introspector.decapitalize(name.substring("is".length())); + } + JAXXPropertyDescriptor property = propertyName != null ? properties.get(propertyName) : null; + if (property != null) { + return property.isBound(); + } + try { + FieldDescriptor field = getBeanClass().getFieldDescriptor(name); + return Modifier.isFinal(field.getModifiers()); // final fields might as well be considered bound -- they can't be modified anyway + } catch (NoSuchFieldException e) { + throw new UnsupportedAttributeException("cannot find property '" + name + "' of " + getBeanClass()); + } + } + + + private static ClassDescriptor getEventClass(ClassDescriptor listenerClass) { + return listenerClass.getMethodDescriptors()[0].getParameterTypes()[0]; + } + + + /** + * @param memberName name of the member + * @return an array of members on which the given property depends. For + * example, the JTextField.getText() member depends upon the getModel() + * member. Returns <code>null</code> if there are no dependencies. + */ + public String[] getMemberDependencies(String memberName) { + ProxyEventInfo eventInfo = eventInfos != null ? eventInfos.get(memberName) : null; + return eventInfo == null ? null : new String[]{eventInfo.modelName}; + } + + + /** + * Returns a snippet of Java code which will cause a <code>PropertyChangeListener</code> to be notified + * when the member's value changes. The <code>PropertyChangeListener</code> is provided in the form + * of a Java code snippet that evaluates to a listener object. + * <p/> + * For ordinary bound JavaBeans properties, the Java code returned is a simple call to + * <code>addPropertyChangeListener</code>. Fields and methods which do not actually fire + * <code>PropertyChangeEvents</code> when they change necessitate more complex code. + * + * @param objectCode Java code which evaluates to the object to which to add the listener + * *@param dataBinding the name of the data binding this listener is a part of + * @param dataBinding databinding + * @param memberName the name of the field or method to listen to + * @param propertyChangeListenerCode Java code which evaluates to a <code>PropertyChangeListener</code> + * @param compiler the current <code>JAXXCompiler</code> + * @return Java code snippet which causes the listener to be added to the object + */ + public String getAddMemberListenerCode(String objectCode, String dataBinding, String memberName, String propertyChangeListenerCode, JAXXCompiler compiler) { + if ("getClass".equals(memberName)) { + return null; + } + + ProxyEventInfo eventInfo = eventInfos != null ? eventInfos.get(memberName) : null; + if (eventInfo != null) { // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents + StringBuffer result = new StringBuffer(); + String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode); + boolean methodExists = compiler.hasMethod(methodName); + ClassDescriptor eventClass = getEventClass(eventInfo.listenerClass); + if (!methodExists) { + compiler.addMethodToJavaFile(new JavaMethod(Modifier.PUBLIC, "void", methodName, + new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, + propertyChangeListenerCode + ".propertyChange(null);")); + } + String code = objectCode + (eventInfo.modelName != null ? ".get" + JAXXCompiler.capitalize(eventInfo.modelName) + "()" : ""); + result.append("$bindingSources.put(\"").append(code).append("\", ").append(code).append(");").append(JAXXCompiler.getLineSeparator()); + result.append(code).append('.').append(eventInfo.addMethod).append("((").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(") jaxx.runtime.Util.getEventListener(").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(".class, ").append(compiler.getRootObject().getJavaCode()).append(", ").append(TypeManager.getJavaCode(methodName)).append("));\n"); + if (eventInfo.modelName != null) { + result.append(getAddMemberListenerCode(objectCode, dataBinding, "get" + JAXXCompiler.capitalize(eventInfo.modelName), + "jaxx.runtime.Util.getDataBindingUpdateListener(this , \"" + dataBinding + "\")", + compiler)); + } + return result.toString(); + } else { + String propertyName = null; + if (memberName.startsWith("get")) { + propertyName = Introspector.decapitalize(memberName.substring("get".length())); + } else if (memberName.startsWith("is")) { + propertyName = Introspector.decapitalize(memberName.substring("is".length())); + } + else { + try { + getBeanClass().getFieldDescriptor(memberName); + propertyName = memberName; + } catch (NoSuchFieldException e) { + // ignore ? + } + } + if (propertyName != null) { + try { + // check for property-specific addPropertyChangeListener method + getBeanClass().getMethodDescriptor("addPropertyChangeListener", new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(String.class), + ClassDescriptorLoader.getClassDescriptor(PropertyChangeListener.class)}); + return objectCode + ".addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; + } catch (NoSuchMethodException e) { + // no property-specific method, use general one + return objectCode + ".addPropertyChangeListener(" + propertyChangeListenerCode + ");\n"; + } + } + return null; + } + } + + + public String getRemoveMemberListenerCode(String objectCode, String dataBinding, String memberName, String propertyChangeListenerCode, JAXXCompiler compiler) { + if ("getClass".equals(memberName)) { + return null; + } + + ProxyEventInfo eventInfo = eventInfos != null ? eventInfos.get(memberName) : null; + if (eventInfo != null) { // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents + StringBuffer result = new StringBuffer(); + String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode); + boolean methodExists = compiler.hasMethod(methodName); + if (!methodExists) { + ClassDescriptor eventClass = getEventClass(eventInfo.listenerClass); + compiler.addMethodToJavaFile(new JavaMethod(Modifier.PUBLIC, "void", methodName, + new JavaArgument[]{new JavaArgument(JAXXCompiler.getCanonicalName(eventClass), "event")}, null, + propertyChangeListenerCode + ".propertyChange(null);")); + } + try { + String modelMemberName = eventInfo.modelName != null ? "get" + JAXXCompiler.capitalize(eventInfo.modelName) : null; + String modelClassName = modelMemberName != null ? getBeanClass().getMethodDescriptor(modelMemberName, new ClassDescriptor[0]).getReturnType().getName() : JAXXCompiler.getCanonicalName(getBeanClass()); + String code = objectCode + (eventInfo.modelName != null ? "." + modelMemberName + "()" : ""); + result.append("((").append(modelClassName).append(") $bindingSources.remove(\"").append(code).append("\")).").append(eventInfo.removeMethod).append("((").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(") jaxx.runtime.Util.getEventListener(").append(JAXXCompiler.getCanonicalName(eventInfo.listenerClass)).append(".class, ").append(compiler.getRootObject().getJavaCode()).append(", ").append(TypeManager.getJavaCode(methodName)).append("));\n"); + if (eventInfo.modelName != null) { + result.append(getRemoveMemberListenerCode(objectCode, dataBinding, "get" + JAXXCompiler.capitalize(eventInfo.modelName), + "jaxx.runtime.Util.getDataBindingUpdateListener(this, \"" + dataBinding + "\")", + compiler)); + } + return result.toString(); + } + catch (NoSuchMethodException e) { + throw new CompilerException("Internal error: " + e); + } + } else { + String propertyName = null; + if (memberName.startsWith("get")) { + propertyName = Introspector.decapitalize(memberName.substring("get".length())); + } else if (memberName.startsWith("is")) { + propertyName = Introspector.decapitalize(memberName.substring("is".length())); + } else { + try { + getBeanClass().getFieldDescriptor(memberName); + propertyName = memberName; + } catch (NoSuchFieldException e) { + // ignore ? + } + } + if (propertyName != null) { + try { + // check for property-specific removePropertyChangeListener method + getBeanClass().getMethodDescriptor("removePropertyChangeListener", new ClassDescriptor[]{ClassDescriptorLoader.getClassDescriptor(String.class), + ClassDescriptorLoader.getClassDescriptor(PropertyChangeListener.class)}); + return objectCode + ".removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; + } catch (NoSuchMethodException e) { + // no property-specific method, use general one + return objectCode + ".removePropertyChangeListener(" + propertyChangeListenerCode + ");\n"; + } + } + return null; + } + } + + + /** + * Configures the event handling for members which do not fire <code>PropertyChangeEvent</code> when + * modified. The default implementation does nothing. Subclasses should override this method to call + * <code>addProxyEventInfo</code> for each member which requires special handling. + */ + protected void configureProxyEventInfo() { + } + + + /** + * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound + * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are + * not bound property <code>get</code> methods. The proxy event handler will attach the specified kind + * of listener to the class and fire a <code>PropertyChangeEvent</code> whenever the listener receives + * any kind of event. + * <p/> + * Even though this method can theoretically be applied to fields (in addition to methods), it would be an + * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would + * be difficult to have a listener that was always notified when a field value changed. + * + * @param memberName the name of the field or method being proxied + * @param listenerClass the type of listener which receives events when the field or method is updated + */ + public void addProxyEventInfo(String memberName, Class listenerClass) { + addProxyEventInfo(memberName, listenerClass, null); + } + + + /** + * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound + * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are + * not bound property <code>get</code> methods. This variant attaches a listener to a property of the + * object (such as <code>model</code>) and not the object itself, which is useful when there is a model + * that is the "real" container of the information. The proxy event handler will attach the specified kind + * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire + * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. + * <p/> + * If the property is itself bound (typically the case with models), any updates to the property's value will + * cause the listener to be removed from the old property value and reattached to the new property value, + * as well as cause a <code>PropertyChangeEvent</code> to be fired. + * <p/> + * Even though this method can theoretically be applied to fields (in addition to methods), it would be an + * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would + * be difficult to have a listener that was always notified when a field value changed. + * + * @param memberName the name of the field or method being proxied + * @param listenerClass the type of listener which receives events when the field or method is updated + * @param modelName the JavaBeans-style name of the model property + */ + public void addProxyEventInfo(String memberName, Class listenerClass, String modelName) { + String listenerName = listenerClass.getName(); + listenerName = listenerName.substring(listenerName.lastIndexOf(".") + 1); + addProxyEventInfo(memberName, listenerClass, modelName, "add" + listenerName, "remove" + listenerName); + } + + + // TODO: remove this temporary method, complete switchover to ClassDescriptors + public void addProxyEventInfo(String memberName, Class listenerClass, + String modelName, String addMethod, String removeMethod) { + try { + addProxyEventInfo(memberName, ClassDescriptorLoader.getClassDescriptor(listenerClass.getName()), modelName, addMethod, removeMethod); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + + /** + * Configures a proxy event handler which fires <code>PropertyChangeEvents</code> when a non-bound + * member is updated. This is necessary for all fields (which cannot be bound) and for methods that are + * not bound property <code>get</code> methods. This variant attaches a listener to a property of the + * object (such as <code>model</code>) and not the object itself, which is useful when there is a model + * that is the "real" container of the information. The proxy event handler will attach the specified kind + * of listener to the property's value (retrieved using the property's <code>get</code> method) and fire + * a <code>PropertyChangeEvent</code> whenever the listener receives any kind of event. + * <p/> + * If the property is itself bound (typically the case with models), any updates to the property's value will + * cause the listener to be removed from the old property value and reattached to the new property value, + * as well as cause a <code>PropertyChangeEvent</code> to be fired. + * <p/> + * This variant of <code>addProxyEventInfo</code> allows the names of the methods that add and remove + * the event listener to be specified, in cases where the names are not simply <code>add<listenerClassName></code> + * and <code>remove<listenerClassName></code>. + * <p/> + * Even though this method can theoretically be applied to fields (in addition to methods), it would be an + * unusual situation in which that would actually work -- as fields cannot fire events when modified, it would + * be difficult to have a listener that was always notified when a field value changed. + * + * @param memberName the name of the field or method being proxied + * @param listenerClass the type of listener which receives events when the field or method is updated + * @param modelName the JavaBeans-style name of the model property + * @param addMethod add method name + * @param removeMethod remove method name + */ + public void addProxyEventInfo(String memberName, ClassDescriptor listenerClass, + String modelName, String addMethod, String removeMethod) { + ProxyEventInfo info = new ProxyEventInfo(); + info.memberName = memberName; + info.listenerClass = listenerClass; + info.modelName = modelName; + info.addMethod = addMethod; + info.removeMethod = removeMethod; + if (eventInfos == null) { + eventInfos = new HashMap<String, ProxyEventInfo>(); + } + eventInfos.put(memberName, info); + } + + + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + scanAttributesForDependencies(tag, compiler); + compileChildrenFirstPass(tag, compiler); + } + + + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + CompiledObject object = objectMap.get(tag); + if (object == null) { + throw new IllegalStateException("unable to find CompiledObject associated with tag <" + tag.getTagName() + ">; should have been registered before second pass"); + } + compiler.checkOverride(object); + String constructorParams = tag.getAttribute("constructorParams"); + if (constructorParams != null && constructorParams.length() > 0) { + object.setConstructorParams(compiler.getScriptManager().trimScript(constructorParams)); + } + + setDefaults(object, tag, compiler); + setAttributes(object, tag, compiler); + + compileChildrenSecondPass(tag, compiler); + } + + + public void registerCompiledObject(Element tag, JAXXCompiler compiler) { + String id = tag.getAttribute("id"); + if (id == null || id.length() == 0) { + id = compiler.getAutoId(getBeanClass()); + } + CompiledObject object = createCompiledObject(id, compiler); + objectMap.put(tag, object); + String styleClass = tag.getAttribute("styleClass").trim(); + if (styleClass.length() > 0) { + object.setStyleClass(styleClass); + } + compiler.registerCompiledObject(object); + } + + + /** + * Creates the <code>CompiledObject</code> which will represent the object created by this <code>TagHandler</code>. + * + * @param id the <code>CompiledObject's</code> ID. + * @param compiler compiler to use + * @return the <code>CompiledObject</code> to use + */ + protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) { + return new CompiledObject(id, getBeanClass(), compiler); + } + + + /** + * Initializes the default settings of the object, prior to setting its attribute values. The default + * implementation does nothing. + * + * @param object the object to initialize + * @param tag the tag being compiled + * @param compiler the current <code>JAXXCompiler</code> + */ + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) { + } + + + /** + * @param property property name to test + * @return <code>true</code> if the specified property should be inherited by child components when specified + * via CSS. + * @throws jaxx.UnsupportedAttributeException + * ? + */ + public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { + return false; + } + + + /** + * @param name name of event + * @return <code>true</code> if the specified name has the form of an event handler attribute + * (e.g. "onActionPerformed"). + */ + public boolean isEventHandlerName(String name) { + return name.length() > 2 && name.startsWith("on") && Character.isUpperCase(name.charAt(2)); + } + + + /** + * Scans all attributes for any dependency classes and adds them to the current compilation + * set. Called by <code>compileFirstPass()</code> (it is an error to add dependencies after + * pass 1 is complete). + * + * @param tag tag to scan + * @param compiler compiler to use + */ + protected void scanAttributesForDependencies(Element tag, JAXXCompiler compiler) { + List<Attr> attributes = new ArrayList<Attr>(); + NamedNodeMap children = tag.getAttributes(); + for (int i = 0; i < children.getLength(); i++) { + attributes.add((Attr) children.item(i)); + } + Collections.sort(attributes, getAttributeComparator()); + + for (Attr attribute : attributes) { + String name = attribute.getName(); + String value = attribute.getValue(); + if (name.equals("constraints") || isEventHandlerName(name)) { + compiler.preprocessScript(value); // adds dependencies as a side effect + } else if (name.equals("constructorParams")) { + for (String param : value.split("\\s*,\\s*")) { + compiler.preprocessScript(param); + } + } else if (value.startsWith("{") && value.endsWith("}")) { + compiler.preprocessScript(value.substring(1, value.length() - 1)); + } + } + } + + + /** + * Processes the attributes of an XML tag. Four kinds of attributes are supported: simple property values (of any + * datatype supported by {@link #convertFromString}), data binding expressions (attributes containing curly-brace + * pairs), event listeners (attributes starting with 'on', such as 'onActionPerformed'), and JAXX-defined properties + * such as 'id'. + * + * @param object the object to be modified + * @param tag the tag from which to pull attributes + * @param compiler the current <code>JAXXCompiler</code> + */ + public void setAttributes(CompiledObject object, Element tag, JAXXCompiler compiler) { + List<Attr> attributes = new ArrayList<Attr>(); + NamedNodeMap children = tag.getAttributes(); + for (int i = 0; i < children.getLength(); i++) { + attributes.add((Attr) children.item(i)); + } + Collections.sort(attributes, getAttributeComparator()); + + for (Attr attribute : attributes) { + String name = attribute.getName(); + String value = attribute.getValue().trim(); + if (name.equals("id") || name.equals("constraints") || name.equals("constructorParams") || name.equals("styleClass") || + name.startsWith("xmlns") || JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + // ignore, already handled + } else if (isEventHandlerName(name)) { + if (!value.endsWith(";")) { + value+=";"; + } + addEventHandler(object, Introspector.decapitalize(name.substring(2)), value, compiler); + } else { + setAttribute(object, name, value, true, compiler); + } + } + } + + + /** + * Returns a <code>Comparator</code> which defines the ordering in which the tag's attributes should be processed. The + * default implementation sorts the attributes according to the order defined by the {@link #getAttributeOrdering} method. + * + * @return a <code>Comparator</code> defining the order of attribute processing + */ + protected Comparator<Attr> getAttributeComparator() { + return new Comparator<Attr>() { + public int compare(Attr a, Attr b) { + int aOrder = getAttributeOrdering(a); + int bOrder = getAttributeOrdering(b); + + return aOrder - bOrder; + } + }; + } + + + /** + * Returns the priority with which a particular attribute should be processed. Lower numbers should be processed before + * higher numbers. This value is used by the {@link #getAttributeComparator} method to define the sort ordering. + * + * @param attr the attribute to treate + * @return the attribute's priority + */ + protected int getAttributeOrdering(Attr attr) { + if (attr.getName().equals("displayedMnemonicIndex") || attr.getName().equals("displayedMnemonic") || attr.getName().equals("mnemonic")) { + return 1; + } + return 0; + } + + + public String getApplyPropertyOrDataBindingCode(CompiledObject object, String propertyName, String stringValue, JAXXCompiler compiler) { + ClassDescriptor type = getPropertyType(object, propertyName, compiler); + String binding = compiler.processDataBindings(stringValue, type); + if (binding != null) { + return ""; + } + try { + Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; + Object value = convertFromString(propertyName, stringValue, typeClass); + return getSetPropertyCode(object.getJavaCode(), propertyName, TypeManager.getJavaCode(value), compiler); + } catch (NumberFormatException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (IllegalArgumentException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (ClassNotFoundException e) { + compiler.reportError("could not find class " + type.getName()); + } + return ""; + } + + + /** + * Set a single property on an object. The value may be either a simple value or contain data binding expressions. + * Simple values are first converted to the property's type using {@link #convertFromString}. + * + * @param object the object on which to set the property + * @param propertyName the name of the property to set + * @param stringValue the raw string value of the property from the XML + * @param inline <code>true</code> if the value was directly specified as an inline class tag attribute, <code>false</code> otherwise (a default value, specified in CSS, etc.) + * @param compiler the current <code>JAXXCompiler</code> + */ + public void setAttribute(CompiledObject object, String propertyName, String stringValue, boolean inline, JAXXCompiler compiler) { + try { + if (ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(object.getObjectClass())) { + // check for data binding & remove if found + JAXXObjectDescriptor jaxxObjectDescriptor = object.getObjectClass().getJAXXObjectDescriptor(); + ComponentDescriptor root = jaxxObjectDescriptor.getComponentDescriptors()[0]; + object.appendInitializationCode(object.getJavaCode() + ".removeDataBinding(" + TypeManager.getJavaCode(root.getId() + "." + propertyName) + ");" + JAXXCompiler.getLineSeparator()); + } + object.addProperty(propertyName, stringValue); + ClassDescriptor type = getPropertyType(object, propertyName, compiler); + String binding = compiler.processDataBindings(stringValue, type); + if (binding != null) { + if (inline) { + compiler.addInlineStyle(object, propertyName, true); + } + ClassDescriptor propertyType = getPropertyType(object, propertyName, compiler); + if (propertyType != null && + propertyType != ClassDescriptorLoader.getClassDescriptor(Boolean.class) && + propertyType != ClassDescriptorLoader.getClassDescriptor(Byte.class) && + propertyType != ClassDescriptorLoader.getClassDescriptor(Short.class) && + propertyType != ClassDescriptorLoader.getClassDescriptor(Integer.class) && + propertyType != ClassDescriptorLoader.getClassDescriptor(Float.class) && + propertyType != ClassDescriptorLoader.getClassDescriptor(Double.class) && + propertyType != ClassDescriptorLoader.getClassDescriptor(Character.class)) { + //binding = "((" + propertyType.getName() + ") " + binding + ")"; + } + if (propertyName.equals("layout")) { // handle containerDelegate (e.g. contentPane on JFrame) + // have to set layout early, before children are added + object.appendInitializationCode(getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler)); + } + object.registerDataBinding(binding, propertyName, getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler), compiler); + } else { // no bindings, convert from string + if (inline) { + compiler.addInlineStyle(object, propertyName, false); + } + try { + Class typeClass = type != null ? ClassDescriptorLoader.getClass(type.getName(), type.getClassLoader()) : null; + Object value = convertFromString(propertyName, stringValue, typeClass); + setProperty(object, propertyName, value, compiler); + } catch (NumberFormatException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (IllegalArgumentException e) { + compiler.reportError("could not convert literal string '" + stringValue + "' to type " + type.getName()); + } catch (ClassNotFoundException e) { + compiler.reportError("could not find class " + type.getName()); + } + } + } catch (UnsupportedAttributeException e) { + compiler.reportError("class " + object.getObjectClass().getName() + " does not support attribute '" + propertyName + "'"); + } + } + + + public void applyStylesheets(CompiledObject object, JAXXCompiler compiler) { + applyStylesheets(object, compiler, null); + } + + + private void applyStylesheets(final CompiledObject object, JAXXCompiler compiler, Stylesheet overrides) { + applyStylesheets(object, compiler, overrides, true); + } + + + private void applyStylesheets(final CompiledObject object, JAXXCompiler compiler, Stylesheet overrides, boolean recurse) { + try { + Stylesheet stylesheet = compiler.getStylesheet(); + ClassDescriptor objectClass = object.getObjectClass(); + if (recurse && ClassDescriptorLoader.getClassDescriptor(JAXXObject.class).isAssignableFrom(objectClass)) { + JAXXObjectDescriptor jaxxObjectDescriptor = objectClass.getJAXXObjectDescriptor(); + ComponentDescriptor[] descriptors = jaxxObjectDescriptor.getComponentDescriptors(); + for (ComponentDescriptor descriptor : descriptors) { + ClassDescriptor classDescriptor = ClassDescriptorLoader.getClassDescriptor(descriptor.getJavaClassName()); + boolean isRoot = classDescriptor != objectClass; + String id = isRoot ? object.getId() + ' ' + descriptor.getId() : "( " + object.getId() + " ) " + descriptor.getId(); + CompiledObject child = new CompiledObject(id, + "((" + JAXXCompiler.getCanonicalName(classDescriptor) + ") " + + object.getJavaCode() + ".getObjectById(" + TypeManager.getJavaCode(descriptor.getId()) + "))", + classDescriptor, + compiler, + true); + ComponentDescriptor parentDescriptor = descriptor.getParent(); + CompiledObject currentObject = child; + while (parentDescriptor != null) { + CompiledObject parent = new CompiledObject("internal", ClassDescriptorLoader.getClassDescriptor(parentDescriptor.getJavaClassName()), compiler); + currentObject.setParent(parent); + currentObject = parent; + parentDescriptor = parentDescriptor.getParent(); + } + currentObject.setParent(object); + String styleClass = object.getStyleClass(); + if (styleClass == null) { + styleClass = descriptor.getStyleClass(); + } + child.setStyleClass(styleClass); + Stylesheet mergedStylesheet = overrides; + Stylesheet childOverrides = jaxxObjectDescriptor.getStylesheet(); + if (childOverrides != null) { + if (mergedStylesheet == null) { + mergedStylesheet = childOverrides; + } else { + mergedStylesheet.add(childOverrides.getRules()); + } + } + TagManager.getTagHandler(objectClass).applyStylesheets(child, compiler, mergedStylesheet, isRoot); + object.appendInitializationCode(child.getInitializationCode(compiler)); + } + } else if (stylesheet != null) + stylesheet.applyTo(object, compiler, overrides); + } + catch (ClassNotFoundException e) { + throw new CompilerException(e); + } catch (IllegalArgumentException e) { + compiler.reportError(e.getMessage()); + } + } + + + /** + * Adds the necessary Java code to a <code>CompiledObject</code> to add an event listener at runtime. + * + * @param object the <code>CompiledObject</code> to which the event listener should be added + * @param name the name of the event listener, such as <code>"actionPerformed"</code> + * @param value the Java code snippet to execute when the event is fired + * @param compiler the current <code>JAXXCompiler</code> + */ + public void addEventHandler(CompiledObject object, String name, String value, JAXXCompiler compiler) { + JAXXEventSetDescriptor JAXXEventSetDescriptor = events.get(name); + if (JAXXEventSetDescriptor != null) { + MethodDescriptor[] listenerMethods = JAXXEventSetDescriptor.getListenerMethods(); + MethodDescriptor listenerMethod = null; + for (MethodDescriptor listenerMethod1 : listenerMethods) { + if (listenerMethod1.getName().equals(name)) { + listenerMethod = listenerMethod1; + break; + } + } + if (listenerMethod == null) { + throw new RuntimeException("expected to find method '" + name + "' in JAXXEventSetDescriptor.getListenerMethods()"); + } + try { + value = compiler.preprocessScript(value); + object.addEventHandler(name, JAXXEventSetDescriptor.getAddListenerMethod(), listenerMethod, value, compiler); + } catch (CompilerException e) { + compiler.reportError("While parsing event handler for '" + name + "': " + e.getMessage()); + } + } else + compiler.reportError("could not find event '" + name + "' for object " + object); + } + + + /** + * Returns a snippet of Java code which will retrieve an object property at runtime. Typically the code is + * just a call to the property's <code>get</code> method, but it can be arbitrarily complex. + * + * @param javaCode Java code for the object whose property is being retrieved + * @param name the name of the property to retrieve + * @param compiler the current <code>JAXXCompiler</code> + * @return the snippet + * @throws CompilerException if a compilation error occurs + */ + public String getGetPropertyCode(String javaCode, String name, JAXXCompiler compiler) { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + + JAXXPropertyDescriptor property = properties.get(name); + if (property != null) { + if (property.getReadMethodDescriptor() != null) { + return javaCode + '.' + property.getReadMethodDescriptor().getName() + "()"; + } + throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " has no read method"); + } + throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); + } + + + /** + * Returns a snippet of Java code which will set an object property at runtime. Typically the code is + * just a call to the property's <code>set</code> method, but it can be arbitrarily complex. + * + * @param javaCode Java code for the object whose property is being set + * @param name the name of the property to set + * @param valueCode Java expression representing the value to set the property to + * @param compiler the current <code>JAXXCompiler</code> + * @return the snippet + * @throws CompilerException if a compilation error occurs + */ + public String getSetPropertyCode(String javaCode, String name, String valueCode, JAXXCompiler compiler) { + JAXXPropertyDescriptor property = properties.get(name); + if (property != null) { + if (property.getWriteMethodDescriptor() != null) { + return javaCode + '.' + property.getWriteMethodDescriptor().getName() + '(' + valueCode + ");"; + } + throw new UnsupportedAttributeException("property '" + name + "' of " + getBeanClass().getName() + " is read-only"); + } + throw new UnsupportedAttributeException("property '" + name + "' could not be found in class " + getBeanClass().getName()); + } + + + /** + * Appends Java code to a <code>CompiledObject</code> in order to implement a property assignment. + * <code>setProperty</code> is invoked in response to most XML attributes (those which are not more + * complicated cases, like data bindings or event handlers). + * <p/> + * By the time it reaches this method, the <code>value</code> has already been converted from its XML + * string representation to the appropriate destination type for the property (i.e. if + * <code>JLabel.foreground</code> is being set, <code>value</code> will be a <code>Color</code>). + * + * @param object the object being modified + * @param name the name of the property to set + * @param value the value to set the property to + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + */ + public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) { + object.appendInitializationCode(getSetPropertyCode(object.getJavaCode(), name, TypeManager.getJavaCode(value), compiler)); + } + + + /** + * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For + * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and + * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. + * <p/> + * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an + * int-valued property has a value which is not a valid number. By default, this method looks at the + * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. + * + * @param key the name of the int-typed property + * @param value the non-numeric value that was specified for the property + * @return the constant integer value + * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid + * @throws NumberFormatException if the property is not an enumeration + */ + protected int constantValue(String key, String value) { + JAXXBeanInfo JAXXBeanInfo = getJAXXBeanInfo(); + JAXXPropertyDescriptor[] properties = JAXXBeanInfo.getJAXXPropertyDescriptors(); + String lowercaseValue = value.toLowerCase(); + for (JAXXPropertyDescriptor property : properties) { + if (property.getName().equals(key)) { + Object[] values = (Object[]) property.getValue("enumerationValues"); + if (values != null) { + for (int j = 0; j < values.length - 2; j += 3) { + if (((String) values[j]).toLowerCase().equals(lowercaseValue)) { + return (Integer) values[j + 1]; + } + } + + StringBuffer message = new StringBuffer("value of '" + key + "' must be one of: ["); + for (int j = 0; j < values.length - 2; j += 3) { + if (j != 0) { + message.append(", "); + } + message.append(((String) values[j]).toLowerCase()); + } + message.append("] (found '").append(value).append("')"); + throw new IllegalArgumentException(message.toString()); + } + } + } + throw new NumberFormatException(value); + } + + + /** + * As {@link TypeManager#convertFromString(String, Class)}, except that it additionally supports constant names + * for <code>int</code>-valued types. + * + * @param key the name of the property whose value is being converted + * @param value the raw string value of the property as it appears in the XML + * @param type the datatype to convert the string into + * @return the converted object + * @see #constantValue + */ + protected Object convertFromString(String key, String value, Class type) { + if (type == null || type == Object.class) { + return value; + } + + try { + return TypeManager.convertFromString(value, type); + } catch (NumberFormatException e) { + if (type == int.class || type == Integer.class) { + return constantValue(key, value); + } + throw e; + } + } + + + /** + * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} + * for each child tag. + * + * @param tag the tag whose children to compile + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildrenFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagFirstPass(child, compiler); + } + } + } + + + /** + * Compiles the child tags of the current tag. The default implementation invokes {@link #compileChildTagFirstPass} + * for each child tag. + * + * @param tag the tag whose children to compile + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + Element child = (Element) node; + compileChildTagSecondPass(child, compiler); + } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + String text = ((Text) node).getData().trim(); + if (text.length() > 0) { + compiler.reportError("tag '" + tag.getLocalName() + "' may not contain text ('" + ((Text) node).getData().trim() + "')"); + } + } + } + } + + + /** + * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass + * JAXXCompiler.compileFirstPass}. + * + * @param tag the child tag to compile + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + + /** + * Compiles a child of the current tag. The default implementation calls {@link JAXXCompiler#compileFirstPass + * JAXXCompiler.compileSecondPass}. + * + * @param tag the child tag to compile + * @param compiler the current <code>JAXXCompiler</code> + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } + + @Override + public String toString() { + return getClass().getName() + "[" + getBeanClass().getName() + "]"; + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,175 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags; - -import jaxx.CompilerException; -import jaxx.UnsupportedAttributeException; -import jaxx.compiler.JAXXCompiler; -import jaxx.css.CSSParser; -import jaxx.css.CSSParserConstants; -import jaxx.css.CSSParserTreeConstants; -import jaxx.css.Rule; -import jaxx.css.Selector; -import jaxx.css.SimpleNode; -import jaxx.css.Stylesheet; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Handles the <code><style></code> tag. - * - * @author Ethan Nicholas - */ -public class StyleHandler implements TagHandler { - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - boolean source = false; - NamedNodeMap attributes = tag.getAttributes(); - for (int i = 0; i < attributes.getLength(); i++) { - Attr attribute = (Attr) attributes.item(i); - String name = attribute.getName(); - String attrValue = attribute.getValue(); - if (name.equals("source")) { - source = true; - File styleFile = new File(compiler.getBaseDir(), attrValue.replace('/', File.separatorChar)); - StringWriter styleBuffer = new StringWriter(); - try { - FileReader in = new FileReader(styleFile); - char[] readBuffer = new char[2048]; - int c; - while ((c = in.read(readBuffer)) > 0) - styleBuffer.write(readBuffer, 0, c); - } - catch (FileNotFoundException e) { - compiler.reportError("stylesheet file not found: " + styleFile); - } - compiler.getSourceFiles().push(styleFile); - compiler.registerStylesheet(processStylesheet(styleBuffer.toString())); - compiler.getSourceFiles().pop(); - } else - if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) - throw new UnsupportedAttributeException(name); - } - - StringBuffer style = new StringBuffer(); - NodeList children = tag.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - switch (child.getNodeType()) { - case Node.ELEMENT_NODE: - compiler.reportError("<style> tag may not contain child elements: " + tag); - case Node.TEXT_NODE: // fall through - case Node.CDATA_SECTION_NODE: - style.append(((Text) child).getData()); - } - } - - String styleString = style.toString().trim(); - if (styleString.length() > 0) { - if (source) - compiler.reportError("<style> tag has both a source attribute and an inline stylesheet"); - compiler.registerStylesheet(processStylesheet(style.toString())); - } - } - - - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - } - - - protected Selector processSelector(SimpleNode selector) { - if (selector.getId() != CSSParserTreeConstants.JJTSELECTOR) - throw new IllegalArgumentException("argument node is not a Selector"); - String javaClassName = null; - String styleClass = null; - String pseudoClass = null; - String id = null; - - for (int i = 0; i < selector.jjtGetNumChildren(); i++) { - SimpleNode child = selector.getChild(i); - switch (child.getId()) { - case CSSParserTreeConstants.JJTJAVACLASS: - if (!child.getText().trim().equals("*")) - javaClassName = child.getText(); - break; - case CSSParserTreeConstants.JJTCLASS: - styleClass = child.getText().substring(1); - break; - case CSSParserTreeConstants.JJTPSEUDOCLASS: - pseudoClass = child.getText().substring(1); - break; - case CSSParserTreeConstants.JJTID: - id = child.getText().substring(1); - break; - - default: - throw new IllegalStateException("unexpected child of Selector node, type=" + child.getId()); - } - } - - return new Selector(javaClassName, styleClass, pseudoClass, id); - } - - - protected Rule processRule(SimpleNode ruleNode) { - if (ruleNode.getId() != CSSParserTreeConstants.JJTRULE) { - throw new IllegalArgumentException("argument node is not a Rule"); - } - SimpleNode selectorsNode = ruleNode.getChild(0); - assert selectorsNode.getId() == CSSParserTreeConstants.JJTSELECTORS : "expected node to be of type Selectors"; - - List<Selector> selectors = new ArrayList<Selector>(); - for (int i = 0; i < selectorsNode.jjtGetNumChildren(); i++) { - SimpleNode selectorNode = selectorsNode.getChild(i); - selectors.add(processSelector(selectorNode)); - } - - Map<String, String> properties = new HashMap<String, String>(); - for (int i = 1; i < ruleNode.jjtGetNumChildren(); i++) { - SimpleNode declarationNode = ruleNode.getChild(i); - if (declarationNode.getId() == CSSParserTreeConstants.JJTDECLARATION) { - String key = declarationNode.getChild(0).getText(); - SimpleNode valueNode = declarationNode.getChild(1); - String value = valueNode.getText(); - if (valueNode.firstToken.kind == CSSParserConstants.STRING) { - value = value.substring(1, value.length() - 1); - } - properties.put(key, value); - } - } - Rule rule; - rule = new Rule(selectors.toArray(new Selector[selectors.size()]), properties); - return rule; - } - - - protected Stylesheet processStylesheet(String stylesheetText) throws CompilerException { - CSSParser p = new CSSParser(new StringReader(stylesheetText)); - SimpleNode node = p.Stylesheet(); - List<Rule> rules = new ArrayList<Rule>(); - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - SimpleNode ruleNode = node.getChild(i); - Rule rule = processRule(ruleNode); - rules.add(rule); - } - Stylesheet stylesheet; - stylesheet = new Stylesheet(rules.toArray(new Rule[rules.size()])); - return stylesheet; - } -} Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java (from rev 965, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/StyleHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,181 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags; + +import jaxx.CompilerException; +import jaxx.UnsupportedAttributeException; +import jaxx.compiler.JAXXCompiler; +import jaxx.css.CSSParser; +import jaxx.css.CSSParserConstants; +import jaxx.css.CSSParserTreeConstants; +import jaxx.css.Rule; +import jaxx.css.Selector; +import jaxx.css.SimpleNode; +import jaxx.css.Stylesheet; +import jaxx.css.ParseException; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Handles the <code><style></code> tag. + * + * @author Ethan Nicholas + */ +public class StyleHandler implements TagHandler { + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + boolean source = false; + NamedNodeMap attributes = tag.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attribute = (Attr) attributes.item(i); + String name = attribute.getName(); + String attrValue = attribute.getValue(); + if (name.equals("source")) { + source = true; + File styleFile = new File(compiler.getBaseDir(), attrValue.replace('/', File.separatorChar)); + StringWriter styleBuffer = new StringWriter(); + try { + FileReader in = new FileReader(styleFile); + char[] readBuffer = new char[2048]; + int c; + while ((c = in.read(readBuffer)) > 0) + styleBuffer.write(readBuffer, 0, c); + } + catch (FileNotFoundException e) { + compiler.reportError("stylesheet file not found: " + styleFile); + } + compiler.getSourceFiles().push(styleFile); + compiler.registerStylesheet(processStylesheet(styleBuffer.toString())); + compiler.getSourceFiles().pop(); + } else + if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) + throw new UnsupportedAttributeException(name); + } + + StringBuffer style = new StringBuffer(); + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.ELEMENT_NODE: + compiler.reportError("<style> tag may not contain child elements: " + tag); + case Node.TEXT_NODE: // fall through + case Node.CDATA_SECTION_NODE: + style.append(((Text) child).getData()); + } + } + + String styleString = style.toString().trim(); + if (styleString.length() > 0) { + if (source) + compiler.reportError("<style> tag has both a source attribute and an inline stylesheet"); + compiler.registerStylesheet(processStylesheet(style.toString())); + } + } + + + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + } + + + protected Selector processSelector(SimpleNode selector) { + if (selector.getId() != CSSParserTreeConstants.JJTSELECTOR) + throw new IllegalArgumentException("argument node is not a Selector"); + String javaClassName = null; + String styleClass = null; + String pseudoClass = null; + String id = null; + + for (int i = 0; i < selector.jjtGetNumChildren(); i++) { + SimpleNode child = selector.getChild(i); + switch (child.getId()) { + case CSSParserTreeConstants.JJTJAVACLASS: + if (!child.getText().trim().equals("*")) + javaClassName = child.getText(); + break; + case CSSParserTreeConstants.JJTCLASS: + styleClass = child.getText().substring(1); + break; + case CSSParserTreeConstants.JJTPSEUDOCLASS: + pseudoClass = child.getText().substring(1); + break; + case CSSParserTreeConstants.JJTID: + id = child.getText().substring(1); + break; + + default: + throw new IllegalStateException("unexpected child of Selector node, type=" + child.getId()); + } + } + + return new Selector(javaClassName, styleClass, pseudoClass, id); + } + + + protected Rule processRule(SimpleNode ruleNode) { + if (ruleNode.getId() != CSSParserTreeConstants.JJTRULE) { + throw new IllegalArgumentException("argument node is not a Rule"); + } + SimpleNode selectorsNode = ruleNode.getChild(0); + assert selectorsNode.getId() == CSSParserTreeConstants.JJTSELECTORS : "expected node to be of type Selectors"; + + List<Selector> selectors = new ArrayList<Selector>(); + for (int i = 0; i < selectorsNode.jjtGetNumChildren(); i++) { + SimpleNode selectorNode = selectorsNode.getChild(i); + selectors.add(processSelector(selectorNode)); + } + + Map<String, String> properties = new HashMap<String, String>(); + for (int i = 1; i < ruleNode.jjtGetNumChildren(); i++) { + SimpleNode declarationNode = ruleNode.getChild(i); + if (declarationNode.getId() == CSSParserTreeConstants.JJTDECLARATION) { + String key = declarationNode.getChild(0).getText(); + SimpleNode valueNode = declarationNode.getChild(1); + String value = valueNode.getText(); + if (valueNode.firstToken.kind == CSSParserConstants.STRING) { + value = value.substring(1, value.length() - 1); + } + properties.put(key, value); + } + } + Rule rule; + rule = new Rule(selectors.toArray(new Selector[selectors.size()]), properties); + return rule; + } + + + protected Stylesheet processStylesheet(String stylesheetText) throws CompilerException { + CSSParser p = new CSSParser(new StringReader(stylesheetText)); + SimpleNode node; + try { + node = p.Stylesheet(); + } catch (Error e) { + throw new CompilerException(e); + } + List<Rule> rules = new ArrayList<Rule>(); + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode ruleNode = node.getChild(i); + Rule rule = processRule(ruleNode); + rules.add(rule); + } + Stylesheet stylesheet; + stylesheet = new Stylesheet(rules.toArray(new Rule[rules.size()])); + return stylesheet; + } +} Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,41 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.swing; - -import jaxx.CompilerException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.runtime.swing.Application; -import jaxx.types.TypeManager; -import org.w3c.dom.Element; - -import javax.swing.WindowConstants; - -public class ApplicationHandler extends JWindowHandler { - - public ApplicationHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, Application.class); - } - - - @Override - public void setAttribute(CompiledObject object, String propertyName, String stringValue, boolean inline, JAXXCompiler compiler) throws CompilerException { - if (propertyName.equals("lookAndFeel") && stringValue != null && !stringValue.trim().startsWith("{")) { - compiler.bodyCode.append("{ ").append(object.getJavaCode()).append(".setLookAndFeel(").append(TypeManager.getJavaCode(stringValue)).append("); }").append(JAXXCompiler.getLineSeparator()); - } else { - super.setAttribute(object, propertyName, stringValue, inline, compiler); - } - } - - - @Override - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - setAttribute(object, "defaultCloseOperation", String.valueOf(WindowConstants.EXIT_ON_CLOSE), false, compiler); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/ApplicationHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,41 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags.swing; + +import jaxx.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.runtime.swing.Application; +import jaxx.types.TypeManager; +import org.w3c.dom.Element; + +import javax.swing.WindowConstants; + +public class ApplicationHandler extends JWindowHandler { + + public ApplicationHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, Application.class); + } + + + @Override + public void setAttribute(CompiledObject object, String propertyName, String stringValue, boolean inline, JAXXCompiler compiler) throws CompilerException { + if (propertyName.equals("lookAndFeel") && stringValue != null && !stringValue.trim().startsWith("{")) { + compiler.appendBodyCode("{ " + object.getJavaCode() + ".setLookAndFeel(" + TypeManager.getJavaCode(stringValue) + "); }" + JAXXCompiler.getLineSeparator()); + } else { + super.setAttribute(object, propertyName, stringValue, inline, compiler); + } + } + + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, "defaultCloseOperation", String.valueOf(WindowConstants.EXIT_ON_CLOSE), false, compiler); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/BeanValidatorHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/BeanValidatorHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/BeanValidatorHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,275 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.swing; - -import jaxx.CompilerException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.introspection.JAXXBeanInfo; -import jaxx.introspection.JAXXPropertyDescriptor; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.runtime.BeanValidator; -import jaxx.tags.DefaultObjectHandler; -import jaxx.types.TypeManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.beans.IntrospectionException; -import java.io.IOException; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - -public class BeanValidatorHandler extends DefaultObjectHandler { - - public static final String BEAN_VALIDATOR_TAG = BeanValidator.class.getSimpleName(); - public static final String BEAN_ATTRIBUTE = "bean"; - public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; - public static final String AUTOFIELD_ATTRIBUTE = "autoField"; - public static final String STRICT_MODE_ATTRIBUTE = "strictMode"; - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static Log log = LogFactory.getLog(BeanValidatorHandler.class); - - /** - * Creates a new <code>DefaultObjectHandler</code> which provides support for the specified class. The - * class is not actually introspected until the {@link #compileFirstPass} method is invoked. - * - * @param beanClass the class which this handler supports - */ - public BeanValidatorHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, BeanValidator.class); - } - - @Override - protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) { - return new CompiledBeanValidator(id, getBeanClass(), compiler); - } - - @Override - protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - log.info(tag); - if (!tag.getLocalName().equals(FieldValidatorHandler.FIELD_VALIDATOR_TAG)) { - compiler.reportError("tag '" + tag.getParentNode().getLocalName() + "' may only contain " + FieldValidatorHandler.FIELD_VALIDATOR_TAG + " as children, but found : " + tag.getLocalName()); - } else { - compiler.compileFirstPass(tag); - } - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - - super.compileSecondPass(tag, compiler); - - CompiledBeanValidator info = (CompiledBeanValidator) objectMap.get(tag); - - String tmp = info.getErrorListModel(); - - if (tmp != null) { - if (compiler.checkReference(tag, tmp, true, ERROR_LIST_MODEL_ATTRIBUTE)) { - String code = getSetPropertyCode(info.getJavaCode(), ERROR_LIST_MODEL_ATTRIBUTE, tmp, compiler); - info.appendAdditionCode(code); - } - } - String bean = info.getBean(); - if (bean != null) { - if (compiler.checkReference(tag, bean, true, BEAN_ATTRIBUTE)) { - String code = getSetPropertyCode(info.getJavaCode(), BEAN_ATTRIBUTE, bean, compiler); - info.appendAdditionCode(code); - } - } - - if (info.getAutoField()) { - if (bean == null) { - compiler.reportError("tag '" + tag.getLocalName() + "' need a " + BEAN_ATTRIBUTE + " attribute to use autofield mode"); - } else { - registerAutoFieldBean(tag, compiler, info); - } - } - - // add fieldrepresentation invocations - addFieldRepresentations(tag, compiler, info); - - // register the validator in compiler - compiler.registerValidator(info); - - // close the compiled object - compiler.closeComponent(info); - } - - @Override - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) { - // open the compiled object - compiler.openInvisibleComponent(object); - } - - @Override - public void setAttribute(CompiledObject object, String propertyName, String stringValue, boolean inline, JAXXCompiler compiler) { - if (compiler.getOptions().isVerbose()) { - log.info(propertyName + " : " + stringValue + " for " + object); - } - object.addProperty(propertyName, stringValue); - } - - protected void registerAutoFieldBean(Element tag, JAXXCompiler compiler, CompiledBeanValidator info) { - for (JAXXPropertyDescriptor beanProperty : info.getBeanDescriptor(compiler).getJAXXPropertyDescriptors()) { - String descriptionName = beanProperty.getName(); - log.info("doAutoField on property " + descriptionName); - if (beanProperty.getWriteMethodDescriptor() == null) { - // read-only property - continue; - } - if (info.getFields().containsKey(descriptionName)) { - // already defined in field - continue; - } - if (!compiler.checkReference(tag, descriptionName, info.getStrictMode(), null)) { - // no editor component found - continue; - } - // ok add the field mapping - info.addField(descriptionName, descriptionName, compiler); - } - } - - protected void addFieldRepresentations(Element tag, JAXXCompiler compiler, CompiledBeanValidator info) { - for (Entry<String, String> entry : info.getFields().entrySet()) { - String propertyName = entry.getKey(); - String component = entry.getValue(); - if (!checkBeanProperty(compiler, info, propertyName)) { - // property not find on bean - continue; - } - if (!compiler.checkReference(tag, component, true, null)) { - // editor component not find on ui - continue; - } - String keyCode = TypeManager.getJavaCode(propertyName); - info.appendAdditionCode(info.getJavaCode() + ".setFieldRepresentation(" + keyCode + ", " + component + ");"); - - } - } - - protected boolean checkBeanProperty(JAXXCompiler compiler, CompiledBeanValidator info, String propertyName) { - - for (JAXXPropertyDescriptor beanProperty : info.getBeanDescriptor(compiler).getJAXXPropertyDescriptors()) { - if (beanProperty.getName().equals(propertyName)) { - if (beanProperty.getWriteMethodDescriptor() == null) { - // read-onlyproperty - compiler.reportError("could not bind the readonly property '" + propertyName + "' on bean [" + info.getBean() + "] "); - return false; - } - return true; - } - } - compiler.reportError("could not find the property '" + propertyName + "' on bean [" + info.getBean() + "] "); - return false; - } - - /** @author chemit */ - public static class CompiledBeanValidator extends CompiledObject { - - protected Map<String, String> fields; - protected String bean; - protected String errorListModel; - protected Boolean autoField; - protected Boolean strictMode; - protected JAXXBeanInfo beanDescriptor; - - public CompiledBeanValidator(String id, ClassDescriptor objectClass, JAXXCompiler compiler) { - super(id, objectClass, compiler); - fields = new TreeMap<String, String>(); - } - - public Map<String, String> getFields() { - return fields; - } - - public void setFields(Map<String, String> fields) { - this.fields = fields; - } - - @Override - public void addProperty(String property, String value) { - - if (BEAN_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - bean = value; - } - return; - } - if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorListModel = value; - } - return; - } - if (AUTOFIELD_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - - autoField = (Boolean) TypeManager.convertFromString(value, Boolean.class); - } - return; - } - if (STRICT_MODE_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - - strictMode = (Boolean) TypeManager.convertFromString(value, Boolean.class); - } - return; - } - //todo should not allowed to find other attributes - super.addProperty(property, value); - } - - public void addField(String id, String component, JAXXCompiler compiler) { - if (fields.containsKey(id)) { - compiler.reportError("duplicate field '" + id + "' for validator " + this); - } else { - log.info("add field <" + id + ":" + component + ">"); - fields.put(id, component); - } - } - - public String getBean() { - return bean; - } - - public String getErrorListModel() { - return errorListModel; - } - - public boolean getAutoField() { - return autoField != null && autoField; - } - - public boolean getStrictMode() { - return strictMode != null && strictMode; - } - - public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { - if (beanDescriptor == null && bean != null) { - try { - ClassDescriptor beanClassDescriptor = ClassDescriptorLoader.getClassDescriptor(compiler.getSymbolTable().getClassTagIds().get(bean)); - beanDescriptor = getJAXXBeanInfo(beanClassDescriptor); - } catch (ClassNotFoundException e) { - compiler.reportError("could not load class " + bean); - } catch (IntrospectionException e) { - compiler.reportError("could not load class " + bean); - } - } - return beanDescriptor; - } - - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - // do nothing - compiler.reportError("can not add CompiledObject in the tag '" + BEAN_VALIDATOR_TAG + " (only field tags)"); - } - } -} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/FieldValidatorHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/FieldValidatorHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/FieldValidatorHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,73 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.swing; - -import jaxx.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.runtime.BeanValidator; -import jaxx.tags.TagHandler; -import jaxx.tags.swing.BeanValidatorHandler.CompiledBeanValidator; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.io.IOException; - -public class FieldValidatorHandler implements TagHandler { - - public static final String FIELD_VALIDATOR_TAG = "field"; - public static final String NAME_ATTRIBUTE = "name"; - public static final String COMPONENT_ATTRIBUTE = "component"; - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(FieldValidatorHandler.class); - - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getOptions().isVerbose()) { - log.info(tag); - } - //todo check there is no child - } - - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getOptions().isVerbose()) { - log.info(tag); - } - - if (!ClassDescriptorLoader.getClassDescriptor(BeanValidator.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { - compiler.reportError(FIELD_VALIDATOR_TAG + " tag may only appear within " + BeanValidatorHandler.BEAN_VALIDATOR_TAG + " tag but was " + tag); - return; - } - - CompiledBeanValidator validator = (CompiledBeanValidator) compiler.getOpenComponent(); - - String name = tag.getAttribute(NAME_ATTRIBUTE); - String component = tag.getAttribute(COMPONENT_ATTRIBUTE); - if (name == null || name.trim().isEmpty()) { - compiler.reportError(FIELD_VALIDATOR_TAG + " tag requires a " + NAME_ATTRIBUTE + " attribute"); - return; - } - name = name.trim(); - if (component == null || component.trim().isEmpty()) { - // try to use the name as component - if (!compiler.checkReference(tag, name, false, name)) { - compiler.reportError(FIELD_VALIDATOR_TAG + " tag requires a " + COMPONENT_ATTRIBUTE + " attribute, try to use the name attribute ["+name+"] for the component, but no such component found"); - return; - } - component = name; - } - component = component.trim(); - - // check component exist (again perharps, but if error will known exactly which tag failed...) - if (compiler.checkReference(tag, component, true, component)) { - // add a field - validator.addField(name, component, compiler); - } - - - } - -} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,53 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.swing; - -import jaxx.CompilerException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.tags.DefaultComponentHandler; -import org.w3c.dom.Element; - -import javax.swing.JInternalFrame; -import javax.swing.JMenuBar; -import javax.swing.WindowConstants; - -public class JInternalFrameHandler extends DefaultComponentHandler { - - public JInternalFrameHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, JInternalFrame.class); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledObject(id, getBeanClass(), compiler) { - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - if (ClassDescriptorLoader.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) - appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); - else - super.addChild(child, constraints, compiler); - } - }; - } - - @Override - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - super.setDefaults(object, tag, compiler); - setAttribute(object, "visible", "true", false, compiler); - setAttribute(object, "closable", "true", false, compiler); - setAttribute(object, "defaultCloseOperation", String.valueOf(WindowConstants.DISPOSE_ON_CLOSE), false, compiler); - } - - - @Override - public void setAttributes(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - super.setAttributes(object, tag, compiler); - compiler.initializer.append(object.getId()).append(".pack();\n"); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JInternalFrameHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,53 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags.swing; + +import jaxx.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JInternalFrame; +import javax.swing.JMenuBar; +import javax.swing.WindowConstants; + +public class JInternalFrameHandler extends DefaultComponentHandler { + + public JInternalFrameHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, JInternalFrame.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (ClassDescriptorLoader.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) + appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); + else + super.addChild(child, constraints, compiler); + } + }; + } + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, "visible", "true", false, compiler); + setAttribute(object, "closable", "true", false, compiler); + setAttribute(object, "defaultCloseOperation", String.valueOf(WindowConstants.DISPOSE_ON_CLOSE), false, compiler); + } + + + @Override + public void setAttributes(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setAttributes(object, tag, compiler); + compiler.appendInitializerCode(object.getId() + ".pack();\n"); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,58 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.swing; - -import jaxx.CompilerException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.tags.DefaultComponentHandler; -import org.w3c.dom.Element; - -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JMenuBar; -import javax.swing.JWindow; -import java.io.IOException; -import java.util.Map; - -public class JWindowHandler extends DefaultComponentHandler { - - public JWindowHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, JWindow.class, JFrame.class, JDialog.class); - } - - @Override - public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { - return new CompiledObject(id, getBeanClass(), compiler) { - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - if (ClassDescriptorLoader.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) - appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); - else - super.addChild(child, constraints, compiler); - } - }; - } - - @Override - protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { - if (compiler.getOpenComponent() != null) - compiler.openInvisibleComponent(object); - else - super.openComponent(object, tag, compiler); - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - super.compileSecondPass(tag, compiler); - CompiledObject object = (CompiledObject) objectMap.get(tag); - Map properties = object.getProperties(); - if (!properties.containsKey("width") && !properties.containsKey("height")) - compiler.lateInitializer.append(object.getId()).append(".pack();\n"); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java (from rev 977, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/JWindowHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,59 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags.swing; + +import jaxx.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JWindow; +import java.io.IOException; +import java.util.Map; + +public class JWindowHandler extends DefaultComponentHandler { + + public JWindowHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, JWindow.class, JFrame.class, JDialog.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (ClassDescriptorLoader.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) + appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); + else + super.addChild(child, constraints, compiler); + } + }; + } + + @Override + protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + if (compiler.getOpenComponent() != null) + compiler.openInvisibleComponent(object); + else + super.openComponent(object, tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileSecondPass(tag, compiler); + CompiledObject object = objectMap.get(tag); + Map properties = object.getProperties(); + if (!properties.containsKey("width") && !properties.containsKey("height")) { + compiler.appendLateInitializer(object.getId() + ".pack();\n"); + } + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,95 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.swing; - -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.runtime.swing.Application; -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.runtime.swing.JAXXComboBox; -import jaxx.runtime.swing.JAXXList; -import jaxx.runtime.swing.JAXXTab; -import jaxx.runtime.swing.JAXXTree; -import jaxx.runtime.swing.Table; -import jaxx.runtime.BeanValidator; -import jaxx.spi.Initializer; -import jaxx.tags.DefaultComponentHandler; -import jaxx.tags.DefaultObjectHandler; -import jaxx.tags.TagManager; -import jaxx.tags.swing.BeanValidatorHandler; -import jaxx.tags.swing.FieldValidatorHandler; -import jaxx.types.KeyStrokeConverter; -import jaxx.types.TypeManager; - -import javax.swing.*; -import javax.swing.text.JTextComponent; -import java.beans.Introspector; - -public class SwingInitializer implements Initializer { - - public void initialize() { - String[] searchPath = Introspector.getBeanInfoSearchPath(); - String[] newSearchPath = new String[searchPath.length + 1]; - System.arraycopy(searchPath, 0, newSearchPath, 0, searchPath.length); - newSearchPath[newSearchPath.length - 1] = "jaxx.beaninfos"; - Introspector.setBeanInfoSearchPath(newSearchPath); - - TagManager.registerTag("java.awt.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorLoader.getClassDescriptor(JAXXButtonGroup.class))); - - // Begin Try to fix bug when component handler is not found, but this is not this... - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JButton.class), DefaultComponentHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JTextField.class), JTextComponentHandler.class); - // End Try to fix bug when component handler is not found, but this is not this... - - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Application.class), ApplicationHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JCheckBox.class), JCheckBoxHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JCheckBoxMenuItem.class), JCheckBoxHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXComboBox.class), JComboBoxHandler.class); - TagManager.registerTag("javax.swing.*", "JComboBox", new JComboBoxHandler(ClassDescriptorLoader.getClassDescriptor(JAXXComboBox.class))); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JDialog.class), JWindowHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JFrame.class), JWindowHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JInternalFrame.class), JInternalFrameHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXList.class), JListHandler.class); - TagManager.registerTag("javax.swing.*", "JList", new JListHandler(ClassDescriptorLoader.getClassDescriptor(JAXXList.class))); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JMenu.class), JMenuHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JPasswordField.class), JPasswordFieldHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JPopupMenu.class), JPopupMenuHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JProgressBar.class), JProgressBarHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JRadioButton.class), JRadioButtonHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JRadioButtonMenuItem.class), JRadioButtonHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JScrollPane.class), JScrollPaneHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JSlider.class), JSliderHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JSpinner.class), JSpinnerHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JSplitPane.class), JSplitPaneHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JTabbedPane.class), JTabbedPaneHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JTextComponent.class), JTextComponentHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JToggleButton.class), JRadioButtonHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JToolBar.class), JToolBarHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXTree.class), JTreeHandler.class); - TagManager.registerTag("javax.swing.*", "JTree", new JTreeHandler(ClassDescriptorLoader.getClassDescriptor(JAXXTree.class))); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JWindow.class), JWindowHandler.class); - - TagManager.registerDefaultNamespace("JEditorPane", "javax.swing.*"); - TagManager.registerDefaultNamespace("JFormattedTextField", "javax.swing.*"); - TagManager.registerDefaultNamespace("JPasswordField", "javax.swing.*"); - TagManager.registerDefaultNamespace("JTextArea", "javax.swing.*"); - TagManager.registerDefaultNamespace("JTextField", "javax.swing.*"); - TagManager.registerDefaultNamespace("JTextPane", "javax.swing.*"); - - TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "tab", new TabHandler()); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Table.class), TableHandler.class); - TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "row", new RowHandler()); - TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "cell", new CellHandler()); - TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "item", new ItemHandler()); - - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXTab.class), JAXXTabHandler.class); - - TypeManager.registerTypeConverter(KeyStroke.class, new KeyStrokeConverter()); - - // validator - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(BeanValidator.class), BeanValidatorHandler.class); - TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, FieldValidatorHandler.FIELD_VALIDATOR_TAG, new FieldValidatorHandler()); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java (from rev 958, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,95 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags.swing; + +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.runtime.swing.Application; +import jaxx.runtime.swing.JAXXButtonGroup; +import jaxx.runtime.swing.JAXXComboBox; +import jaxx.runtime.swing.JAXXList; +import jaxx.runtime.swing.JAXXTab; +import jaxx.runtime.swing.JAXXTree; +import jaxx.runtime.swing.Table; +import jaxx.runtime.validator.BeanValidator; +import jaxx.spi.Initializer; +import jaxx.tags.DefaultComponentHandler; +import jaxx.tags.DefaultObjectHandler; +import jaxx.tags.TagManager; +import jaxx.tags.validator.BeanValidatorHandler; +import jaxx.tags.validator.FieldValidatorHandler; +import jaxx.types.KeyStrokeConverter; +import jaxx.types.TypeManager; + +import javax.swing.*; +import javax.swing.text.JTextComponent; +import java.beans.Introspector; + +public class SwingInitializer implements Initializer { + + public void initialize() { + String[] searchPath = Introspector.getBeanInfoSearchPath(); + String[] newSearchPath = new String[searchPath.length + 1]; + System.arraycopy(searchPath, 0, newSearchPath, 0, searchPath.length); + newSearchPath[newSearchPath.length - 1] = "jaxx.beaninfos"; + Introspector.setBeanInfoSearchPath(newSearchPath); + + TagManager.registerTag("java.awt.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorLoader.getClassDescriptor(JAXXButtonGroup.class))); + + // Begin Try to fix bug when component handler is not found, but this is not this... + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JButton.class), DefaultComponentHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JTextField.class), JTextComponentHandler.class); + // End Try to fix bug when component handler is not found, but this is not this... + + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Application.class), ApplicationHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JCheckBox.class), JCheckBoxHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JCheckBoxMenuItem.class), JCheckBoxHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXComboBox.class), JComboBoxHandler.class); + TagManager.registerTag("javax.swing.*", "JComboBox", new JComboBoxHandler(ClassDescriptorLoader.getClassDescriptor(JAXXComboBox.class))); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JDialog.class), JWindowHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JFrame.class), JWindowHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JInternalFrame.class), JInternalFrameHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXList.class), JListHandler.class); + TagManager.registerTag("javax.swing.*", "JList", new JListHandler(ClassDescriptorLoader.getClassDescriptor(JAXXList.class))); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JMenu.class), JMenuHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JPasswordField.class), JPasswordFieldHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JPopupMenu.class), JPopupMenuHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JProgressBar.class), JProgressBarHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JRadioButton.class), JRadioButtonHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JRadioButtonMenuItem.class), JRadioButtonHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JScrollPane.class), JScrollPaneHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JSlider.class), JSliderHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JSpinner.class), JSpinnerHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JSplitPane.class), JSplitPaneHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JTabbedPane.class), JTabbedPaneHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JTextComponent.class), JTextComponentHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JToggleButton.class), JRadioButtonHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JToolBar.class), JToolBarHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXTree.class), JTreeHandler.class); + TagManager.registerTag("javax.swing.*", "JTree", new JTreeHandler(ClassDescriptorLoader.getClassDescriptor(JAXXTree.class))); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JWindow.class), JWindowHandler.class); + + TagManager.registerDefaultNamespace("JEditorPane", "javax.swing.*"); + TagManager.registerDefaultNamespace("JFormattedTextField", "javax.swing.*"); + TagManager.registerDefaultNamespace("JPasswordField", "javax.swing.*"); + TagManager.registerDefaultNamespace("JTextArea", "javax.swing.*"); + TagManager.registerDefaultNamespace("JTextField", "javax.swing.*"); + TagManager.registerDefaultNamespace("JTextPane", "javax.swing.*"); + + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "tab", new TabHandler()); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Table.class), TableHandler.class); + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "row", new RowHandler()); + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "cell", new CellHandler()); + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "item", new ItemHandler()); + + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(JAXXTab.class), JAXXTabHandler.class); + + TypeManager.registerTypeConverter(KeyStroke.class, new KeyStrokeConverter()); + + // validator + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(BeanValidator.class), BeanValidatorHandler.class); + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, FieldValidatorHandler.FIELD_VALIDATOR_TAG, new FieldValidatorHandler()); + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator (from rev 958, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator) Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-10-17 20:55:15 UTC (rev 958) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,312 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.validator; - -import jaxx.CompilerException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.introspection.JAXXBeanInfo; -import jaxx.introspection.JAXXPropertyDescriptor; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.runtime.validator.BeanValidator; -import jaxx.runtime.validator.ui.AbstractBeanValidatorUI; -import jaxx.tags.DefaultObjectHandler; -import jaxx.types.TypeManager; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.beans.IntrospectionException; -import java.io.IOException; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - -public class BeanValidatorHandler extends DefaultObjectHandler { - - public static final String BEAN_VALIDATOR_TAG = BeanValidator.class.getSimpleName(); - public static final String BEAN_ATTRIBUTE = "bean"; - public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; - public static final String AUTOFIELD_ATTRIBUTE = "autoField"; - public static final String UI_CLASS_ATTRIBUTE = "uiClass"; - public static final String STRICT_MODE_ATTRIBUTE = "strictMode"; - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static Log log = LogFactory.getLog(BeanValidatorHandler.class); - - /** - * Creates a new <code>DefaultObjectHandler</code> which provides support for the specified class. The - * class is not actually introspected until the {@link #compileFirstPass} method is invoked. - * - * @param beanClass the class which this handler supports - */ - public BeanValidatorHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, BeanValidator.class); - } - - @Override - protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) { - return new CompiledBeanValidator(id, getBeanClass(), compiler); - } - - @Override - protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getOptions().isVerbose()) { - log.info(tag); - } - if (!tag.getLocalName().equals(FieldValidatorHandler.FIELD_VALIDATOR_TAG)) { - compiler.reportError("tag '" + tag.getParentNode().getLocalName() + "' may only contain " + FieldValidatorHandler.FIELD_VALIDATOR_TAG + " as children, but found : " + tag.getLocalName()); - } else { - compiler.compileFirstPass(tag); - } - } - - @Override - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - - super.compileSecondPass(tag, compiler); - - CompiledBeanValidator info = (CompiledBeanValidator) objectMap.get(tag); - - String tmp; - - tmp = info.getErrorListModel(); - if (tmp != null) { - if (compiler.checkReference(tag, tmp, true, ERROR_LIST_MODEL_ATTRIBUTE)) { - String code = getSetPropertyCode(info.getJavaCode(), ERROR_LIST_MODEL_ATTRIBUTE, tmp, compiler); - info.appendAdditionCode(code); - } - } - - tmp = info.getUiClass(); - if (tmp != null) { - try { - ClassDescriptor uiClass = ClassDescriptorLoader.getClassDescriptor(tmp); - if (!ClassDescriptorLoader.getClassDescriptor(AbstractBeanValidatorUI.class).isAssignableFrom(uiClass)) { - compiler.reportError("attribute 'ui' :'" + tmp + "' is not assignable from class " + AbstractBeanValidatorUI.class); - } else { - String code = getSetPropertyCode(info.getJavaCode(), UI_CLASS_ATTRIBUTE, uiClass.getName() + ".class", compiler); - info.appendAdditionCode(code); - } - } catch (ClassNotFoundException e) { - compiler.reportError("class not found '" + tmp + "'"); - } - } - - String bean = info.getBean(); - if (bean != null) { - if (compiler.checkReference(tag, bean, true, BEAN_ATTRIBUTE)) { - String code = getSetPropertyCode(info.getJavaCode(), BEAN_ATTRIBUTE, bean, compiler); - info.appendAdditionCode(code); - } - } - - if (info.getAutoField()) { - if (bean == null) { - compiler.reportError("tag '" + tag.getLocalName() + "' need a " + BEAN_ATTRIBUTE + " attribute to use autofield mode"); - } else { - registerAutoFieldBean(tag, compiler, info); - } - } - - // add fieldrepresentation invocations - addFieldRepresentations(tag, compiler, info); - - // register the validator in compiler - compiler.registerValidator(info); - - // close the compiled object - compiler.closeComponent(info); - } - - @Override - protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) { - // open the compiled object - compiler.openInvisibleComponent(object); - } - - @Override - public void setAttribute(CompiledObject object, String propertyName, String stringValue, boolean inline, JAXXCompiler compiler) { - if (compiler.getOptions().isVerbose()) { - log.info(propertyName + " : " + stringValue + " for " + object); - } - object.addProperty(propertyName, stringValue); - } - - protected void registerAutoFieldBean(Element tag, JAXXCompiler compiler, CompiledBeanValidator info) { - JAXXBeanInfo beanInfo = info.getBeanDescriptor(compiler); - for (JAXXPropertyDescriptor beanProperty : beanInfo.getJAXXPropertyDescriptors()) { - String descriptionName = beanProperty.getName(); - if (compiler.getOptions().isVerbose()) { - log.info("try to bind on bean " + beanInfo.getJAXXBeanDescriptor().getName() + " property " + descriptionName); - } - if (beanProperty.getWriteMethodDescriptor() == null) { - // read-only property - continue; - } - if (info.getFields().containsKey(descriptionName)) { - // already defined in field - continue; - } - if (!compiler.checkReference(tag, descriptionName, info.getStrictMode(), null)) { - // no editor component found - continue; - } - // ok add the field mapping - info.addField(descriptionName, descriptionName, compiler); - } - } - - protected void addFieldRepresentations(Element tag, JAXXCompiler compiler, CompiledBeanValidator info) { - for (Entry<String, String> entry : info.getFields().entrySet()) { - String propertyName = entry.getKey(); - String component = entry.getValue(); - if (!checkBeanProperty(compiler, info, propertyName)) { - // property not find on bean - continue; - } - if (!compiler.checkReference(tag, component, true, null)) { - // editor component not find on ui - continue; - } - String keyCode = TypeManager.getJavaCode(propertyName); - info.appendAdditionCode(info.getJavaCode() + ".setFieldRepresentation(" + keyCode + ", " + component + ");"); - - } - } - - protected boolean checkBeanProperty(JAXXCompiler compiler, CompiledBeanValidator info, String propertyName) { - - for (JAXXPropertyDescriptor beanProperty : info.getBeanDescriptor(compiler).getJAXXPropertyDescriptors()) { - if (beanProperty.getName().equals(propertyName)) { - if (beanProperty.getWriteMethodDescriptor() == null) { - // read-onlyproperty - compiler.reportError("could not bind the readonly property '" + propertyName + "' on bean [" + info.getBean() + "] "); - return false; - } - return true; - } - } - compiler.reportError("could not find the property '" + propertyName + "' on bean [" + info.getBean() + "] "); - return false; - } - - /** @author chemit */ - public static class CompiledBeanValidator extends CompiledObject { - - protected Map<String, String> fields; - protected String bean; - protected String uiClass; - protected String errorListModel; - protected Boolean autoField; - protected Boolean strictMode; - protected JAXXBeanInfo beanDescriptor; - - public CompiledBeanValidator(String id, ClassDescriptor objectClass, JAXXCompiler compiler) { - super(id, objectClass, compiler); - fields = new TreeMap<String, String>(); - } - - public Map<String, String> getFields() { - return fields; - } - - public void setFields(Map<String, String> fields) { - this.fields = fields; - } - - @Override - public void addProperty(String property, String value) { - - if (BEAN_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - bean = value; - } - return; - } - if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorListModel = value; - } - return; - } - if (UI_CLASS_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - uiClass = value; - } - return; - } - if (AUTOFIELD_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - - autoField = (Boolean) TypeManager.convertFromString(value, Boolean.class); - } - return; - } - if (STRICT_MODE_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - - strictMode = (Boolean) TypeManager.convertFromString(value, Boolean.class); - } - return; - } - //todo should not allowed to find other attributes - super.addProperty(property, value); - } - - public void addField(String id, String component, JAXXCompiler compiler) { - if (fields.containsKey(id)) { - compiler.reportError("duplicate field '" + id + "' for validator " + this); - } else { - if (compiler.getOptions().isVerbose()) { - log.info("add field <" + id + ":" + component + ">"); - } - fields.put(id, component); - } - } - - public String getBean() { - return bean; - } - - public String getErrorListModel() { - return errorListModel; - } - - public boolean getAutoField() { - return autoField != null && autoField; - } - - public boolean getStrictMode() { - return strictMode != null && strictMode; - } - - public String getUiClass() { - return uiClass; - } - - public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { - if (beanDescriptor == null && bean != null) { - try { - ClassDescriptor beanClassDescriptor = ClassDescriptorLoader.getClassDescriptor(compiler.getSymbolTable().getClassTagIds().get(bean)); - beanDescriptor = getJAXXBeanInfo(beanClassDescriptor); - } catch (ClassNotFoundException e) { - compiler.reportError("could not load class " + bean); - } catch (IntrospectionException e) { - compiler.reportError("could not load class " + bean); - } - } - return beanDescriptor; - } - - @Override - public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { - // do nothing - compiler.reportError("can not add CompiledObject in the tag '" + BEAN_VALIDATOR_TAG + " (only field tags)"); - } - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java (from rev 975, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,340 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags.validator; + +import jaxx.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.introspection.JAXXBeanInfo; +import jaxx.introspection.JAXXPropertyDescriptor; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.ui.AbstractBeanValidatorUI; +import jaxx.tags.DefaultObjectHandler; +import jaxx.types.TypeManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + +import java.beans.IntrospectionException; +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +public class BeanValidatorHandler extends DefaultObjectHandler { + + public static final String BEAN_VALIDATOR_TAG = BeanValidator.class.getSimpleName(); + public static final String BEAN_ATTRIBUTE = "bean"; + public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; + public static final String AUTOFIELD_ATTRIBUTE = "autoField"; + public static final String UI_CLASS_ATTRIBUTE = "uiClass"; + public static final String STRICT_MODE_ATTRIBUTE = "strictMode"; + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static Log log = LogFactory.getLog(BeanValidatorHandler.class); + + /** + * Creates a new <code>DefaultObjectHandler</code> which provides support for the specified class. The + * class is not actually introspected until the {@link #compileFirstPass} method is invoked. + * + * @param beanClass the class which this handler supports + */ + public BeanValidatorHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, BeanValidator.class); + } + + @Override + protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) { + return new CompiledBeanValidator(id, getBeanClass(), compiler); + } + + @Override + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getOptions().isVerbose()) { + log.info(tag); + } + if (!tag.getLocalName().equals(FieldValidatorHandler.FIELD_VALIDATOR_TAG)) { + compiler.reportError("tag '" + tag.getParentNode().getLocalName() + "' may only contain " + FieldValidatorHandler.FIELD_VALIDATOR_TAG + " as children, but found : " + tag.getLocalName()); + } else { + compiler.compileFirstPass(tag); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + + super.compileSecondPass(tag, compiler); + + CompiledBeanValidator info = (CompiledBeanValidator) objectMap.get(tag); + + String tmp; + + tmp = info.getErrorListModel(); + if (tmp != null) { + if (compiler.checkReference(tag, tmp, true, ERROR_LIST_MODEL_ATTRIBUTE)) { + String code = getSetPropertyCode(info.getJavaCode(), ERROR_LIST_MODEL_ATTRIBUTE, tmp, compiler); + info.appendAdditionCode(code); + } + } + + tmp = info.getUiClass(); + if (tmp != null) { + try { + ClassDescriptor uiClass = ClassDescriptorLoader.getClassDescriptor(tmp); + if (!ClassDescriptorLoader.getClassDescriptor(AbstractBeanValidatorUI.class).isAssignableFrom(uiClass)) { + compiler.reportError("attribute 'ui' :'" + tmp + "' is not assignable from class " + AbstractBeanValidatorUI.class); + } else { + String code = getSetPropertyCode(info.getJavaCode(), UI_CLASS_ATTRIBUTE, uiClass.getName() + ".class", compiler); + info.appendAdditionCode(code); + } + } catch (ClassNotFoundException e) { + compiler.reportError("class not found '" + tmp + "'"); + } + } + + String bean = info.getBean(); + boolean error = false; + if (bean != null) { + if (compiler.checkReference(tag, bean, true, BEAN_ATTRIBUTE)) { + String code = getSetPropertyCode(info.getJavaCode(), BEAN_ATTRIBUTE, bean, compiler); + info.appendAdditionCode(code); + // add generic type to validator + JAXXBeanInfo beanInfo = info.getBeanDescriptor(compiler); + info.setGenericTypes(new String[]{beanInfo.getJAXXBeanDescriptor().getClassDescriptor().getName()}); + } else { + error=true; + } + + //TODO: checkthe bean is not already used in another validator + if (!error && compiler.isBeanUsedByValidator(bean)) { + compiler.reportError("the bean '" + bean + "' is already used in another the validator, can not used it in '" + tag + "'"); + error = true; + } + + if (!error && info.getAutoField()) { + //if (bean == null) { + // compiler.reportError("tag '" + tag.getLocalName() + "' need a " + BEAN_ATTRIBUTE + " attribute to use autofield mode"); + //} else { + registerAutoFieldBean(tag, compiler, info); + // } + } + + if (!error && info.getBeanDescriptor(compiler) != null) { + + // add fieldrepresentation invocations + addFieldRepresentations(tag, compiler, info); + + // register the validator in compiler + compiler.registerValidator(info); + } + + } else { + compiler.reportError("tag '" + tag + "' requires a bean attribute"); + } + + // close the compiled object + compiler.closeComponent(info); + } + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) { + // open the compiled object + compiler.openInvisibleComponent(object); + } + + @Override + public void setAttribute(CompiledObject object, String propertyName, String stringValue, boolean inline, JAXXCompiler compiler) { + if (compiler.getOptions().isVerbose()) { + log.info(propertyName + " : " + stringValue + " for " + object); + } + object.addProperty(propertyName, stringValue); + } + + protected void registerAutoFieldBean(Element tag, JAXXCompiler compiler, CompiledBeanValidator info) { + JAXXBeanInfo beanInfo = info.getBeanDescriptor(compiler); + for (JAXXPropertyDescriptor beanProperty : beanInfo.getJAXXPropertyDescriptors()) { + String descriptionName = beanProperty.getName(); + if (compiler.getOptions().isVerbose()) { + log.info("try to bind on bean " + beanInfo.getJAXXBeanDescriptor().getName() + " property " + descriptionName); + } + if (beanProperty.getWriteMethodDescriptor() == null) { + // read-only property + continue; + } + if (info.getFields().containsKey(descriptionName)) { + // already defined in field + continue; + } + if (!compiler.checkReference(tag, descriptionName, info.getStrictMode(), null)) { + // no editor component found + continue; + } + // ok add the field mapping + info.addField(descriptionName, descriptionName, compiler); + } + } + + protected void addFieldRepresentations(Element tag, JAXXCompiler compiler, CompiledBeanValidator info) { + for (Entry<String, String> entry : info.getFields().entrySet()) { + String propertyName = entry.getKey(); + String component = entry.getValue(); + if (!checkBeanProperty(compiler, info, propertyName)) { + // property not find on bean + continue; + } + if (!compiler.checkReference(tag, component, true, null)) { + // editor component not find on ui + continue; + } + if (compiler.isComponentUsedByValidator(component)) { + // component is already used by another validator + compiler.reportError("component '" + component + "' is already used by another validator."); + continue; + } + String keyCode = TypeManager.getJavaCode(propertyName); + info.appendAdditionCode(info.getJavaCode() + ".setFieldRepresentation(" + keyCode + ", " + component + ");"); + + } + } + + protected boolean checkBeanProperty(JAXXCompiler compiler, CompiledBeanValidator info, String propertyName) { + + for (JAXXPropertyDescriptor beanProperty : info.getBeanDescriptor(compiler).getJAXXPropertyDescriptors()) { + if (beanProperty.getName().equals(propertyName)) { + if (beanProperty.getWriteMethodDescriptor() == null) { + // read-onlyproperty + compiler.reportError("could not bind the readonly property '" + propertyName + "' on bean [" + info.getBean() + "] "); + return false; + } + return true; + } + } + compiler.reportError("could not find the property '" + propertyName + "' on bean [" + info.getBean() + "] "); + return false; + } + + /** @author chemit */ + public static class CompiledBeanValidator extends CompiledObject { + + protected Map<String, String> fields; + protected String bean; + protected String uiClass; + protected String errorListModel; + protected Boolean autoField; + protected Boolean strictMode; + protected JAXXBeanInfo beanDescriptor; + + public CompiledBeanValidator(String id, ClassDescriptor objectClass, JAXXCompiler compiler) { + super(id, objectClass, compiler); + fields = new TreeMap<String, String>(); + } + + public Map<String, String> getFields() { + return fields; + } + + public void setFields(Map<String, String> fields) { + this.fields = fields; + } + + @Override + public void addProperty(String property, String value) { + + if (BEAN_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + bean = value; + } + return; + } + if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorListModel = value; + } + return; + } + if (UI_CLASS_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + uiClass = value; + } + return; + } + if (AUTOFIELD_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + + autoField = (Boolean) TypeManager.convertFromString(value, Boolean.class); + } + return; + } + if (STRICT_MODE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + + strictMode = (Boolean) TypeManager.convertFromString(value, Boolean.class); + } + return; + } + //todo should not allowed to find other attributes + super.addProperty(property, value); + } + + public void addField(String id, String component, JAXXCompiler compiler) { + if (fields.containsKey(id)) { + compiler.reportError("duplicate field '" + id + "' for validator " + this); + } else { + if (compiler.getOptions().isVerbose()) { + log.info("add field <" + id + ":" + component + ">"); + } + fields.put(id, component); + } + } + + public String getBean() { + return bean; + } + + public String getErrorListModel() { + return errorListModel; + } + + public boolean getAutoField() { + return autoField != null && autoField; + } + + public boolean getStrictMode() { + return strictMode != null && strictMode; + } + + public String getUiClass() { + return uiClass; + } + + public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { + if (beanDescriptor == null && bean != null) { + try { + String beanClassName = compiler.getSymbolTable().getClassTagIds().get(bean); + if (beanClassName == null) { + compiler.reportError("could not find class of the bean '" + bean + "'"); + return null; + } + ClassDescriptor beanClassDescriptor = ClassDescriptorLoader.getClassDescriptor(beanClassName); + beanDescriptor = getJAXXBeanInfo(beanClassDescriptor); + } catch (ClassNotFoundException e) { + compiler.reportError("could not load class " + bean); + } catch (IntrospectionException e) { + compiler.reportError("could not load class " + bean); + } + } + return beanDescriptor; + } + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + // do nothing + compiler.reportError("can not add CompiledObject in the tag '" + BEAN_VALIDATOR_TAG + " (only field tags)"); + } + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java 2008-10-17 20:55:15 UTC (rev 958) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,73 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.validator; - -import jaxx.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.runtime.validator.BeanValidator; -import jaxx.tags.TagHandler; -import jaxx.tags.validator.BeanValidatorHandler.CompiledBeanValidator; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Element; - -import java.io.IOException; - -public class FieldValidatorHandler implements TagHandler { - - public static final String FIELD_VALIDATOR_TAG = "field"; - public static final String NAME_ATTRIBUTE = "name"; - public static final String COMPONENT_ATTRIBUTE = "component"; - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(FieldValidatorHandler.class); - - public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getOptions().isVerbose()) { - log.info(tag); - } - //todo check there is no child - } - - public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { - if (compiler.getOptions().isVerbose()) { - log.info(tag); - } - - if (!ClassDescriptorLoader.getClassDescriptor(BeanValidator.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { - compiler.reportError(FIELD_VALIDATOR_TAG + " tag may only appear within " + BeanValidatorHandler.BEAN_VALIDATOR_TAG + " tag but was " + tag); - return; - } - - CompiledBeanValidator validator = (CompiledBeanValidator) compiler.getOpenComponent(); - - String name = tag.getAttribute(NAME_ATTRIBUTE); - String component = tag.getAttribute(COMPONENT_ATTRIBUTE); - if (name == null || name.trim().isEmpty()) { - compiler.reportError(FIELD_VALIDATOR_TAG + " tag requires a " + NAME_ATTRIBUTE + " attribute"); - return; - } - name = name.trim(); - if (component == null || component.trim().isEmpty()) { - // try to use the name as component - if (!compiler.checkReference(tag, name, false, name)) { - compiler.reportError(FIELD_VALIDATOR_TAG + " tag requires a " + COMPONENT_ATTRIBUTE + " attribute, try to use the name attribute ["+name+"] for the component, but no such component found"); - return; - } - component = name; - } - component = component.trim(); - - // check component exist (again perharps, but if error will known exactly which tag failed...) - if (compiler.checkReference(tag, component, true, component)) { - // add a field - validator.addField(name, component, compiler); - } - - - } - -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java (from rev 974, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,78 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags.validator; + +import jaxx.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.runtime.validator.BeanValidator; +import jaxx.tags.TagHandler; +import jaxx.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + +import java.io.IOException; + +public class FieldValidatorHandler implements TagHandler { + + public static final String FIELD_VALIDATOR_TAG = "field"; + public static final String NAME_ATTRIBUTE = "name"; + public static final String COMPONENT_ATTRIBUTE = "component"; + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(FieldValidatorHandler.class); + + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getOptions().isVerbose()) { + log.info(tag); + } + //todo check there is no child + } + + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getOptions().isVerbose()) { + log.info(tag); + } + + if (!ClassDescriptorLoader.getClassDescriptor(BeanValidator.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { + compiler.reportError(FIELD_VALIDATOR_TAG + " tag may only appear within " + BeanValidatorHandler.BEAN_VALIDATOR_TAG + " tag but was " + tag); + return; + } + + CompiledBeanValidator validator = (CompiledBeanValidator) compiler.getOpenComponent(); + + String name = tag.getAttribute(NAME_ATTRIBUTE); + String component = tag.getAttribute(COMPONENT_ATTRIBUTE); + if (name == null || name.trim().isEmpty()) { + compiler.reportError(FIELD_VALIDATOR_TAG + " tag requires a " + NAME_ATTRIBUTE + " attribute"); + return; + } + name = name.trim(); + if (component == null || component.trim().isEmpty()) { + // try to use the name as component + if (!compiler.checkReference(tag, name, false, name)) { + compiler.reportError(FIELD_VALIDATOR_TAG + " tag requires a " + COMPONENT_ATTRIBUTE + " attribute, try to use the name attribute ["+name+"] for the component, but no such component found"); + return; + } + component = name; + } + component = component.trim(); + + // check component is not already used by this validator + if (validator.getFields().containsValue(component)) { + compiler.reportError(FIELD_VALIDATOR_TAG + " tag found a attribute " + COMPONENT_ATTRIBUTE + " ["+component+"] already used in this validator"); + return; + } + // check component exist (again perharps, but if error will known exactly which tag failed...) + if (compiler.checkReference(tag, component, true, COMPONENT_ATTRIBUTE)) { + // add a field + validator.addField(name, component, compiler); + } + + + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/resources/example.jnlp =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/resources/example.jnlp 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/resources/example.jnlp 2008-10-21 07:31:05 UTC (rev 990) @@ -1,16 +0,0 @@ -<jnlp spec="1.0+" codebase="http://www.jaxxframework.org/examples/@name@" href="@name@.jnlp"> - <information> - <title>@name@.jaxx</title> - <vendor>jaxxframework.org</vendor> - <offline-allowed/> - </information> - - <resources> - <j2se version="1.4.0+" href="http://java.sun.com/products/autodl/j2se"/> - <jar href="@name@.jar"/> - <jar href="../jaxx-runtime.jar"/> - </resources> - - <application-desc main-class="examples.@name@.@name@"/> -</jnlp> - Deleted: lutinjaxx/tags/0.5/jaxx-core/src/main/resources/manifest.mf =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/resources/manifest.mf 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/resources/manifest.mf 2008-10-21 07:31:05 UTC (rev 990) @@ -1,4 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: ../jaxx-runtime.jar -Main-Class: @class@ - Copied: lutinjaxx/tags/0.5/jaxx-core/src/main/resources/validators.xml (from rev 981, lutinjaxx/trunk/jaxx-core/src/main/resources/validators.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/main/resources/validators.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/main/resources/validators.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE validators PUBLIC + "-//OpenSymphony Group//XWork Validator Config 1.0//EN" + "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd"> + +<!-- START SNIPPET: validators --> +<validators> + <validator name="requiredFile" class="jaxx.runtime.validator.RequiredFileFieldValidator"/> + <validator name="existingFile" class="jaxx.runtime.validator.ExistingFileFieldValidator"/> + <validator name="notExistingFile" class="jaxx.runtime.validator.NotExistingFileFieldValidator"/> + <validator name="existingDirectory" class="jaxx.runtime.validator.ExistingDirectoryFieldValidator"/> + <validator name="notExistingDirectory" class="jaxx.runtime.validator.NotExistingDirectoryFieldValidator"/> +</validators> +<!-- END SNIPPET: validators --> Copied: lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java (from rev 981, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,79 @@ +package jaxx.junit; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; + +public class ValidatorBean { + + protected File existingFile; + protected File notExistingFile; + + protected File existingDirectory; + protected File notExistingDirectory; + + + PropertyChangeSupport p; + + public ValidatorBean() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + + public File getExistingFile() { + return existingFile; + } + + public File getNotExistingFile() { + return notExistingFile; + } + + public File getExistingDirectory() { + return existingDirectory; + } + + public File getNotExistingDirectory() { + return notExistingDirectory; + } + + public void setExistingFile(File existingFile) { + File old = this.existingFile; + this.existingFile = existingFile; + p.firePropertyChange("existingFile", old, existingFile); + } + + public void setNotExistingFile(File notExistingFile) { + File old = this.notExistingFile; + this.notExistingFile = notExistingFile; + p.firePropertyChange("notExistingFile", old, notExistingFile); + } + + public void setExistingDirectory(File existingDirectory) { + File old = this.existingDirectory; + this.existingDirectory = existingDirectory; + p.firePropertyChange("existingDirectory", old, existingDirectory); + } + + public void setNotExistingDirectory(File notExistingDirectory) { + File old = this.notExistingDirectory; + this.notExistingDirectory = notExistingDirectory; + p.firePropertyChange("notExistingDirectory", old, notExistingDirectory); + } + +} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java (from rev 981, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,167 @@ +package jaxx.junit; + +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidatorError; +import jaxx.runtime.validator.BeanValidatorErrorListModel; +import junit.framework.TestCase; + +import javax.swing.JLabel; +import java.io.File; +import java.util.Enumeration; + +/** @author chemit */ +public class ValidatorTest extends TestCase { + + ValidatorBean bean; + + static protected Boolean init = null; + + + static protected BeanValidator<ValidatorBean> validator; + + static protected BeanValidatorErrorListModel errors; + + static protected File basedir; + + @Override + protected void setUp() throws Exception { + super.setUp(); + if (init == null) { + String b = System.getenv("basedir"); + if (b == null) { + b = new File("").getAbsolutePath(); + } + basedir = new File(b); + validator = new BeanValidator<ValidatorBean>(); + validator.setErrorListModel(errors = new BeanValidatorErrorListModel()); + JLabel label = new JLabel(); + validator.setFieldRepresentation("existingFile", label); + validator.setFieldRepresentation("existingDirectory", label); + validator.setFieldRepresentation("notExistingFile", label); + validator.setFieldRepresentation("notExistingDirectory", label); + init = true; + } + validator.setBean(bean = new ValidatorBean()); + } + + public void testRequiredFileFieldValidator() throws Exception { + + assertNull(bean.getExistingFile()); + assertFieldInError("existingFile", "existingFile.required", true); + + bean.setExistingFile(new File("")); + assertFieldInError("existingFile", "existingFile.required", true); + + bean.setExistingFile(basedir); + assertFieldInError("existingFile", "existingFile.required", false); + + assertFieldInError("existingFile", "existingFile.not.exist", true); + + bean.setExistingFile(new File(basedir, "pom.xml")); + assertFieldInError("existingFile", "existingFile.required", false); + assertFieldInError("existingFile", "existingFile.not.exist", false); + + } + + public void testExistingFileFieldValidator() throws Exception { + + assertNull(bean.getExistingFile()); + assertFieldInError("existingFile", "existingFile.required", true); + + bean.setExistingFile(new File("")); + assertFieldInError("existingFile", "existingFile.required", true); + + // existing directory + bean.setExistingFile(basedir); + assertFieldInError("existingFile", "existingFile.required", false); + assertFieldInError("existingFile", "existingFile.not.exist", true); + + // existing file + bean.setExistingFile(new File(basedir, "pom.xml")); + assertFieldInError("existingFile", "existingFile.required", false); + assertFieldInError("existingFile", "existingFile.not.exist", false); + + } + + public void testNotExistingFileFieldValidator() throws Exception { + + assertNull(bean.getNotExistingFile()); + assertFieldInError("notExistingFile", "notExistingFile.required", true); + + bean.setNotExistingFile(new File("")); + assertFieldInError("notExistingFile", "notExistingFile.required", true); + + // existing directory + bean.setNotExistingFile(basedir); + assertFieldInError("notExistingFile", "notExistingFile.required", false); + assertFieldInError("notExistingFile", "notExistingFile.exist", true); + + // existing file + bean.setNotExistingFile(new File(basedir, "pom.xml")); + assertFieldInError("notExistingFile", "notExistingFile.required", false); + assertFieldInError("notExistingFile", "notExistingFile.exist", true); + + // none existing file + bean.setNotExistingFile(new File(basedir, "pom.xml-" + System.currentTimeMillis())); + assertFieldInError("notExistingFile", "notEexistingFile.required", false); + assertFieldInError("notExistingFile", "notExistingFile.exist", false); + + + } + + public void testExistingDirectoryFieldValidator() throws Exception { + + assertNull(bean.getExistingDirectory()); + assertFieldInError("existingDirectory", "existingDirectory.required", true); + + bean.setExistingDirectory(new File("")); + assertFieldInError("existingDirectory", "existingDirectory.required", true); + + // existing file + bean.setExistingDirectory(new File(basedir, "pom.xml")); + assertFieldInError("existingDirectory", "existingDirectory.required", false); + assertFieldInError("existingDirectory", "existingDirectory.not.exist", true); + + // existing directory + bean.setExistingDirectory(basedir); + assertFieldInError("existingDirectory", "existingDirectory.required", false); + assertFieldInError("existingDirectory", "existingDirectory.not.exist", false); + + } + + public void testNotExistingDirectoryFieldValidator() throws Exception { + assertNull(bean.getNotExistingDirectory()); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", true); + + bean.setNotExistingDirectory(new File("")); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", true); + + // existing directory + bean.setNotExistingDirectory(basedir); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", false); + assertFieldInError("notExistingDirectory", "notExistingDirectory.exist", true); + + // existing file + bean.setNotExistingDirectory(new File(basedir, "pom.xml")); + assertFieldInError("notExistingDirectory", "notExistingDirectory.required", false); + assertFieldInError("notExistingDirectory", "notExistingDirectory.exist", true); + + // none existing directory + bean.setNotExistingDirectory(new File(basedir, "pom.xml-" + System.currentTimeMillis())); + assertFieldInError("notExistingDirectory", "notEexistingFile.required", false); + assertFieldInError("notExistingDirectory", "notExistingDirectory.exist", false); + } + + protected void assertFieldInError(String s, String error, boolean required) { + Enumeration<?> myErrors = errors.elements(); + while (myErrors.hasMoreElements()) { + BeanValidatorError o = (BeanValidatorError) myErrors.nextElement(); + if (o.getFieldName().equals(s) && o.getError().equals(error)) { + assertTrue(required); + return; + } + } + // error was not found + assertFalse(required); + } +} Copied: lutinjaxx/tags/0.5/jaxx-core/src/test/resources/jaxx (from rev 981, lutinjaxx/trunk/jaxx-core/src/test/resources/jaxx) Deleted: lutinjaxx/tags/0.5/jaxx-core/src/test/resources/log4j.properties =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/resources/log4j.properties 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-core/src/test/resources/log4j.properties 2008-10-21 07:31:05 UTC (rev 990) @@ -1,9 +0,0 @@ -# Global logging configuration -log4j.rootLogger=INFO, stdout -# Console output... -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n - -#log4j.logger.org.codelutin.jaxx=DEBUG -#log4j.logger.jaxx=DEBUG Copied: lutinjaxx/tags/0.5/jaxx-core/src/test/resources/log4j.properties (from rev 981, lutinjaxx/trunk/jaxx-core/src/test/resources/log4j.properties) =================================================================== --- lutinjaxx/tags/0.5/jaxx-core/src/test/resources/log4j.properties (rev 0) +++ lutinjaxx/tags/0.5/jaxx-core/src/test/resources/log4j.properties 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,9 @@ +# Global logging configuration +log4j.rootLogger=ERROR, stdout +# Console output... +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n + +#log4j.logger.org.codelutin.jaxx=DEBUG +#log4j.logger.jaxx=DEBUG Deleted: lutinjaxx/tags/0.5/jaxx-example/Calculator/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Calculator/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Calculator/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-example</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.jaxx-example</groupId> - <artifactId>Calculator</artifactId> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>Calculator example</name> - <description>Jaxx Calculator example</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <plugins> - <plugin> - <groupId>org.codehaus.mojo.webstart</groupId> - <artifactId>webstart-maven-plugin</artifactId> - </plugin> - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.example}</connection> - <developerConnection>${scm.developerConnection.example}</developerConnection> - <url>${scm.url.example}</url> - </scm> - -</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/Calculator/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-example/Calculator/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Calculator/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Calculator/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,39 @@ +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-example</artifactId> + <version>0.5</version> + </parent> + + <groupId>org.codelutin.jaxx-example</groupId> + <artifactId>Calculator</artifactId> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>Calculator example</name> + <description>Jaxx Calculator example</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/Calculator</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/Calculator</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-example/Calculator?root=buix</url> + </scm> + +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-example/Components/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Components/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Components/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,43 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-example</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.jaxx-example</groupId> - <artifactId>Components</artifactId> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>Components example</name> - <version>0.5-SNAPSHOT</version> - <inceptionYear>2008</inceptionYear> - <description>Jaxx Components example</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <plugins> - <plugin> - <groupId>org.codehaus.mojo.webstart</groupId> - <artifactId>webstart-maven-plugin</artifactId> - </plugin> - </plugins> - </build> -</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/Components/pom.xml (from rev 964, lutinjaxx/trunk/jaxx-example/Components/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Components/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Components/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-example</artifactId> + <version>0.5-SNAPSHOT</version> + </parent> + + <groupId>org.codelutin.jaxx-example</groupId> + <artifactId>Components</artifactId> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>Components example</name> + <description>Jaxx Components example</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>${scm.connection.example}</connection> + <developerConnection>${scm.developerConnection.example}</developerConnection> + <url>${scm.url.example}</url> + </scm> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-example/Counter/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Counter/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Counter/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-example</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.jaxx-example</groupId> - <artifactId>Counter</artifactId> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>Counter example</name> - <description>Jaxx Counter example</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <plugins> - <plugin> - <groupId>org.codehaus.mojo.webstart</groupId> - <artifactId>webstart-maven-plugin</artifactId> - </plugin> - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.example}</connection> - <developerConnection>${scm.developerConnection.example}</developerConnection> - <url>${scm.url.example}</url> - </scm> -</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/Counter/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-example/Counter/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Counter/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Counter/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,38 @@ +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-example</artifactId> + <version>0.5</version> + </parent> + + <groupId>org.codelutin.jaxx-example</groupId> + <artifactId>Counter</artifactId> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>Counter example</name> + <description>Jaxx Counter example</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/Counter</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/Counter</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-example/Counter?root=buix</url> + </scm> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-example/LabelStyle/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/LabelStyle/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/LabelStyle/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-example</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.jaxx-example</groupId> - <artifactId>LabelStyle</artifactId> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>LabelStyle example</name> - <description>Jaxx LabelStyle example</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <plugins> - <plugin> - <groupId>org.codehaus.mojo.webstart</groupId> - <artifactId>webstart-maven-plugin</artifactId> - </plugin> - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.example}</connection> - <developerConnection>${scm.developerConnection.example}</developerConnection> - <url>${scm.url.example}</url> - </scm> -</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/LabelStyle/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-example/LabelStyle/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/LabelStyle/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/LabelStyle/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,38 @@ +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-example</artifactId> + <version>0.5</version> + </parent> + + <groupId>org.codelutin.jaxx-example</groupId> + <artifactId>LabelStyle</artifactId> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>LabelStyle example</name> + <description>Jaxx LabelStyle example</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/LabelStyle</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/LabelStyle</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-example/LabelStyle?root=buix</url> + </scm> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-example/Validation/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Validation/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-example</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.jaxx-example</groupId> - <artifactId>Validation</artifactId> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>Validation example</name> - <description>Jaxx Validation (with xwork validation) example</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <plugins> - <plugin> - <groupId>org.codehaus.mojo.webstart</groupId> - <artifactId>webstart-maven-plugin</artifactId> - </plugin> - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.example}</connection> - <developerConnection>${scm.developerConnection.example}</developerConnection> - <url>${scm.url.example}</url> - </scm> -</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/Validation/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-example/Validation/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Validation/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,38 @@ +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-example</artifactId> + <version>0.5</version> + </parent> + + <groupId>org.codelutin.jaxx-example</groupId> + <artifactId>Validation</artifactId> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>Validation example</name> + <description>Jaxx Validation (with xwork validation) example</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/Validation</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example/Validation</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-example/Validation?root=buix</url> + </scm> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java =================================================================== --- lutinjaxx/trunk/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,79 +0,0 @@ -package examples.Validation; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -public class Identity { - - protected String firstName = ""; - - protected String lastName = ""; - - protected String email = "dummy@codelutin.com"; - - protected int age = 51; - - - PropertyChangeSupport p; - - public Identity() { - p = new PropertyChangeSupport(this); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - p.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - p.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - p.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - p.removePropertyChangeListener(propertyName, listener); - } - - - public String getFirstName() { - return firstName; - } - - public String getLastName() { - return lastName; - } - - public String getEmail() { - return email; - } - - public int getAge() { - return age; - } - - public void setFirstName(String firstName) { - String oldFirstName = this.firstName; - this.firstName = firstName; - p.firePropertyChange("firstName", oldFirstName, firstName); - } - - public void setLastName(String lastName) { - String oldLastName = this.lastName; - this.lastName = lastName; - p.firePropertyChange("lastName", oldLastName, lastName); - } - - public void setEmail(String email) { - String oldEmail =this.email; - this.email = email; - p.firePropertyChange("email", oldEmail, email); - } - - public void setAge(int age) { - int oldAge = this.age; - this.age = age; - p.firePropertyChange("age", oldAge, age); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java (from rev 979, lutinjaxx/trunk/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Identity.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,103 @@ +package examples.Validation; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; + +public class Identity { + + protected String firstName = ""; + + protected String lastName = ""; + + protected String email = "dummy@codelutin.com"; + + protected int age = 51; + + protected File config = new File("/tmp"); + + protected File dir = new File("/tmp"); + + PropertyChangeSupport p; + + public Identity() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getEmail() { + return email; + } + + public int getAge() { + return age; + } + + public File getConfig() { + return config; + } + + public File getDir() { + return dir; + } + + public void setFirstName(String firstName) { + String oldFirstName = this.firstName; + this.firstName = firstName; + p.firePropertyChange("firstName", oldFirstName, firstName); + } + + public void setLastName(String lastName) { + String oldLastName = this.lastName; + this.lastName = lastName; + p.firePropertyChange("lastName", oldLastName, lastName); + } + + public void setEmail(String email) { + String oldEmail = this.email; + this.email = email; + p.firePropertyChange("email", oldEmail, email); + } + + public void setAge(int age) { + int oldAge = this.age; + this.age = age; + p.firePropertyChange("age", oldAge, age); + } + + public void setConfig(File config) { + File oldConfig = this.config; + this.config = config; + p.firePropertyChange("config", oldConfig, config); + } + + public void setDir(File dir) { + File oldDir = this.dir; + this.dir = dir; + p.firePropertyChange("dir", oldDir, dir); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css =================================================================== --- lutinjaxx/trunk/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css 2008-10-21 07:31:05 UTC (rev 990) @@ -1,8 +0,0 @@ -JSlider { - paintTicks: true; -} - -JSlider#ratio { - minorTickSpacing: 5; - majorTickSpacing: 10; -} Copied: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css (from rev 956, lutinjaxx/trunk/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.css 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,5 @@ +JSlider { + paintTicks: true; + minorTickSpacing: 5; + majorTickSpacing: 10; +} Deleted: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx =================================================================== --- lutinjaxx/trunk/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -1,292 +0,0 @@ -<Application title="Validation.jaxx"> - <style source="Validation.css"/> - - <!-- models --> - <Model id='model'/> - <Model id='model2'/> - <Identity id='identity'/> - - <!-- errors model --> - <DefaultListModel id='errors' onIntervalAdded='ok.setEnabled(errors.size()==0)' onIntervalRemoved='ok.setEnabled(errors.size()==0)'/> - - <!-- validators --> - <BeanValidator id='validator' bean='model' errorListModel='errors'> - <field name="text"/> - <field name="text2"/> - <field name="ratio"/> - </BeanValidator> - <BeanValidator id='validator2' bean='model2' errorListModel='errors'> - <field name="text" component="_text"/> - <field name="text2" component="_text2"/> - <field name="ratio" component="_ratio"/> - </BeanValidator> - <BeanValidator id='validator3' autoField='true' bean='identity' errorListModel='errors'> - <field name="email" component="email2"/> - <field name="email" component="email2"/> - </BeanValidator> - - <Table fill='both'> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Form")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <org.jdesktop.jxlayer.JXLayer> - <JTextField id='text' text='{model.getText()}' - onKeyReleased='model.setText(text.getText())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <org.jdesktop.jxlayer.JXLayer> - <JTextField id='text2' text='{model.getText2()}' - onKeyReleased='model.setText2(text2.getText())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <org.jdesktop.jxlayer.JXLayer> - <JSlider id='ratio' minimum='0' maximum='100' value='{model.getRatio()}' - onStateChanged='model.setRatio(ratio.getValue())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model.getText()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model.getText2()}'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JLabel text='{model.getRatio()}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Form2")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <org.jdesktop.jxlayer.JXLayer> - <JTextField id='_text' text='{model2.getText()}' - onKeyReleased='model2.setText(_text.getText())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <org.jdesktop.jxlayer.JXLayer> - <JTextField id='_text2' text='{model2.getText2()}' - onKeyReleased='model2.setText2(_text2.getText())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <org.jdesktop.jxlayer.JXLayer> - <JSlider id='_ratio' minimum='0' maximum='100' value='{model2.getRatio()}' - onStateChanged='model2.setRatio(_ratio.getValue())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Model2")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='Text:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model2.getText()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Text2:'/> - </cell> - <cell weightx='1'> - <JLabel text='{model2.getText2()}'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Ratio:'/> - </cell> - <cell> - <JLabel text='{model2.getRatio()}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' - layout='{new GridLayout()}' width='250' height='140'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='FirstName:'/> - </cell> - <cell weightx='1'> - <org.jdesktop.jxlayer.JXLayer> - <JTextField id='firstName' text='{identity.getFirstName()}' - onKeyReleased='identity.setFirstName(firstName.getText())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - <row> - <cell> - <JLabel text='LastName:'/> - </cell> - <cell weightx='1'> - <org.jdesktop.jxlayer.JXLayer> - <JTextField id='lastName' text='{identity.getLastName()}' - onKeyReleased='identity.setLastName(lastName.getText())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - <row> - <cell> - <JLabel text='Email:'/> - </cell> - <cell weightx='1'> - <org.jdesktop.jxlayer.JXLayer> - <JTextField id='email2' text='{identity.getEmail()}' - onKeyReleased='identity.setEmail(email2.getText())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - - <row> - <cell> - <JLabel text='Age:'/> - </cell> - <cell> - <org.jdesktop.jxlayer.JXLayer> - <JSlider id='age' minimum='0' maximum='100' value='{identity.getAge()}' - onStateChanged='identity.setAge(age.getValue())'/> - </org.jdesktop.jxlayer.JXLayer> - </cell> - </row> - </Table> - </JPanel> - </cell> - <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> - <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' - layout='{new GridLayout()}' width='250' height='120'> - <Table anchor='west' fill='both'> - <row> - <cell> - <JLabel text='FirstName:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getFirstName()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='LastName:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getLastName()}'/> - </cell> - </row> - <row> - <cell> - <JLabel text='Email:'/> - </cell> - <cell weightx='1'> - <JLabel text='{identity.getEmail()}'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Age:'/> - </cell> - <cell> - <JLabel text='{identity.getAge()}'/> - </cell> - </row> - </Table> - </JPanel> - </cell> - </row> - <row> - <cell columns='2' fill="both"> - <JPanel border='{BorderFactory.createTitledBorder("Errors")}' layout='{new GridLayout()}' height='200' width='500'> - <JScrollPane> - <JList model='{errors}'/> - </JScrollPane> - </JPanel> - </cell> - </row> - <row> - <cell columns='2' fill="both"> - <JPanel layout='{new GridLayout(1,2,0,0)}'> - <JButton text='cancel' onActionPerformed='dispose()'/> - <JButton id='ok' text='valid' onActionPerformed='dispose()'/> - </JPanel> - </cell> - </row> - - </Table> -</Application> Copied: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx (from rev 979, lutinjaxx/trunk/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/java/examples/Validation/Validation.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,304 @@ +<Application title="Validation.jaxx"> + <style source="Validation.css"/> + + <!-- models --> + <Model id='model'/> + <Model id='model2'/> + <Identity id='identity'/> + + <!-- errors model --> + <jaxx.runtime.validator.BeanValidatorErrorListModel id='errors' onContentsChanged='ok.setEnabled(errors.size()==0)'/> + + <!-- validators --> + <BeanValidator id='validator' bean='model' errorListModel='errors'> + <field name="text"/> + <field name="text2"/> + <field name="ratio"/> + </BeanValidator> + <BeanValidator id='validator2' bean='model2' errorListModel='errors' uiClass="jaxx.runtime.validator.ui.IconValidationUI"> + <field name="text" component="_text"/> + <field name="text2" component="_text2"/> + <field name="ratio" component="_ratio"/> + </BeanValidator> + <BeanValidator id='validator3' autoField='true' bean='identity' errorListModel='errors' uiClass="jaxx.runtime.validator.ui.TranslucentValidationUI"> + <field name="email" component="email2"/> + </BeanValidator> + + <Table fill='both'> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Form")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='text' text='{model.getText()}' + onKeyReleased='model.setText(text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='text2' text='{model.getText2()}' + onKeyReleased='model.setText2(text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='ratio' minimum='0' maximum='100' value='{model.getRatio()}' + onStateChanged='model.setRatio(ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model.getRatio()}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Form2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text' text='{model2.getText()}' + onKeyReleased='model2.setText(_text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text2' text='{model2.getText2()}' + onKeyReleased='model2.setText2(_text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='_ratio' minimum='0' maximum='100' value='{model2.getRatio()}' + onStateChanged='model2.setRatio(_ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model2.getRatio()}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' + layout='{new GridLayout()}' width='250' height='180'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JTextField id='firstName' text='{identity.getFirstName()}' + onKeyReleased='identity.setFirstName(firstName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JTextField id='lastName' text='{identity.getLastName()}' + onKeyReleased='identity.setLastName(lastName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JTextField id='email2' text='{identity.getEmail()}' + onKeyReleased='identity.setEmail(email2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JSlider id='age' minimum='0' maximum='100' value='{identity.getAge()}' + onStateChanged='identity.setAge(age.getValue())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file :'/> + </cell> + <cell> + <JTextField id='config' text='{identity.getConfig()}' + onKeyReleased='identity.setConfig(new java.io.File(config.getText()))'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Working directory:'/> + </cell> + <cell> + <JTextField id='dir' text='{identity.getDir()}' + onKeyReleased='identity.setDir(new java.io.File(dir.getText()))'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getFirstName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getLastName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getEmail()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JLabel text='{identity.getAge()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file:'/> + </cell> + <cell> + <JLabel text='{identity.getConfig()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Directory file:'/> + </cell> + <cell> + <JLabel text='{identity.getDir()}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel border='{BorderFactory.createTitledBorder("Errors")}' layout='{new GridLayout()}' height='200' width='500'> + <JScrollPane> + <JList model='{errors}'/> + </JScrollPane> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel layout='{new GridLayout(1,2,0,0)}'> + <JButton text='cancel' onActionPerformed='dispose()'/> + <JButton id='ok' text='valid' onActionPerformed='dispose()'/> + </JPanel> + </cell> + </row> + + </Table> +</Application> Deleted: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,32 +0,0 @@ -<!DOCTYPE validators PUBLIC - "-//OpenSymphony Group//XWork Validator 1.0.2//EN" - "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> -<validators> - <field name="firstName"> - <field-validator type="requiredstring" short-circuit="true"> - <message>You must enter a firstName.</message> - </field-validator> - </field> - <field name="lastName"> - <field-validator type="requiredstring" short-circuit="true"> - <message>You must enter a lastName.</message> - </field-validator> - </field> - - <field name="email"> - <field-validator type="requiredstring" short-circuit="true"> - <message>You must enter a value for email.</message> - </field-validator> - <field-validator type="email" short-circuit="true"> - <message>Not a valid e-mail.</message> - </field-validator> - </field> - - <field name="age"> - <field-validator type="int"> - <param name="min">18</param> - <param name="max">88</param> - <message>Age needs to be between ${min} and ${max}</message> - </field-validator> - </field> -</validators> \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml (from rev 983, lutinjaxx/trunk/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/Validation/src/main/resources/examples/Validation/Identity-validation.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,50 @@ +<!DOCTYPE validators PUBLIC + "-//OpenSymphony Group//XWork Validator 1.0.2//EN" + "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> +<validators> + <field name="firstName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a firstName.</message> + </field-validator> + </field> + <field name="lastName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a lastName.</message> + </field-validator> + </field> + + <field name="email"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a value for email.</message> + </field-validator> + <field-validator type="email" short-circuit="true"> + <message>Not a valid e-mail.</message> + </field-validator> + </field> + + <field name="config"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for config.</message> + </field-validator> + <field-validator type="existingFile" short-circuit="true"> + <message>The configuration file ${config} does not exist.</message> + </field-validator> + </field> + + <field name="dir"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for dir.</message> + </field-validator> + <field-validator type="existingDirectory" short-circuit="true"> + <message>The directory ${dir} does not exist.</message> + </field-validator> + </field> + + <field name="age"> + <field-validator type="int"> + <param name="min">18</param> + <param name="max">88</param> + <message>Age needs to be between ${min} and ${max}</message> + </field-validator> + </field> +</validators> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-example/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-example/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,268 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>lutinjaxx</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <artifactId>jaxx-example</artifactId> - - <dependencies> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-core</artifactId> - <scope>compile</scope> - </dependency> - - </dependencies> - - <modules> - <module>Calculator</module> - <!--module>Components</module--> - <module>Counter</module> - <module>LabelStyle</module> - <module>Validation</module> - </modules> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>jaxx-example</name> - <description>Jaxx Example super pom</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>pom</packaging> - - <properties> - - <!-- this property must be defined here, since it can be override by a profile --> - - <maven.jar.main.class>examples.${project.artifactId}.${project.artifactId}</maven.jar.main.class> - - <!-- jnlp --> - <keystorepath>${codelutin.keystorepath}</keystorepath> - <keystorealias>CodeLutin</keystorealias> - <keystorepass>codelutin</keystorepass> - - <jnlp.build.directory>${project.build.directory}/jnlp</jnlp.build.directory> - - <!-- scm (for sons) --> - <scm.url.example> - http://${labs.host}/plugins/scmsvn/viewcvs.php/lutinjaxx/trunk/jaxx-example/${pom.artifactId}/?root=${labs.project} - </scm.url.example> - - <scm.developerConnection.example> - scm:svn:svn+ssh://${username}@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/jaxx-example/${pom.artifactId} - </scm.developerConnection.example> - - <scm.connection.example> - scm:svn:svn://anonymous@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/jaxx-example/${pom.artifactId} - </scm.connection.example> - - </properties> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.son}</connection> - <developerConnection>${scm.developerConnection.son}</developerConnection> - <url>${scm.url.son}</url> - </scm> - - <build> - <pluginManagement> - <plugins> - - <plugin> - - <artifactId>maven-antrun-plugin</artifactId> - <executions> - <!-- Ajout des libs signe par Sun dans un fichier jnlp separe --> - <execution> - <id>JnlpSun</id> - <phase>compile</phase> - <configuration> - <tasks> - <mkdir dir="${jnlp.build.directory}"/> - <copy file="${project.basedir}/../src/main/jnlp/sun.jnlp" - verbose="${maven.verbose}" - todir="${jnlp.build.directory}" failonerror="false"> - <filterset> - <filter token="lib" value="javahelp-2.0.02.jar"/> - <filter token="url" value="${project.url}"/> - </filterset> - </copy> - <copy file="${project.basedir}/../src/main/jnlp/jxlayer.jnlp" - verbose="${maven.verbose}" - todir="${jnlp.build.directory}" failonerror="false"> - <filterset> - <filter token="lib" value="jxlayer-3.0.1.jar"/> - <filter token="url" value="${project.url}"/> - </filterset> - </copy> - <copy file="${project.build.directory}/lib/javahelp-2.0.02.jar" - verbose="${maven.verbose}" - todir="${jnlp.build.directory}/lib" failonerror="false"/> - <copy file="${project.build.directory}/lib/jxlayer-3.0.1.jar" - verbose="${maven.verbose}" - todir="${jnlp.build.directory}/lib" failonerror="false"/> - </tasks> - </configuration> - <goals> - <goal>run</goal> - </goals> - </execution> - - <execution> - <id>JnlpToSite</id> - <phase>pre-site</phase> - <configuration> - <tasks> - <mkdir dir="${maven.site.gen.dir}/resources"/> - <copy todir="${maven.site.gen.dir}/resources" verbose="${maven.verbose}" - failonerror="false" overwrite="false"> - <fileset dir="${jnlp.build.directory}"> - <include name="**"/> - </fileset> - </copy> - </tasks> - </configuration> - <goals> - <goal>run</goal> - </goals> - </execution> - </executions> - </plugin> - - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-jaxx-plugin</artifactId> - <version>0.5-SNAPSHOT</version> - <configuration> - <src>${basedir}/src/main/java</src> - <force>true</force> - </configuration> - <executions> - <execution> - <goals> - <goal>generate</goal> - </goals> - </execution> - </executions> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <configuration> - <outputDirectory>${project.build.directory}/lib</outputDirectory> - </configuration> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <configuration> - <archive> - <manifest> - <addClasspath>true</addClasspath> - <mainClass>${maven.jar.main.class}</mainClass> - <classpathPrefix>lib/</classpathPrefix> - </manifest> - </archive> - </configuration> - </plugin> - - - <plugin> - <groupId>org.codehaus.mojo.webstart</groupId> - <artifactId>webstart-maven-plugin</artifactId> - <version>1.0-alpha-2-cl_20081016</version> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>jnlp-inline</goal> - </goals> - </execution> - </executions> - <configuration> - <dependencies> - <excludes> - <exclude>javax.help:javahelp</exclude> - <exclude>org.swinglabs:jxlayer</exclude> - </excludes> - </dependencies> - <libPath>lib</libPath> - <extensions> - <sun>sun.jnlp</sun> - <jxlayer>jxlayer.jnlp</jxlayer> - </extensions> - <jnlp> - <outputFile>launch-${project.artifactId}.jnlp</outputFile> - <mainClass>${maven.jar.main.class}</mainClass> - <allPermissions>true</allPermissions> - <offlineAllowed>true</offlineAllowed> - </jnlp> - - <sign> - <keystore>${keystorepath}</keystore> - <keypass/> - <storepass>${keystorepass}</storepass> - <storetype/> - <alias>${keystorealias}</alias> - <validity/> - <dnameCn/> - <dnameOu/> - <dnameO/> - <dnameL/> - <dnameSt/> - <dnameC/> - <verify>true</verify> - <keystoreConfig> - <delete>false</delete> - <gen>false</gen> - </keystoreConfig> - </sign> - - - <pack200>false</pack200> - <gzip>true</gzip> - <verbose>false</verbose> - </configuration> - </plugin> - - </plugins> - - </pluginManagement> - - <plugins> - - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-jaxx-plugin</artifactId> - </plugin> - - <plugin> - <artifactId>maven-dependency-plugin</artifactId> - </plugin> - - </plugins> - </build> - -</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/jaxx-example/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-example/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-example/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-example/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,262 @@ +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>lutinjaxx</artifactId> + <version>0.5</version> + </parent> + + <artifactId>jaxx-example</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-core</artifactId> + <scope>compile</scope> + </dependency> + + </dependencies> + + <modules> + <module>Calculator</module> + <!--module>Components</module--> + <module>Counter</module> + <module>LabelStyle</module> + <module>Validation</module> + </modules> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>jaxx-example</name> + <description>Jaxx Example super pom</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>pom</packaging> + + <properties> + + <!-- this property must be defined here, since it can be override by a profile --> + + <maven.jar.main.class>examples.${project.artifactId}.${project.artifactId}</maven.jar.main.class> + + <!-- jnlp --> + <keystorepath>${codelutin.keystorepath}</keystorepath> + <keystorealias>CodeLutin</keystorealias> + <keystorepass>codelutin</keystorepass> + + <jnlp.build.directory>${project.build.directory}/jnlp</jnlp.build.directory> + + <!-- scm (for sons) --> + <scm.url.example> + http://${labs.host}/plugins/scmsvn/viewcvs.php/lutinjaxx/trunk/jaxx-example/${pom.artifactId}/?root=${labs.project} + </scm.url.example> + + <scm.developerConnection.example> + scm:svn:svn+ssh://${username}@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/jaxx-example/${pom.artifactId} + </scm.developerConnection.example> + + <scm.connection.example> + scm:svn:svn://anonymous@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/jaxx-example/${pom.artifactId} + </scm.connection.example> + + </properties> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-example</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-example?root=buix</url> + </scm> + + <build> + <pluginManagement> + <plugins> + + <plugin> + + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <!-- Ajout des libs signe par Sun dans un fichier jnlp separe --> + <execution> + <id>JnlpSun</id> + <phase>compile</phase> + <configuration> + <tasks> + <mkdir dir="${jnlp.build.directory}" /> + <copy file="${project.basedir}/../src/main/jnlp/sun.jnlp" verbose="${maven.verbose}" todir="${jnlp.build.directory}" failonerror="false"> + <filterset> + <filter token="lib" value="javahelp-2.0.02.jar" /> + <filter token="url" value="${project.url}" /> + </filterset> + </copy> + <copy file="${project.basedir}/../src/main/jnlp/jxlayer.jnlp" verbose="${maven.verbose}" todir="${jnlp.build.directory}" failonerror="false"> + <filterset> + <filter token="lib" value="jxlayer-3.0.1.jar" /> + <filter token="url" value="${project.url}" /> + </filterset> + </copy> + <copy file="${project.build.directory}/lib/javahelp-2.0.02.jar" verbose="${maven.verbose}" todir="${jnlp.build.directory}/lib" failonerror="false" /> + <copy file="${project.build.directory}/lib/jxlayer-3.0.1.jar" verbose="${maven.verbose}" todir="${jnlp.build.directory}/lib" failonerror="false" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + + <execution> + <id>JnlpToSite</id> + <phase>pre-site</phase> + <configuration> + <tasks> + <mkdir dir="${maven.site.gen.dir}/resources" /> + <copy todir="${maven.site.gen.dir}/resources" verbose="${maven.verbose}" failonerror="false" overwrite="false"> + <fileset dir="${jnlp.build.directory}"> + <include name="**" /> + </fileset> + </copy> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-jaxx-plugin</artifactId> + <version>0.5</version> + <configuration> + <src>${basedir}/src/main/java</src> + <force>true</force> + </configuration> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <configuration> + <outputDirectory>${project.build.directory}/lib</outputDirectory> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <mainClass>${maven.jar.main.class}</mainClass> + <classpathPrefix>lib/</classpathPrefix> + </manifest> + </archive> + </configuration> + </plugin> + + + <plugin> + <groupId>org.codehaus.mojo.webstart</groupId> + <artifactId>webstart-maven-plugin</artifactId> + <version>1.0-alpha-2-cl_20081018</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>jnlp-inline</goal> + </goals> + </execution> + </executions> + <configuration> + <force>false</force> + <dependencies> + <excludes> + <exclude>javax.help:javahelp</exclude> + <exclude>org.swinglabs:jxlayer</exclude> + </excludes> + </dependencies> + <libPath>lib</libPath> + <extensions> + <sun>sun.jnlp</sun> + <jxlayer>jxlayer.jnlp</jxlayer> + </extensions> + <jnlp> + <outputFile>launch-${project.artifactId}.jnlp</outputFile> + <mainClass>${maven.jar.main.class}</mainClass> + <allPermissions>true</allPermissions> + <offlineAllowed>true</offlineAllowed> + </jnlp> + + <sign> + <keystore>${keystorepath}</keystore> + <keypass /> + <storepass>${keystorepass}</storepass> + <storetype /> + <alias>${keystorealias}</alias> + <validity /> + <dnameCn /> + <dnameOu /> + <dnameO /> + <dnameL /> + <dnameSt /> + <dnameC /> + <verify>true</verify> + <keystoreConfig> + <delete>false</delete> + <gen>false</gen> + </keystoreConfig> + </sign> + + + <pack200>false</pack200> + <gzip>true</gzip> + <verbose>false</verbose> + </configuration> + </plugin> + + </plugins> + + </pluginManagement> + + <plugins> + + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-jaxx-plugin</artifactId> + </plugin> + + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo.webstart</groupId> + <artifactId>webstart-maven-plugin</artifactId> + </plugin> + + </plugins> + </build> + +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/jaxx-swing-action/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-swing-action/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-swing-action/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,75 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>lutinjaxx</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <artifactId>jaxx-swing-action</artifactId> - - <dependencies> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-core</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>jboss</groupId> - <artifactId>javassist</artifactId> - <version>3.7.ga</version> - <scope>compile</scope> - </dependency> - - </dependencies> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>jaxx-swing-action</name> - <description>Jaxx lutin library swing extension (tabs and actions)</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - <packaging>jar</packaging> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <compilerArgument>-proc:none</compilerArgument> - </configuration> - </plugin> - - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-i18n-plugin</artifactId> - </plugin> - - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.son}</connection> - <developerConnection>${scm.developerConnection.son}</developerConnection> - <url>${scm.url.son}</url> - </scm> - -</project> Copied: lutinjaxx/tags/0.5/jaxx-swing-action/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-swing-action/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-swing-action/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-swing-action/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + + <modelVersion>4.0.0</modelVersion> + + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>lutinjaxx</artifactId> + <version>0.5</version> + </parent> + + <artifactId>jaxx-swing-action</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-core</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>jboss</groupId> + <artifactId>javassist</artifactId> + <version>3.7.ga</version> + <scope>compile</scope> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>jaxx-swing-action</name> + <description>Jaxx lutin library swing extension (tabs and actions)</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + <packaging>jar</packaging> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compilerArgument>-proc:none</compilerArgument> + </configuration> + </plugin> + + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-i18n-plugin</artifactId> + </plugin> + + </plugins> + </build> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-swing-action</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-swing-action</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-swing-action?root=buix</url> + </scm> + +</project> Deleted: lutinjaxx/tags/0.5/jaxx-util/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-util/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/jaxx-util/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,46 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - <parent> - <groupId>org.codelutin</groupId> - <artifactId>lutinjaxx</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <artifactId>jaxx-util</artifactId> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>jaxx-util</name> - <description>Jaxx lutin library utility</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - <packaging>jar</packaging> - - <build> - <plugins> - <plugin> - <groupId>org.codelutin.plugin</groupId> - <artifactId>maven-i18n-plugin</artifactId> - </plugin> - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.son}</connection> - <developerConnection>${scm.developerConnection.son}</developerConnection> - <url>${scm.url.son}</url> - </scm> -</project> Copied: lutinjaxx/tags/0.5/jaxx-util/pom.xml (from rev 989, lutinjaxx/trunk/jaxx-util/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/jaxx-util/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/jaxx-util/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + <parent> + <groupId>org.codelutin</groupId> + <artifactId>lutinjaxx</artifactId> + <version>0.5</version> + </parent> + + <artifactId>jaxx-util</artifactId> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>jaxx-util</name> + <description>Jaxx lutin library utility</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + <packaging>jar</packaging> + + <build> + <plugins> + <plugin> + <groupId>org.codelutin.plugin</groupId> + <artifactId>maven-i18n-plugin</artifactId> + </plugin> + </plugins> + </build> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-util</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/jaxx-util</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/jaxx-util?root=buix</url> + </scm> +</project> Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/pom.xml =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,131 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>lutinjaxx</artifactId> - <version>0.5-SNAPSHOT</version> - </parent> - - <artifactId>maven-jaxx-plugin</artifactId> - - <dependencies> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinutil</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-core</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-swing-action</artifactId> - <scope>compile</scope> - </dependency> - - <!-- maven plugin project dependencies --> - <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-plugin-api</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-project</artifactId> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.apache.maven.shared</groupId> - <artifactId>maven-plugin-testing-harness</artifactId> - <version>1.1</version> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>org.apache.maven.shared</groupId> - <artifactId>maven-verifier</artifactId> - <version>1.0</version> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinpluginutil</artifactId> - <scope>compile</scope> - </dependency> - - </dependencies> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - - <name>maven-jaxx-plugin</name> - - <description> - Maven 2 plugin to generate java source from ui interface definitions - in jaxx format. - </description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>maven-plugin</packaging> - <build> - <plugins> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-plugin-plugin</artifactId> - <version>2.4.3</version> - <executions> - <execution> - <id>helpmojo</id> - <goals> - <goal>helpmojo</goal> - </goals> - </execution> - </executions> - </plugin> - - </plugins> - </build> - - <reporting> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-plugin-plugin</artifactId> - <version>2.4.3</version> - </plugin> - </plugins> - </reporting> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${scm.connection.son}</connection> - <developerConnection>${scm.developerConnection.son}</developerConnection> - <url>${scm.url.son}</url> - </scm> - - -</project> Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/pom.xml (from rev 989, lutinjaxx/trunk/maven-jaxx-plugin/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,128 @@ +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>lutinjaxx</artifactId> + <version>0.5</version> + </parent> + + <artifactId>maven-jaxx-plugin</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-core</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-swing-action</artifactId> + <scope>compile</scope> + </dependency> + + <!-- maven plugin project dependencies --> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-plugin-testing-harness</artifactId> + <version>1.1</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-verifier</artifactId> + <version>1.0</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinpluginutil</artifactId> + <scope>compile</scope> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>maven-jaxx-plugin</name> + + <description> + Maven 2 plugin to generate java source from ui interface definitions + in jaxx format. + </description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>maven-plugin</packaging> + <build> + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>2.4.3</version> + <executions> + <execution> + <id>helpmojo</id> + <goals> + <goal>helpmojo</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + + <reporting> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugin-plugin</artifactId> + <version>2.4.3</version> + </plugin> + </plugins> + </reporting> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/maven-jaxx-plugin</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5/maven-jaxx-plugin</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5/maven-jaxx-plugin?root=buix</url> + </scm> + + +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,448 +0,0 @@ -/* *##% - * Copyright (C) 2007 - * JaxxPlugin, Code Lutin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * 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 for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -package org.codelutin.jaxx; - -import jaxx.compiler.CompilerOptions; -import jaxx.compiler.JAXXCompiler; -import jaxx.tags.TagManager; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugin.logging.Log; -import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.util.DirectoryScanner; -import org.codelutin.util.FileUpdaterHelper; -import org.codelutin.util.MirroredFileUpdater; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -/** - * Classe permettant de transformer des sources jaxx vers du source java. - * - * @author chemit - * @goal generate - * @phase process-sources - */ -public class JaxxGeneratorMojo extends AbstractMojo { - - /** - * Dépendance du projet. - * - * @parameter default-value="${project}" - * @readonly - */ - protected MavenProject project; - - /** - * Repertoire de destination des fichiers java a generer. - * - * @parameter expression="${jaxx.outJava}" default-value="${basedir}/target/generated-sources/java" - */ - protected File outJava; - - /** - * chemin du repertoire de generation des resources. - * - * @parameter expression="${jaxx.outResource}" default-value="${basedir}/target/generated-sources/resources" - */ - protected File outResource; - - /** - * chemin du repertoire de compilation des resources. - * - * @parameter expression="${jaxx.outClass}" default-value="${basedir}/target/classes" - */ - protected File outClass; - - /** - * verbose flag - * - * @parameter expression="${jaxx.verbose}" default-value="false" - */ - protected boolean verbose; - - /** - * Repertoire sources des fichiers jaxx a generer. - * - * @parameter expression="${jaxx.src}" default-value="${maven.src.dir}/main/uimodel" - */ - protected File src; - - /** - * pour optimizer le code compile ou genere ? - * - * @parameter expression="${jaxx.optimize}" default-value="false" - */ - protected boolean optimize; - - /** - * les options de la compilation - * - * @parameter expression="${jaxx.javaOpts}" - */ - protected String javaOpts = null; - - /** - * pour filter les fichiers a traiter - * - * @parameter expression="${jaxx.includes}" - */ - protected String[] includes; - - /** - * to force generation of java source for any jaxx files with no timestamp checking. - * <p/> - * By default, never force generation. - * - * @parameter expression="${jaxx.force}" default-value="false" - */ - protected boolean force; - - /** - * to make compiler i18nable, says add the {@link org.codelutin.i18n.I18n#_(String, Object[])} method - * invocation on {@link jaxx.compiler.I18nHelper#I18N_ATTRIBUTES} attributes. - * - * @parameter expression="${jaxx.i18nable}" default-value="true" - * @see jaxx.compiler.I18nHelper - */ - protected boolean i18nable; - - - /** - * flag to add logger to each generated jaxx file. - * <p/> - * By default, always add it. - * - * @parameter expression="${jaxx.addLogger}" default-value="true" - */ - protected boolean addLogger; - - protected String[] files; - - private static final String[] INCLUDES = {"**\\/*.jaxx"}; - - protected CompilerOptions options; - - protected MirroredFileUpdater updater; - - protected boolean skip = true; - - protected void init() { - - if (project!=null && ("pom".equals(project.getPackaging()) || "site".equals(project.getPackaging()))) { - // nothing to be done for this type of packaging - skip = true; - getLog().info("skip generate goal for packaging " + project.getPackaging()); - return; - } - - skip=false; - - if (!outResource.exists()) { - outResource.mkdirs(); - } - - if (!outJava.exists()) { - outJava.mkdirs(); - } - - fixCompileSourceRoots(); - - DirectoryScanner ds; - ds = new DirectoryScanner(); - ds.setBasedir(src); - boolean noIncludes = includes == null || includes.length == 0; - ds.setIncludes(noIncludes ? INCLUDES : includes); - ds.scan(); - String[] files = ds.getIncludedFiles(); - if (verbose) { - getLog().info("jaxx - discover " + files.length + " jaxx file(s). "); - } - - updater = (MirroredFileUpdater) FileUpdaterHelper.newJaxxFileUpdater(src, outJava); - - if (force) { - // we will regenerate all files - this.files = files; - } else { - // filter files - List<String> listFiles = new ArrayList<String>(); - - for (String file : files) { - if (updater.isFileUpToDate(new File(src, file))) { - if (verbose) { - getLog().info("jaxx - skip file [" + file + "]."); - } - } else { - if (verbose) { - getLog().info("jaxx - will generate file [" + file + "]."); - } - listFiles.add(file); - } - } - this.files = listFiles.toArray(new String[listFiles.size()]); - } - - - options = toCompilerOptions(); - - if (verbose) { - printInit(); - } - - } - - public CompilerOptions toCompilerOptions() { - CompilerOptions result = new CompilerOptions(); - result.setClassPath(src.getPath()); - if (javaOpts != null && !"".equals(javaOpts)) { - result.setJavacOpts(javaOpts); - } - result.setKeepJavaFiles(true); - result.setOptimize(optimize); - result.setJavacTargetDirectory(outClass); - result.setTargetDirectory(outJava); - result.setVerbose(verbose); - result.setI18nable(i18nable); - result.setAddLogger(addLogger); - return result; - } - - public void execute() throws MojoExecutionException, MojoFailureException { - - init(); - - if (skip) { - if (verbose) { - getLog().info("jaxx - skip!"); - } - return; - } - - if (files.length == 0) { - getLog().info("jaxx - no jaxx file to treate. "); - return; - } - - getLog().info("jaxx - will generate " + this.files.length + " jaxx file(s). "); - - try { - - // force compiler init from here, not in a static block - TagManager.reset(verbose); - - if (!JAXXCompiler.compile(src, files, options)) { - throw new MojoFailureException("Aborting due to errors reported by jaxxc"); - } - - } catch (Exception e) { - getLog().error(e); - Throwable e2 = e; - while (e2.getCause() != null) { - e2 = e.getCause(); - } - getLog().error(e2); - - throw new MojoExecutionException(e.getMessage(), e); - } - - } - - protected void fixCompileSourceRoots() { - //fixme should remove this silly test when we will make real maven plugin tests :) - if (project != null) { - if (!project.getCompileSourceRoots().contains(outJava.getPath())) { - project.addCompileSourceRoot(outJava.getPath()); - } - } - } - - @SuppressWarnings({"unchecked"}) - protected URLClassLoader initClassLoader(MavenProject project, Log log) { - URLClassLoader loader = null; - if (project != null) { - URLClassLoader result; - try { - Set<Artifact> compileClasspathElements = project.getArtifacts(); - URL[] url = new URL[compileClasspathElements.size() + 1]; - url[0] = outClass.toURI().toURL(); - int i = 1; - for (Artifact artifact : compileClasspathElements) { - File file = new File(artifact.getFile().getAbsolutePath()); - if (file.getName().endsWith(".jar")) { - url[i] = new URL("jar", "", file.toURI().toURL().toString() + "!/"); - } else { - url[i] = file.toURI().toURL(); - } - i++; - } - //ClassLoader parent = Thread.currentThread().getContextClassLoader(); - if (compileClasspathElements.size() == 0) { - result = new URLClassLoader(url, getClass().getClassLoader()); - } else { - result = new URLClassLoader(url, getClass().getClassLoader()); - } - } catch (MalformedURLException eee) { - throw new RuntimeException("Can't create ClassLoader for script, bad directory: " + outClass + " for reason " + eee.getMessage(), eee); - } catch (IOException e) { - throw new RuntimeException("Can't create ClassLoader for script, bad directory: " + outClass + " for reason " + e.getMessage(), e); - } - loader = result; - } - if (verbose && loader != null) { - for (URL entry : loader.getURLs()) { - log.info("outClass url " + entry); - } - } - return loader; - } - - protected void printInit() { - getLog().info(options.toString()); - getLog().info("includes : " + Arrays.toString(includes)); - for (String file : files) { - getLog().info("will generate " + file); - } - - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - getLog().info(cl.toString()); - if (cl.getClass().getSimpleName().equals("RealmClassLoader")) { - try { - java.lang.reflect.Method m = cl.getClass().getDeclaredMethod("getURLs"); - m.setAccessible(true); - URL[] urls = (URL[]) m.invoke(cl); - - for (URL url : urls) { - getLog().info("url in class loader " + url); - } - } catch (Exception e) { - getLog().warn("??? : " + e.getMessage(), e); - } - } - - //fixme should remove this silly test when we will make real maven plugin tests :) - if (getPluginContext() != null) { - for (Object e : getPluginContext().keySet()) { - getLog().info("pluginContext " + e + " : " + getPluginContext().get(e)); - } - } - } - - public File getOutJava() { - return outJava; - } - - public void setOutJava(File outJava) { - this.outJava = outJava; - } - - public File getOutResource() { - return outResource; - } - - public void setOutResource(File outResource) { - this.outResource = outResource; - } - - public File getOutClass() { - return outClass; - } - - public void setOutClass(File outClass) { - this.outClass = outClass; - } - - public boolean isVerbose() { - return verbose; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - public File getSrc() { - return src; - } - - public void setSrc(File src) { - this.src = src; - } - - public boolean isOptimize() { - return optimize; - } - - public void setOptimize(boolean optimize) { - this.optimize = optimize; - } - - public String getJavaOpts() { - return javaOpts; - } - - public void setJavaOpts(String javaOpts) { - this.javaOpts = javaOpts; - } - - public String[] getIncludes() { - return includes; - } - - public void setIncludes(String[] includes) { - this.includes = includes; - } - - public String[] getFiles() { - return files; - } - - public void setFiles(String[] files) { - this.files = files; - } - - public boolean isForce() { - return force; - } - - public void setForce(boolean force) { - this.force = force; - } - - public boolean isI18nable() { - return i18nable; - } - - public void setI18nable(boolean i18nable) { - this.i18nable = i18nable; - } - - public MirroredFileUpdater getUpdater() { - return updater; - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java (from rev 971, lutinjaxx/trunk/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,464 @@ +/* *##% + * Copyright (C) 2007 + * JaxxPlugin, Code Lutin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +package org.codelutin.jaxx; + +import jaxx.compiler.CompilerOptions; +import jaxx.compiler.JAXXCompiler; +import jaxx.tags.TagManager; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.DirectoryScanner; +import org.codelutin.util.FileUpdaterHelper; +import org.codelutin.util.MirroredFileUpdater; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + * Classe permettant de transformer des sources jaxx vers du source java. + * + * @author chemit + * @goal generate + * @phase process-sources + */ +public class JaxxGeneratorMojo extends AbstractMojo { + + /** + * Dépendance du projet. + * + * @parameter default-value="${project}" + * @readonly + */ + protected MavenProject project; + + /** + * Repertoire de destination des fichiers java a generer. + * + * @parameter expression="${jaxx.outJava}" default-value="${basedir}/target/generated-sources/java" + */ + protected File outJava; + + /** + * chemin du repertoire de generation des resources. + * + * @parameter expression="${jaxx.outResource}" default-value="${basedir}/target/generated-sources/resources" + */ + protected File outResource; + + /** + * chemin du repertoire de compilation des resources. + * + * @parameter expression="${jaxx.outClass}" default-value="${basedir}/target/classes" + */ + protected File outClass; + + /** + * verbose flag + * + * @parameter expression="${jaxx.verbose}" default-value="false" + */ + protected boolean verbose; + + /** + * Repertoire sources des fichiers jaxx a generer. + * + * @parameter expression="${jaxx.src}" default-value="${maven.src.dir}/main/uimodel" + */ + protected File src; + + /** + * pour optimizer le code compile ou genere ? + * + * @parameter expression="${jaxx.optimize}" default-value="false" + */ + protected boolean optimize; + + /** + * les options de la compilation + * + * @parameter expression="${jaxx.javaOpts}" + */ + protected String javaOpts = null; + + /** + * pour filter les fichiers a traiter + * + * @parameter expression="${jaxx.includes}" + */ + protected String[] includes; + + /** + * pour filter les fichiers a ne pas traiter + * + * @parameter expression="${jaxx.excludes}" + */ + protected String[] excludes; + + /** + * to force generation of java source for any jaxx files with no timestamp checking. + * <p/> + * By default, never force generation. + * + * @parameter expression="${jaxx.force}" default-value="false" + */ + protected boolean force; + + /** + * to make compiler i18nable, says add the {@link org.codelutin.i18n.I18n#_(String, Object[])} method + * invocation on {@link jaxx.compiler.I18nHelper#I18N_ATTRIBUTES} attributes. + * + * @parameter expression="${jaxx.i18nable}" default-value="true" + * @see jaxx.compiler.I18nHelper + */ + protected boolean i18nable; + + + /** + * flag to add logger to each generated jaxx file. + * <p/> + * By default, always add it. + * + * @parameter expression="${jaxx.addLogger}" default-value="true" + */ + protected boolean addLogger; + + protected String[] files; + + private static final String[] INCLUDES = {"**\\/*.jaxx"}; + + protected CompilerOptions options; + + protected MirroredFileUpdater updater; + + protected boolean skip = true; + + protected void init() { + + if (project!=null && ("pom".equals(project.getPackaging()) || "site".equals(project.getPackaging()))) { + // nothing to be done for this type of packaging + skip = true; + getLog().info("skip generate goal for packaging " + project.getPackaging()); + return; + } + + skip=false; + + if (!outResource.exists()) { + outResource.mkdirs(); + } + + if (!outJava.exists()) { + outJava.mkdirs(); + } + + fixCompileSourceRoots(); + + DirectoryScanner ds; + ds = new DirectoryScanner(); + ds.setBasedir(src); + boolean noIncludes = includes == null || includes.length == 0; + ds.setIncludes(noIncludes ? INCLUDES : includes); + + if (excludes!=null && excludes.length>0) { + ds.setExcludes(excludes); + } + + ds.scan(); + String[] files = ds.getIncludedFiles(); + if (verbose) { + getLog().info("jaxx - discover " + files.length + " jaxx file(s). "); + } + + updater = (MirroredFileUpdater) FileUpdaterHelper.newJaxxFileUpdater(src, outJava); + + if (force) { + // we will regenerate all files + this.files = files; + } else { + // filter files + List<String> listFiles = new ArrayList<String>(); + + for (String file : files) { + if (updater.isFileUpToDate(new File(src, file))) { + if (verbose) { + getLog().info("jaxx - skip file [" + file + "]."); + } + } else { + if (verbose) { + getLog().info("jaxx - will generate file [" + file + "]."); + } + listFiles.add(file); + } + } + this.files = listFiles.toArray(new String[listFiles.size()]); + } + + + options = toCompilerOptions(); + + if (verbose) { + printInit(); + } + + } + + public CompilerOptions toCompilerOptions() { + CompilerOptions result = new CompilerOptions(); + result.setClassPath(src.getPath()); + if (javaOpts != null && !"".equals(javaOpts)) { + result.setJavacOpts(javaOpts); + } + result.setKeepJavaFiles(true); + result.setOptimize(optimize); + result.setJavacTargetDirectory(outClass); + result.setTargetDirectory(outJava); + result.setVerbose(verbose); + result.setI18nable(i18nable); + result.setAddLogger(addLogger); + return result; + } + + public void execute() throws MojoExecutionException, MojoFailureException { + + init(); + + if (skip) { + if (verbose) { + getLog().info("jaxx - skip!"); + } + return; + } + + if (files.length == 0) { + getLog().info("jaxx - no jaxx file to treate. "); + return; + } + + doAction(); + + } + + public void doAction() throws MojoExecutionException { + getLog().info("jaxx - will generate " + this.files.length + " jaxx file(s). "); + + try { + + // force compiler init from here, not in a static block + TagManager.reset(verbose); + + if (!JAXXCompiler.compile(src, files, options)) { + throw new MojoFailureException("Aborting due to errors reported by jaxxc"); + } + + } catch (Exception e) { + getLog().error(e); + Throwable e2 = e; + while (e2.getCause() != null) { + e2 = e.getCause(); + } + getLog().error(e2); + + throw new MojoExecutionException(e.getMessage(), e); + } + } + + protected void fixCompileSourceRoots() { + //fixme should remove this silly test when we will make real maven plugin tests :) + if (project != null) { + if (!project.getCompileSourceRoots().contains(outJava.getPath())) { + project.addCompileSourceRoot(outJava.getPath()); + } + } + } + + @SuppressWarnings({"unchecked"}) + protected URLClassLoader initClassLoader(MavenProject project, Log log) { + URLClassLoader loader = null; + if (project != null) { + URLClassLoader result; + try { + Set<Artifact> compileClasspathElements = project.getArtifacts(); + URL[] url = new URL[compileClasspathElements.size() + 1]; + url[0] = outClass.toURI().toURL(); + int i = 1; + for (Artifact artifact : compileClasspathElements) { + File file = new File(artifact.getFile().getAbsolutePath()); + if (file.getName().endsWith(".jar")) { + url[i] = new URL("jar", "", file.toURI().toURL().toString() + "!/"); + } else { + url[i] = file.toURI().toURL(); + } + i++; + } + //ClassLoader parent = Thread.currentThread().getContextClassLoader(); + if (compileClasspathElements.size() == 0) { + result = new URLClassLoader(url, getClass().getClassLoader()); + } else { + result = new URLClassLoader(url, getClass().getClassLoader()); + } + } catch (MalformedURLException eee) { + throw new RuntimeException("Can't create ClassLoader for script, bad directory: " + outClass + " for reason " + eee.getMessage(), eee); + } catch (IOException e) { + throw new RuntimeException("Can't create ClassLoader for script, bad directory: " + outClass + " for reason " + e.getMessage(), e); + } + loader = result; + } + if (verbose && loader != null) { + for (URL entry : loader.getURLs()) { + log.info("outClass url " + entry); + } + } + return loader; + } + + protected void printInit() { + getLog().info(options.toString()); + getLog().info("includes : " + Arrays.toString(includes)); + for (String file : files) { + getLog().info("will generate " + file); + } + + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + getLog().info(cl.toString()); + if (cl.getClass().getSimpleName().equals("RealmClassLoader")) { + try { + java.lang.reflect.Method m = cl.getClass().getDeclaredMethod("getURLs"); + m.setAccessible(true); + URL[] urls = (URL[]) m.invoke(cl); + + for (URL url : urls) { + getLog().info("url in class loader " + url); + } + } catch (Exception e) { + getLog().warn("??? : " + e.getMessage(), e); + } + } + + //fixme should remove this silly test when we will make real maven plugin tests :) + if (getPluginContext() != null) { + for (Object e : getPluginContext().keySet()) { + getLog().info("pluginContext " + e + " : " + getPluginContext().get(e)); + } + } + } + + public File getOutJava() { + return outJava; + } + + public void setOutJava(File outJava) { + this.outJava = outJava; + } + + public File getOutResource() { + return outResource; + } + + public void setOutResource(File outResource) { + this.outResource = outResource; + } + + public File getOutClass() { + return outClass; + } + + public void setOutClass(File outClass) { + this.outClass = outClass; + } + + public boolean isVerbose() { + return verbose; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + public File getSrc() { + return src; + } + + public void setSrc(File src) { + this.src = src; + } + + public boolean isOptimize() { + return optimize; + } + + public void setOptimize(boolean optimize) { + this.optimize = optimize; + } + + public String getJavaOpts() { + return javaOpts; + } + + public void setJavaOpts(String javaOpts) { + this.javaOpts = javaOpts; + } + + public String[] getIncludes() { + return includes; + } + + public void setIncludes(String[] includes) { + this.includes = includes; + } + + public String[] getFiles() { + return files; + } + + public void setFiles(String[] files) { + this.files = files; + } + + public boolean isForce() { + return force; + } + + public void setForce(boolean force) { + this.force = force; + } + + public boolean isI18nable() { + return i18nable; + } + + public void setI18nable(boolean i18nable) { + this.i18nable = i18nable; + } + + public MirroredFileUpdater getUpdater() { + return updater; + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,103 +0,0 @@ -package org.codelutin.jaxx; - -import junit.framework.TestCase; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.maven.it.Verifier; -import org.apache.maven.it.VerificationException; -import org.codehaus.plexus.util.FileUtils; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** @author chemit */ -public class BuildExamples extends TestCase { - - protected static final Log log = LogFactory.getLog(BuildExamples.class); - - protected File srcDir; - - protected File destDir; - - protected File siteDir; - protected File siteDestDir; - - protected Verifier verifier; - - protected File getBasedir() { - String b = System.getenv("basedir"); - if (b == null) { - b = new File("").getAbsolutePath(); - } - return new File(b); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - log.info("start " + getName()); - String dirname = getName().substring(4); - - srcDir = new File(getBasedir(), "src" + File.separator + "examples" + File.separator + dirname); - destDir = new File(getBasedir(), "target" + File.separator + "examples" + File.separator + dirname); - siteDestDir = new File(getBasedir(), "target" + File.separator + "generated-site" + File.separator + "resources" + File.separator + "examples"); - siteDir = new File(destDir, "target" + File.separator + "jnlp"); - - destDir.mkdirs(); - - FileUtils.copyDirectoryStructure(srcDir, destDir); - - verifier = new Verifier(destDir.getAbsolutePath(), true); - - List<String> cliOptions = new ArrayList<String>(); - cliOptions.add("-Dmaven.verbose=true"); - verifier.setCliOptions(cliOptions); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - srcDir = destDir = null; - if (verifier != null) { - verifier.resetStreams(); - verifier = null; - } - } - - /** - * fixme : make this test works again. - * - * @throws Exception if any - */ - public void estComponents() throws Exception { - buildExample(); - } - - public void testCalculator() throws Exception { - buildExample(); - } - - public void testCounter() throws Exception { - buildExample(); - } - - public void testLabelStyle() throws Exception { - buildExample(); - } - - public void testValidation() throws Exception { - buildExample(); - } - - protected void buildExample() throws VerificationException, IOException { - verifier.executeGoals(Arrays.asList("jaxx:generate", "package")); - verifier.verifyErrorFreeLog(); - FileUtils.copyDirectory(new File(siteDir, "lib"), new File(siteDestDir,"lib")); - FileUtils.copyDirectory(siteDir, siteDestDir,"*.jnlp",""); - } - - -} Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java (from rev 969, lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,106 @@ +package org.codelutin.jaxx; + +import junit.framework.TestCase; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.maven.it.VerificationException; +import org.apache.maven.it.Verifier; +import org.codehaus.plexus.util.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author chemit + * @deprecated This goal is not ny longer used : we have specific maven modules to build examples... + */ +public abstract class BuildExamples extends TestCase { + + protected static final Log log = LogFactory.getLog(BuildExamples.class); + + protected File srcDir; + + protected File destDir; + + protected File siteDir; + protected File siteDestDir; + + protected Verifier verifier; + + protected File getBasedir() { + String b = System.getenv("basedir"); + if (b == null) { + b = new File("").getAbsolutePath(); + } + return new File(b); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + log.info("start " + getName()); + String dirname = getName().substring(4); + + srcDir = new File(getBasedir(), "src" + File.separator + "examples" + File.separator + dirname); + destDir = new File(getBasedir(), "target" + File.separator + "examples" + File.separator + dirname); + siteDestDir = new File(getBasedir(), "target" + File.separator + "generated-site" + File.separator + "resources" + File.separator + "examples"); + siteDir = new File(destDir, "target" + File.separator + "jnlp"); + + destDir.mkdirs(); + + FileUtils.copyDirectoryStructure(srcDir, destDir); + + verifier = new Verifier(destDir.getAbsolutePath(), true); + + List<String> cliOptions = new ArrayList<String>(); + cliOptions.add("-Dmaven.verbose=true"); + verifier.setCliOptions(cliOptions); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + srcDir = destDir = null; + if (verifier != null) { + verifier.resetStreams(); + verifier = null; + } + } + + /** + * fixme : make this test works again. + * + * @throws Exception if any + */ + public void estComponents() throws Exception { + buildExample(); + } + + public void testCalculator() throws Exception { + buildExample(); + } + + public void testCounter() throws Exception { + buildExample(); + } + + public void testLabelStyle() throws Exception { + buildExample(); + } + + public void testValidation() throws Exception { + buildExample(); + } + + protected void buildExample() throws VerificationException, IOException { + verifier.executeGoals(Arrays.asList("jaxx:generate", "package")); + verifier.verifyErrorFreeLog(); + FileUtils.copyDirectory(new File(siteDir, "lib"), new File(siteDestDir, "lib")); + FileUtils.copyDirectory(siteDir, siteDestDir, "*.jnlp", ""); + } + + +} Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java 2008-10-21 07:31:05 UTC (rev 990) @@ -1,142 +0,0 @@ -package org.codelutin.jaxx; - -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; - -import java.io.File; - -public class CompilerTest extends JaxxBaseTest { - - protected String prefix = "src" + File.separator + "test" + File.separator + "resources" + File.separator + "testcases" + File.separator; - - public String getPrefix() { - return prefix; - } - - public void testInnerClasses() throws Exception { - mojo.execute(); - assertEquals(1, mojo.getFiles().length); - } - - public void testSpecialSubclassing() throws Exception { - mojo.execute(); - assertEquals(7, mojo.getFiles().length); - } - - public void testCSSTests() throws Exception { - mojo.execute(); - assertEquals(7, mojo.getFiles().length); - } - - public void testWithLog() throws Exception { - mojo.execute(); - String[] files = mojo.getFiles(); - assertEquals(2, files.length); - - String withLogFile; - String withnoLogFile; - if (files[0].endsWith("WithLog.jaxx")) { - withLogFile = files[0]; - withnoLogFile = files[1]; - } else { - withLogFile = files[1]; - withnoLogFile = files[0]; - } - checkPattern(mojo, "Log log = LogFactory.getLog(", true, withLogFile); - checkPattern(mojo, "import org.apache.commons.logging.Log;", true, withLogFile); - checkPattern(mojo, "import org.apache.commons.logging.LogFactory;", true, withLogFile); - - checkPattern(mojo, "Log log = LogFactory.getLog(", false, withnoLogFile); - checkPattern(mojo, "import org.apache.commons.logging.Log;", false, withnoLogFile); - checkPattern(mojo, "import org.apache.commons.logging.LogFactory;", false, withnoLogFile); - } - - public void testNoLog() throws Exception { - mojo.execute(); - String[] files = mojo.getFiles(); - assertEquals(2, files.length); - checkPattern(mojo, "Log log = LogFactory.getLog(", false, files); - checkPattern(mojo, "import org.apache.commons.logging.Log;", false, files); - checkPattern(mojo, "import org.apache.commons.logging.LogFactory;", false, files); - } - - public void testErrors() throws Exception { - // init mojo to get alls files to treate - mojo.init(); - String[] files = mojo.getFiles(); - // execute mjo on each jaxx file to produce the error - for (String file : files) { - mojo.setFiles(new String[]{file}); - try { - mojo.execute(); - // should never pass - fail(); - } catch (MojoExecutionException e) { - // ok jaxx compiler failed - assertTrue(true); - } catch (MojoFailureException e) { - // this exception should not appear - fail(); - } - } - } - - public void testInitializers() throws Exception { - mojo.execute(); - assertEquals(1, mojo.getFiles().length); - } - - public void testScript() throws Exception { - mojo.execute(); - assertEquals(1, mojo.getFiles().length); - } - - public void testOverridingDataBindings() throws Exception { - mojo.execute(); - assertEquals(3, mojo.getFiles().length); - } - - public void testClassReferences() throws Exception { - mojo.execute(); - assertEquals(6, mojo.getFiles().length); - } - - public void testForce() throws Exception { - - // first round, with force option so will generate theonly JButton.jaxx file - mojo.execute(); - String[] files = mojo.getFiles(); - assertEquals(1, files.length); - - File srcFile = new File(mojo.getSrc(), files[0]); - - File dstFile = mojo.getUpdater().getMirrorFile(srcFile); - - long oldTime = dstFile.lastModified(); - // second round, no force so will not the file - mojo.setForce(false); - mojo.execute(); - files = mojo.getFiles(); - assertEquals(0, files.length); - - Thread.sleep(1000); - - assertEquals(oldTime, mojo.getUpdater().getMirrorFile(srcFile).lastModified()); - - // three round : modify a source with no force option - srcFile.setLastModified(System.currentTimeMillis()); - - mojo.execute(); - files = mojo.getFiles(); - assertEquals(1, files.length); - - assertTrue(mojo.getUpdater().getMirrorFile(srcFile).lastModified() > oldTime); - - // last round, reforce file generation for an no modify source - mojo.setForce(true); - mojo.execute(); - files = mojo.getFiles(); - assertEquals(1, files.length); - assertTrue(mojo.getUpdater().getMirrorFile(srcFile).lastModified() > oldTime); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java (from rev 977, lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,238 @@ +package org.codelutin.jaxx; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerHelper; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.SystemStreamLog; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.Map; + +public class CompilerTest extends JaxxBaseTest { + + protected String prefix = "src" + File.separator + "test" + File.separator + "resources" + File.separator + "testcases" + File.separator; + + public String getPrefix() { + return prefix; + } + + public void testInnerClasses() throws Exception { + mojo.execute(); + assertEquals(1, mojo.getFiles().length); + } + + public void testSpecialSubclassing() throws Exception { + mojo.execute(); + assertEquals(7, mojo.getFiles().length); + } + + public void testCSSTests() throws Exception { + mojo.execute(); + assertEquals(7, mojo.getFiles().length); + } + + public void testWithLog() throws Exception { + mojo.execute(); + String[] files = mojo.getFiles(); + assertEquals(2, files.length); + + String withLogFile; + String withnoLogFile; + if (files[0].endsWith("WithLog.jaxx")) { + withLogFile = files[0]; + withnoLogFile = files[1]; + } else { + withLogFile = files[1]; + withnoLogFile = files[0]; + } + checkPattern(mojo, "Log log = LogFactory.getLog(", true, withLogFile); + checkPattern(mojo, "import org.apache.commons.logging.Log;", true, withLogFile); + checkPattern(mojo, "import org.apache.commons.logging.LogFactory;", true, withLogFile); + + checkPattern(mojo, "Log log = LogFactory.getLog(", false, withnoLogFile); + checkPattern(mojo, "import org.apache.commons.logging.Log;", false, withnoLogFile); + checkPattern(mojo, "import org.apache.commons.logging.LogFactory;", false, withnoLogFile); + } + + public void testNoLog() throws Exception { + mojo.execute(); + String[] files = mojo.getFiles(); + assertEquals(2, files.length); + checkPattern(mojo, "Log log = LogFactory.getLog(", false, files); + checkPattern(mojo, "import org.apache.commons.logging.Log;", false, files); + checkPattern(mojo, "import org.apache.commons.logging.LogFactory;", false, files); + } + + public void testErrors() throws Exception { + // init mojo to get alls files to treate + mojo.init(); + String[] files = mojo.getFiles(); + assertEquals(34, mojo.getFiles().length); + mojo.setLog(new SystemStreamLog() { + @Override + public boolean isErrorEnabled() { + return false; + } + + @Override + public void error(Throwable error) { + //do nothing + } + + @Override + public void error(CharSequence content) { + //do nothing + } + + @Override + public void error(CharSequence content, Throwable error) { + //do nothing + } + }); + Field fieldCompilers = JAXXCompilerHelper.class.getDeclaredField("compilers"); + Field fieldErrorCount = JAXXCompilerHelper.class.getDeclaredField("errorCount"); + + fieldCompilers.setAccessible(true); + fieldErrorCount.setAccessible(true); + + // execute mjo on each jaxx file to produce the error + for (String file : files) { + getLog().info("test bad file " + file); + mojo.setFiles(new String[]{file}); + try { + mojo.doAction(); + // should never pass + fail(); + } catch (MojoExecutionException e) { + // ok jaxx compiler failed + assertTrue(true); + + Map<String, JAXXCompiler> compilers = (Map<String, JAXXCompiler>) fieldCompilers.get(null); + assertEquals(1, compilers.size()); + JAXXCompiler compiler = compilers.values().iterator().next(); + Integer nberrors = (Integer) fieldErrorCount.get(compiler); + assertTrue(nberrors > 0); + } + } + } + + public void testInitializers() throws Exception { + mojo.execute(); + assertEquals(1, mojo.getFiles().length); + } + + public void testScript() throws Exception { + mojo.execute(); + assertEquals(1, mojo.getFiles().length); + } + + public void testOverridingDataBindings() throws Exception { + mojo.execute(); + assertEquals(3, mojo.getFiles().length); + } + + public void testClassReferences() throws Exception { + mojo.execute(); + assertEquals(6, mojo.getFiles().length); + } + + public void testForce() throws Exception { + + // first round, with force option so will generate theonly JButton.jaxx file + mojo.execute(); + String[] files = mojo.getFiles(); + assertEquals(1, files.length); + + File srcFile = new File(mojo.getSrc(), files[0]); + + File dstFile = mojo.getUpdater().getMirrorFile(srcFile); + + long oldTime = dstFile.lastModified(); + // second round, no force so will not the file + mojo.setForce(false); + mojo.execute(); + files = mojo.getFiles(); + assertEquals(0, files.length); + + Thread.sleep(1000); + + assertEquals(oldTime, mojo.getUpdater().getMirrorFile(srcFile).lastModified()); + + // three round : modify a source with no force option + srcFile.setLastModified(System.currentTimeMillis()); + + mojo.execute(); + files = mojo.getFiles(); + assertEquals(1, files.length); + + assertTrue(mojo.getUpdater().getMirrorFile(srcFile).lastModified() > oldTime); + + // last round, reforce file generation for an no modify source + mojo.setForce(true); + mojo.execute(); + files = mojo.getFiles(); + assertEquals(1, files.length); + assertTrue(mojo.getUpdater().getMirrorFile(srcFile).lastModified() > oldTime); + } + + public void testValidatorOk() throws Exception { + mojo.execute(); + assertEquals(1, mojo.getFiles().length); + + } + + public void testValidatorErrors() throws Exception { + // init mojo to get alls files to treate + mojo.init(); + String[] files = mojo.getFiles(); + assertEquals(16, mojo.getFiles().length); + mojo.setLog(new SystemStreamLog() { + @Override + public boolean isErrorEnabled() { + return false; + } + + @Override + public void error(Throwable error) { + //do nothing + } + + @Override + public void error(CharSequence content) { + //do nothing + } + + @Override + public void error(CharSequence content, Throwable error) { + //do nothing + } + }); + Field fieldCompilers = JAXXCompilerHelper.class.getDeclaredField("compilers"); + Field fieldErrorCount = JAXXCompilerHelper.class.getDeclaredField("errorCount"); + + fieldCompilers.setAccessible(true); + fieldErrorCount.setAccessible(true); + + // execute mjo on each jaxx file to produce the error + for (String file : files) { + getLog().info("test bad file " + file); + mojo.setFiles(new String[]{file}); + try { + mojo.doAction(); + // should never pass + fail(); + } catch (MojoExecutionException e) { + // ok jaxx compiler failed + assertTrue(true); + + Map<String, JAXXCompiler> compilers = (Map<String, JAXXCompiler>) fieldCompilers.get(null); + assertEquals(1, compilers.size()); + JAXXCompiler compiler = compilers.values().iterator().next(); + Integer nberrors = (Integer) fieldErrorCount.get(compiler); + assertEquals(1, nberrors.intValue()); + } + } + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - <build> - <plugins> - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-jaxx-plugin</artifactId> - <configuration> - <src>${basedir}/src/test/resources</src> - <outJava>${basedir}/target/it-generated-source/java</outJava> - <outResource>${basedir}/target/it-generated-source/resources</outResource> - <force>true</force> - <includes> - <value>**/errors/*.jaxx</value> - </includes> - </configuration> - </plugin> - </plugins> - </build> -</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml (from rev 968, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/Errors.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + <build> + <plugins> + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-jaxx-plugin</artifactId> + <configuration> + <src>${basedir}/src/test/resources</src> + <outJava>${basedir}/target/it-generated-source/java</outJava> + <outResource>${basedir}/target/it-generated-source/resources</outResource> + <force>true</force> + <includes> + <value>**/errors/*.jaxx</value> + </includes> + <excludes> + <value>**/validator/errors/*.jaxx</value> + </excludes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorErrors.xml (from rev 968, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/ValidatorErrors.xml) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorErrors.xml (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorErrors.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + <build> + <plugins> + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-jaxx-plugin</artifactId> + <configuration> + <src>${basedir}/src/test/resources</src> + <outJava>${basedir}/target/it-generated-source/java</outJava> + <outResource>${basedir}/target/it-generated-source/resources</outResource> + <force>true</force> + <includes> + <value>**/validator/errors/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorOk.xml (from rev 968, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/ValidatorOk.xml) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorOk.xml (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/ValidatorOk.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + <build> + <plugins> + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-jaxx-plugin</artifactId> + <configuration> + <src>${basedir}/src/test/resources</src> + <outJava>${basedir}/target/it-generated-source/java</outJava> + <outResource>${basedir}/target/it-generated-source/resources</outResource> + <force>true</force> + <includes> + <value>**/validator/ok/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -1 +0,0 @@ -<JButton id='testId' text='test.text'/> \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx (from rev 986, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/force/JButton.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1 @@ +<javax.swing.JButton id='testId' text='test.text'/> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -1 +0,0 @@ -<JButton id='testId' text='test.text'/> \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx (from rev 986, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/text/JButton.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1 @@ +<javax.swing.JButton id='testId' text='test.text'/> \ No newline at end of file Deleted: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -1 +0,0 @@ -<JButton id='testId' toolTipText='test.toolTipText'/> \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx (from rev 986, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx) =================================================================== --- lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx (rev 0) +++ lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/i18n/tooltiptext/JButton.jaxx 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1 @@ +<javax.swing.JButton id='testId' toolTipText='test.toolTipText'/> \ No newline at end of file Copied: lutinjaxx/tags/0.5/maven-jaxx-plugin/src/test/resources/testcases/validator (from rev 968, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator) Deleted: lutinjaxx/tags/0.5/pom.xml =================================================================== --- lutinjaxx/trunk/pom.xml 2008-10-17 16:44:54 UTC (rev 948) +++ lutinjaxx/tags/0.5/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -1,213 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>lutinproject</artifactId> - <version>3.0</version> - </parent> - - <artifactId>lutinjaxx</artifactId> - - <modules> - <module>jaxx-util</module> - <module>jaxx-core</module> - <module>jaxx-swing-action</module> - <module>maven-jaxx-plugin</module> - <!--module>jaxx-example</module--> - </modules> - - <dependencies> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinutil</artifactId> - </dependency> - </dependencies> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>lutinjaxx</name> - <version>0.5-SNAPSHOT</version> - <description>Jaxx lutin library main pom</description> - <inceptionYear>2008</inceptionYear> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>pom</packaging> - - <properties> - - <license-switcher.version>0.5-SNAPSHOT</license-switcher.version> - - <!-- current version --> - <current.version>0.5-SNAPSHOT</current.version> - - <!-- id du projet du labs --> - <labs.id>38</labs.id> - - <labs.project>buix</labs.project> - - <!-- override this property to define scm url property --> - <scm.url.son> - http://${labs.host}/plugins/scmsvn/viewcvs.php/lutinjaxx/trunk/${pom.artifactId}/?root=${labs.project} - </scm.url.son> - - <!-- BEWARE, will be suffixed by /${pom.artifactId} by inheritance --> - <scm.developerConnection.son> - scm:svn:svn+ssh://${username}@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/${pom.artifactId} - </scm.developerConnection.son> - - <!-- BEWARE, will be suffixed by /${pom.artifactId} by inheritance --> - <scm.connection.son> - scm:svn:svn://anonymous@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/${pom.artifactId} - </scm.connection.son> - - </properties> - - <build> - - <pluginManagement> - <plugins> - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-i18n-plugin</artifactId> - <executions> - <execution> - <goals> - <goal>parserJava</goal> - <goal>gen</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </pluginManagement> - - <plugins> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-javadoc-plugin</artifactId> - <executions> - - <execution> - <phase>pre-site</phase> - </execution> - </executions> - </plugin> - - </plugins> - - </build> - - <dependencyManagement> - <dependencies> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinutil</artifactId> - <version>0.31</version> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-util</artifactId> - <version>${current.version}</version> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-core</artifactId> - <version>${current.version}</version> - </dependency> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-swing-action</artifactId> - <version>${current.version}</version> - </dependency> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-example</artifactId> - <version>${current.version}</version> - </dependency> - - <dependency> - <groupId>com.sun</groupId> - <artifactId>dt</artifactId> - <version>${java.version}</version> - <scope>system</scope> - <systemPath>${java.home}/../lib/dt.jar</systemPath> - </dependency> - - <dependency> - <groupId>javax.help</groupId> - <artifactId>javahelp</artifactId> - <version>2.0.02</version> - </dependency> - - <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-plugin-api</artifactId> - <version>2.0.4</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-project</artifactId> - <version>2.0.4</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinpluginutil</artifactId> - <version>0.2</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>com.opensymphony</groupId> - <artifactId>xwork</artifactId> - <version>2.1.1-cl_20081015</version> - <!--version>2.1.1</version--> - </dependency> - - <dependency> - <groupId>org.swinglabs</groupId> - <artifactId>jxlayer</artifactId> - <version>3.0.1</version> - </dependency> - - </dependencies> - </dependencyManagement> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${maven.scm.connection}</connection> - <developerConnection>${maven.scm.developerConnection}</developerConnection> - <url>${maven.scm.url}</url> - </scm> - - <profiles> - <profile> - <id>example</id> - <modules> - <module>jaxx-example</module> - </modules> - </profile> - </profiles> - -</project> Copied: lutinjaxx/tags/0.5/pom.xml (from rev 989, lutinjaxx/trunk/pom.xml) =================================================================== --- lutinjaxx/tags/0.5/pom.xml (rev 0) +++ lutinjaxx/tags/0.5/pom.xml 2008-10-21 07:31:05 UTC (rev 990) @@ -0,0 +1,216 @@ +<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"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>lutinproject</artifactId> + <version>3.0</version> + </parent> + + <artifactId>lutinjaxx</artifactId> + + <modules> + <module>jaxx-util</module> + <module>jaxx-core</module> + <module>jaxx-swing-action</module> + <module>maven-jaxx-plugin</module> + <!--module>jaxx-example</module--> + </modules> + + <dependencies> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + </dependency> + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>lutinjaxx</name> + <version>0.5</version> + <description>Jaxx lutin library main pom</description> + <inceptionYear>2008</inceptionYear> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>pom</packaging> + + <properties> + + <!--license-switcher.version>0.5-SNAPSHOT</license-switcher.version--> + + <!-- current version --> + <current.version>0.5-SNAPSHOT</current.version> + + <!-- id du projet du labs --> + <labs.id>38</labs.id> + + <labs.project>buix</labs.project> + + <!-- override this property to define scm url property --> + <scm.url.son> + http://${labs.host}/plugins/scmsvn/viewcvs.php/lutinjaxx/trunk/${pom.artifactId}/?root=${labs.project} + </scm.url.son> + + <!-- BEWARE, will be suffixed by /${pom.artifactId} by inheritance --> + <scm.developerConnection.son> + scm:svn:svn+ssh://${username}@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/${pom.artifactId} + </scm.developerConnection.son> + + <!-- BEWARE, will be suffixed by /${pom.artifactId} by inheritance --> + <scm.connection.son> + scm:svn:svn://anonymous@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/${pom.artifactId} + </scm.connection.son> + + </properties> + + <build> + + <pluginManagement> + <plugins> + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </pluginManagement> + + <plugins> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <executions> + + <execution> + <phase>pre-site</phase> + </execution> + </executions> + </plugin> + + </plugins> + + </build> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + <version>0.31</version> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-util</artifactId> + <version>0.5</version> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-core</artifactId> + <version>0.5</version> + </dependency> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-swing-action</artifactId> + <version>0.5</version> + </dependency> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-example</artifactId> + <version>0.5</version> + </dependency> + + <dependency> + <groupId>com.sun</groupId> + <artifactId>dt</artifactId> + <version>${java.version}</version> + <scope>system</scope> + <systemPath>${java.home}/../lib/dt.jar</systemPath> + </dependency> + + <dependency> + <groupId>javax.help</groupId> + <artifactId>javahelp</artifactId> + <version>2.0.02</version> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>2.0.4</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.0.4</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinpluginutil</artifactId> + <version>0.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>com.opensymphony</groupId> + <artifactId>xwork</artifactId> + <version>2.1.1-cl_20081015</version> + <!--version>2.1.1</version--> + </dependency> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + <version>3.0.1</version> + </dependency> + + </dependencies> + </dependencyManagement> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.5</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.5?root=buix</url> + </scm> + + <profiles> + <!-- by default example are included, use -Ddoexample=false to disable examples --> + <profile> + <activation> + <property> + <name>doexample</name> + <value>!false</value> + </property> + </activation> + <modules> + <module>jaxx-example</module> + </modules> + </profile> + </profiles> + +</project> \ No newline at end of file
participants (1)
-
tchemit@users.labs.libre-entreprise.org