Author: tchemit Date: 2008-12-10 12:03:56 +0000 (Wed, 10 Dec 2008) New Revision: 1063 Added: lutinjaxx/tags/0.7/ lutinjaxx/tags/0.7/README.txt lutinjaxx/tags/0.7/changelog.txt lutinjaxx/tags/0.7/jaxx-core/README.txt lutinjaxx/tags/0.7/jaxx-core/changelog.txt lutinjaxx/tags/0.7/jaxx-core/pom.xml lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/Base64Coder.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/DefaultInitializer.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataSource.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGeneratorConstants.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaField.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Rule.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Stylesheet.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Decorator.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXAction.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContextEntryDef.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Util.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/CardLayout2.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeCellRenderer.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapterWithCardLayout.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationUtil.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableRenderer.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/ExcludeFieldValidatorHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/ColorConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeManager.java lutinjaxx/tags/0.7/jaxx-core/src/main/resources/icons/ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/BeanValidator.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/I18n.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Interface.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JAXXContext.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JavaBean.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/NavigationTreeModel.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Todo.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/index.rst lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/DefaultJAXXContextTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/resources/log4j.properties lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/README.txt lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/changelog.txt lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/pom.xml lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/images/BeanDataBinding-screenshot.png lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst lutinjaxx/tags/0.7/jaxx-example/Calculator/README.txt lutinjaxx/tags/0.7/jaxx-example/Calculator/changelog.txt lutinjaxx/tags/0.7/jaxx-example/Calculator/pom.xml lutinjaxx/tags/0.7/jaxx-example/Components/ lutinjaxx/tags/0.7/jaxx-example/Components/README.txt lutinjaxx/tags/0.7/jaxx-example/Components/changelog.txt lutinjaxx/tags/0.7/jaxx-example/Components/pom.xml lutinjaxx/tags/0.7/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx lutinjaxx/tags/0.7/jaxx-example/Counter/README.txt lutinjaxx/tags/0.7/jaxx-example/Counter/changelog.txt lutinjaxx/tags/0.7/jaxx-example/Counter/pom.xml lutinjaxx/tags/0.7/jaxx-example/LabelStyle/README.txt lutinjaxx/tags/0.7/jaxx-example/LabelStyle/changelog.txt lutinjaxx/tags/0.7/jaxx-example/LabelStyle/pom.xml lutinjaxx/tags/0.7/jaxx-example/README.txt lutinjaxx/tags/0.7/jaxx-example/Validation/README.txt lutinjaxx/tags/0.7/jaxx-example/Validation/changelog.txt lutinjaxx/tags/0.7/jaxx-example/Validation/pom.xml lutinjaxx/tags/0.7/jaxx-example/changelog.txt lutinjaxx/tags/0.7/jaxx-example/pom.xml lutinjaxx/tags/0.7/jaxx-swing-action/README.txt lutinjaxx/tags/0.7/jaxx-swing-action/changelog.txt lutinjaxx/tags/0.7/jaxx-swing-action/pom.xml lutinjaxx/tags/0.7/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java lutinjaxx/tags/0.7/jaxx-util/README.txt lutinjaxx/tags/0.7/jaxx-util/changelog.txt lutinjaxx/tags/0.7/jaxx-util/pom.xml lutinjaxx/tags/0.7/maven-jaxx-plugin/README.txt lutinjaxx/tags/0.7/maven-jaxx-plugin/changelog.txt lutinjaxx/tags/0.7/maven-jaxx-plugin/pom.xml lutinjaxx/tags/0.7/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/Bug1750Test.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/Bug_1750.xml lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTaist.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ErrorJaxxContextImplementorClass.xml lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/bug_1750/ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx lutinjaxx/tags/0.7/pom.xml Removed: lutinjaxx/tags/0.7/jaxx-core/changelog lutinjaxx/tags/0.7/jaxx-core/pom.xml lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/DefaultInitializer.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataSource.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaField.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Rule.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Stylesheet.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Util.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationtreeSelectionAdapterWithCardLayout.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/ColorConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeConverter.java lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeManager.java lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Todo.rst lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/index.rst lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/NavigationTreeModelTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java lutinjaxx/tags/0.7/jaxx-core/src/test/resources/log4j.properties lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/pom.xml lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/images/Validation-screenshot.png lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst lutinjaxx/tags/0.7/jaxx-example/Calculator/pom.xml lutinjaxx/tags/0.7/jaxx-example/Components/ lutinjaxx/tags/0.7/jaxx-example/Components/pom.xml lutinjaxx/tags/0.7/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx lutinjaxx/tags/0.7/jaxx-example/Counter/pom.xml lutinjaxx/tags/0.7/jaxx-example/LabelStyle/pom.xml lutinjaxx/tags/0.7/jaxx-example/Validation/pom.xml lutinjaxx/tags/0.7/jaxx-example/pom.xml lutinjaxx/tags/0.7/jaxx-swing-action/changelog lutinjaxx/tags/0.7/jaxx-swing-action/pom.xml lutinjaxx/tags/0.7/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java lutinjaxx/tags/0.7/jaxx-util/pom.xml lutinjaxx/tags/0.7/maven-jaxx-plugin/changelog lutinjaxx/tags/0.7/maven-jaxx-plugin/pom.xml lutinjaxx/tags/0.7/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTest.java lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/DuplicatedFieldInOtherValidator.jaxx lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/FieldComponentDuplicated2.jaxx lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx lutinjaxx/tags/0.7/pom.xml Log: [maven-release-plugin] copy for tag 0.7 Copied: lutinjaxx/tags/0.7 (from rev 1003, lutinjaxx/trunk) Copied: lutinjaxx/tags/0.7/README.txt (from rev 1057, lutinjaxx/trunk/README.txt) =================================================================== --- lutinjaxx/tags/0.7/README.txt (rev 0) +++ lutinjaxx/tags/0.7/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/changelog.txt (from rev 1061, lutinjaxx/trunk/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,3 @@ +0.7 chemit 200812?? + * 20081210 [chemit] use lutinutil 1.0 and lutinproject 3.2 + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-core/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Deleted: lutinjaxx/tags/0.7/jaxx-core/changelog =================================================================== --- lutinjaxx/trunk/jaxx-core/changelog 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/changelog 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,19 +0,0 @@ - ver-0-6 chemit 200811?? - * 20081027 [chemit] fix bug 1722 - * 20081027 [chemit] add conversion support in validator - * 20081025 [chemit] improve BeanValidator tag : - - add a errorList attribute for set a ErrorListMouseListener on the errorList - - add a beanInitializer attribute for set the validator's bean at runtime - - add a default errorListModel value 'errors' - * 20081025 [chemit] introduce JAXXInitialContext to fill JAXXContext at runtime before $initialize() method - * 20081024 [chemit] fix validator context lost if UI is launched from another thread - 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) Copied: lutinjaxx/tags/0.7/jaxx-core/changelog.txt (from rev 1060, lutinjaxx/trunk/jaxx-core/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,67 @@ + 0.7 chemit 200812?? +* 20081210 [chemit] - improve JAXXButtonGroup (add ActionChangeListener and toolTipText mecanism) +* 20081208 [chemit] - javabBean attribute use to initialize bean + - introduce Base64Coder to fix bug 1750 and control serailVersionUI (put them to 1L for the moment) + - introduce MultiJXPathDecorator + - add a resetAfterCompile parameter toCompilerOption to keep in test used compilers + + * 20081207 [chemit] use lutinproject 3.1 + - can exclude field from validator + * 20081202 [chemit] - add strategy for loading ui in NavigationTreeSelectionAdapter + - fix bug when searching for a inner class + + * 20081201 [chemit] - implements jaxx.runtime.JXPathDecorator + - add setcontextValue and removeContextValue on JAXXContextEntryDef + - introduce scope in BeanValidator (ERROR or WARNING) and related swing stuff + - only enter once in $initialize method in generated code + + 0.6 chemit 20081117 + * 20081118 [chemit] introduce NavigationUtil, save in context selected node + * 20081107 [chemit] improve data binding and code generation : + - make possible inheritance in binding + - add an attribute javaBean to an object : will generate a full java bean support property + - make possible binding to the javaBean added properties + - clean generated code + + * 20081105 [chemit] introduce a CardLayout2 to extends awt CardLayout + introduce a NavigationTreeModel + introduce a Decorator to render Object + propagate constructor JAXXContext(JAXXContext) in JAXXObject generation + begin of rst documentation + + * 20081104 [chemit] can add extra beanInfoSearchPath in SwingInitializer + * 20081104 [chemit] add jaxxContextImplementorClass in option to make possible use of other JAXXContext implementor. + * 20081102 [chemit] improve JAXXContext : + - introduce a JAXXContextEntryDef to qualify an entry of a JAXXContext + - do javadoc in JAXXContext + - add logic in DefaultJAXXContext : seek in parent context if entry not found + * 20081102 [chemit] improve tests : + - fix the last failed test from Jaxx original version :) + - dumps tests to JUnit4 :) + * 20081030 [chemit] improve BeanValidator : + - add full PropertyChangeEvent java-bean support and a property valid + - when remove bean from validator, must remove errors from model + - make possible to have a dynamic errorListModel in jaxx files + * 20081030 [chemit] improve JAXXContext : + - fix setContextValue bug when setting twice a same type for a same key + - implements a DefaultJAXXContext + - use this default implementation with delegate pattern in JAXXObject + * 20081030 [chemit] add JAXXAction contract to simplify init of ui with JAXXInitialContext + * 20081027 [chemit] fix bug 1722 + * 20081027 [chemit] add conversion support in validator + * 20081025 [chemit] improve BeanValidator tag : + - add a errorList attribute for set a ErrorListMouseListener on the errorList + - add a beanInitializer attribute for set the validator's bean at runtime + - add a default errorListModel value 'errors' + * 20081025 [chemit] introduce JAXXInitialContext to fill JAXXContext at runtime before $initialize() method + * 20081024 [chemit] fix validator context lost if UI is launched from another thread + 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.7/jaxx-core/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-core/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,69 +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.6-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.7/jaxx-core/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-core/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,65 @@ +<?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.7</version> + </parent> + + <artifactId>jaxx-core</artifactId> + + <dependencies> + + <!-- 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> + + <dependency> + <groupId>commons-jxpath</groupId> + <artifactId>commons-jxpath</artifactId> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>jaxx-core</name> + <description>Jaxx lutin library core</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + <packaging>jar</packaging> + + <build> + <defaultGoal>install</defaultGoal> + </build> + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-core</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-core</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-core?root=buix</url> + </scm> +</project> Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/Base64Coder.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/Base64Coder.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/Base64Coder.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/Base64Coder.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,240 @@ +package jaxx; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +/** + * A Base64 Encoder/Decoder. + * <p/> + * <p/> + * This class is used to encode and decode data in Base64 format as described in RFC 1521. + * <p/> + * <p/> + * This is "Open Source" software and released under the <a href="http://www.gnu.org/licenses/lgpl.html">GNU/LGPL</a> license.<br> + * It is provided "as is" without warranty of any kind.<br> + * Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.<br> + * Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br> + * <p/> + * <p/> + * Version history:<br> + * 2003-07-22 Christian d'Heureuse (chdh): Module created.<br> + * 2005-08-11 chdh: Lincense changed from GPL to LGPL.<br> + * 2006-11-21 chdh:<br> + * Method encode(String) renamed to encodeString(String).<br> + * Method decode(String) renamed to decodeString(String).<br> + * New method encode(byte[],int) added.<br> + * New method decode(String) added.<br> + */ + +public class Base64Coder { + + // Mapping table from 6-bit nibbles to Base64 characters. + private static char[] map1 = new char[64]; + + static { + int i = 0; + for (char c = 'A'; c <= 'Z'; c++) { + map1[i++] = c; + } + for (char c = 'a'; c <= 'z'; c++) { + map1[i++] = c; + } + for (char c = '0'; c <= '9'; c++) { + map1[i++] = c; + } + map1[i++] = '+'; + map1[i] = '/'; + } + + // Mapping table from Base64 characters to 6-bit nibbles. + private static byte[] map2 = new byte[128]; + + static { + for (int i = 0; i < map2.length; i++) { + map2[i] = -1; + } + for (int i = 0; i < 64; i++) { + map2[map1[i]] = (byte) i; + } + } + + /** + * Read the object from Base64 string. + * + * @param s the string representation of serialized object. + * @param gzip if gzip stream + * @return the deserialize object + * @throws java.io.IOException if any io pb + * @throws ClassNotFoundException if class not found ? + */ + public static Object deserialize(String s, boolean gzip) throws IOException, + ClassNotFoundException { + byte[] data = Base64Coder.decode(s); + InputStream stream = new ByteArrayInputStream(data); + if (gzip) { + stream = new GZIPInputStream(stream); + } + ObjectInputStream ois = new ObjectInputStream(stream); + Object o = ois.readObject(); + ois.close(); + return o; + } + + /** + * Write the object to a Base64 string. + * + * @param o the object to serialize + * @param gzip if gzip stream + * @return the string representation + * @throws java.io.IOException if any io pb + */ + public static String serialize(Object o, boolean gzip) throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + ObjectOutputStream oos; + if (gzip) { + oos = new ObjectOutputStream(new GZIPOutputStream(stream)); + } else { + oos = new ObjectOutputStream(stream); + } + oos.writeObject(o); + oos.close(); + return new String(Base64Coder.encode(stream.toByteArray())); + } + + /** + * Encodes a string into Base64 format. + * No blanks or line breaks are inserted. + * + * @param s a String to be encoded. + * @return A String with the Base64 encoded data. + */ + public static String encodeString(String s) { + return new String(encode(s.getBytes())); + } + + /** + * Encodes a byte array into Base64 format. + * No blanks or line breaks are inserted. + * + * @param in an array containing the data bytes to be encoded. + * @return A character array with the Base64 encoded data. + */ + public static char[] encode(byte[] in) { + return encode(in, in.length); + } + + /** + * Encodes a byte array into Base64 format. + * No blanks or line breaks are inserted. + * + * @param in an array containing the data bytes to be encoded. + * @param iLen number of bytes to process in <code>in</code>. + * @return A character array with the Base64 encoded data. + */ + public static char[] encode(byte[] in, int iLen) { + int oDataLen = (iLen * 4 + 2) / 3; // output length without padding + int oLen = ((iLen + 2) / 3) * 4; // output length including padding + char[] out = new char[oLen]; + int ip = 0; + int op = 0; + while (ip < iLen) { + int i0 = in[ip++] & 0xff; + int i1 = ip < iLen ? in[ip++] & 0xff : 0; + int i2 = ip < iLen ? in[ip++] & 0xff : 0; + int o0 = i0 >>> 2; + int o1 = ((i0 & 3) << 4) | (i1 >>> 4); + int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); + int o3 = i2 & 0x3F; + out[op++] = map1[o0]; + out[op++] = map1[o1]; + out[op] = op < oDataLen ? map1[o2] : '='; + op++; + out[op] = op < oDataLen ? map1[o3] : '='; + op++; + } + return out; + } + + /** + * Decodes a string from Base64 format. + * + * @param s a Base64 String to be decoded. + * @return A String containing the decoded data. + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. + */ + public static String decodeString(String s) { + return new String(decode(s)); + } + + /** + * Decodes a byte array from Base64 format. + * + * @param s a Base64 String to be decoded. + * @return An array containing the decoded data bytes. + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. + */ + public static byte[] decode(String s) { + return decode(s.toCharArray()); + } + + /** + * Decodes a byte array from Base64 format. + * No blanks or line breaks are allowed within the Base64 encoded data. + * + * @param in a character array containing the Base64 encoded data. + * @return An array containing the decoded data bytes. + * @throws IllegalArgumentException if the input is not valid Base64 encoded data. + */ + public static byte[] decode(char[] in) { + int iLen = in.length; + if (iLen % 4 != 0) { + throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4."); + } + while (iLen > 0 && in[iLen - 1] == '=') { + iLen--; + } + int oLen = (iLen * 3) / 4; + byte[] out = new byte[oLen]; + int ip = 0; + int op = 0; + while (ip < iLen) { + int i0 = in[ip++]; + int i1 = in[ip++]; + int i2 = ip < iLen ? in[ip++] : 'A'; + int i3 = ip < iLen ? in[ip++] : 'A'; + if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) { + throw new IllegalArgumentException("Illegal character in Base64 encoded data."); + } + int b0 = map2[i0]; + int b1 = map2[i1]; + int b2 = map2[i2]; + int b3 = map2[i3]; + if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) { + throw new IllegalArgumentException("Illegal character in Base64 encoded data."); + } + int o0 = (b0 << 2) | (b1 >>> 4); + int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); + int o2 = ((b2 & 3) << 6) | b3; + out[op++] = (byte) o0; + if (op < oLen) { + out[op++] = (byte) o1; + } + if (op < oLen) { + out[op++] = (byte) o2; + } + } + return out; + } + + // Dummy constructor. + private Base64Coder() { + } + +} // end class Base64Coder + Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/DefaultInitializer.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/DefaultInitializer.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/DefaultInitializer.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,59 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx; - -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.spi.Initializer; -import jaxx.tags.DefaultComponentHandler; -import jaxx.tags.DefaultObjectHandler; -import jaxx.tags.ScriptHandler; -import jaxx.tags.StyleHandler; -import jaxx.tags.TagManager; -import jaxx.types.ColorConverter; -import jaxx.types.GridBagConstraintsConverter; -import jaxx.types.InsetsConverter; -import jaxx.types.PrimitiveConverter; -import jaxx.types.TypeManager; - -import java.awt.Color; -import java.awt.Component; -import java.awt.GridBagConstraints; -import java.awt.Insets; - -/** Initializes support for Swing components and types. */ -public class DefaultInitializer implements Initializer { - - /** Called by the JAXX SPI system to initialize Swing support. */ - public void initialize() { - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Object.class), DefaultObjectHandler.class); - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Component.class), DefaultComponentHandler.class); - TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "script", new ScriptHandler()); - TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "style", new StyleHandler()); - - PrimitiveConverter primitiveConverter = new PrimitiveConverter(); - TypeManager.registerTypeConverter(boolean.class, primitiveConverter); - TypeManager.registerTypeConverter(Boolean.class, primitiveConverter); - TypeManager.registerTypeConverter(byte.class, primitiveConverter); - TypeManager.registerTypeConverter(Byte.class, primitiveConverter); - TypeManager.registerTypeConverter(short.class, primitiveConverter); - TypeManager.registerTypeConverter(Short.class, primitiveConverter); - TypeManager.registerTypeConverter(int.class, primitiveConverter); - TypeManager.registerTypeConverter(Integer.class, primitiveConverter); - TypeManager.registerTypeConverter(long.class, primitiveConverter); - TypeManager.registerTypeConverter(Long.class, primitiveConverter); - TypeManager.registerTypeConverter(float.class, primitiveConverter); - TypeManager.registerTypeConverter(Float.class, primitiveConverter); - TypeManager.registerTypeConverter(double.class, primitiveConverter); - TypeManager.registerTypeConverter(Double.class, primitiveConverter); - TypeManager.registerTypeConverter(char.class, primitiveConverter); - TypeManager.registerTypeConverter(Character.class, primitiveConverter); - TypeManager.registerTypeConverter(String.class, primitiveConverter); - - TypeManager.registerTypeConverter(Color.class, new ColorConverter()); - TypeManager.registerTypeConverter(GridBagConstraints.class, new GridBagConstraintsConverter()); - TypeManager.registerTypeConverter(Insets.class, new InsetsConverter()); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/DefaultInitializer.java (from rev 1042, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/DefaultInitializer.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/DefaultInitializer.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/DefaultInitializer.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,63 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx; + +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.spi.Initializer; +import jaxx.tags.DefaultComponentHandler; +import jaxx.tags.DefaultObjectHandler; +import jaxx.tags.ScriptHandler; +import jaxx.tags.StyleHandler; +import jaxx.tags.TagManager; +import jaxx.types.ColorConverter; +import jaxx.types.GridBagConstraintsConverter; +import jaxx.types.InsetsConverter; +import jaxx.types.PrimitiveConverter; +import jaxx.types.TypeManager; +import jaxx.types.BeanValidatorScopeConverter; +import jaxx.runtime.validator.BeanValidator.Scope; + +import java.awt.Color; +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.Insets; + +/** Initializes support for Swing components and types. */ +public class DefaultInitializer implements Initializer { + + /** Called by the JAXX SPI system to initialize Swing support. */ + public void initialize() { + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Object.class), DefaultObjectHandler.class); + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(Component.class), DefaultComponentHandler.class); + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "script", new ScriptHandler()); + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, "style", new StyleHandler()); + + PrimitiveConverter primitiveConverter = new PrimitiveConverter(); + TypeManager.registerTypeConverter(boolean.class, primitiveConverter); + TypeManager.registerTypeConverter(Boolean.class, primitiveConverter); + TypeManager.registerTypeConverter(byte.class, primitiveConverter); + TypeManager.registerTypeConverter(Byte.class, primitiveConverter); + TypeManager.registerTypeConverter(short.class, primitiveConverter); + TypeManager.registerTypeConverter(Short.class, primitiveConverter); + TypeManager.registerTypeConverter(int.class, primitiveConverter); + TypeManager.registerTypeConverter(Integer.class, primitiveConverter); + TypeManager.registerTypeConverter(long.class, primitiveConverter); + TypeManager.registerTypeConverter(Long.class, primitiveConverter); + TypeManager.registerTypeConverter(float.class, primitiveConverter); + TypeManager.registerTypeConverter(Float.class, primitiveConverter); + TypeManager.registerTypeConverter(double.class, primitiveConverter); + TypeManager.registerTypeConverter(Double.class, primitiveConverter); + TypeManager.registerTypeConverter(char.class, primitiveConverter); + TypeManager.registerTypeConverter(Character.class, primitiveConverter); + TypeManager.registerTypeConverter(String.class, primitiveConverter); + + TypeManager.registerTypeConverter(Color.class, new ColorConverter()); + TypeManager.registerTypeConverter(GridBagConstraints.class, new GridBagConstraintsConverter()); + TypeManager.registerTypeConverter(Insets.class, new InsetsConverter()); + + TypeManager.registerTypeConverter(Scope.class, new BeanValidatorScopeConverter()); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,520 +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>(); - - /** 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() { - String result = javaCode; - if (isOverride()) { - // handle cases where object is overridden to be a different class - result = "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; - } - return result; - } - - - /** - * 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 Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompiledObject.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,575 @@ +/* + * 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; + + /** a flag to indicate if javaBean full support must be support for this object by root object */ + private boolean javaBean; + + /** code to initialize the bean (can be null) */ + private String javaBeanInitCode; + + /** the type of the override object (can be null if no oveeride) */ + private ClassDescriptor overrideType; + + /** + * 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() { + String result = javaCode; + if (isOverride()) { + // handle cases where object is overridden to be a different class + result = "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; + } + return result; + } + + public String getJavaCodeForProperty(String property) { + if (!override) { + return javaCode; + } + String result = "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; + + String methodName = JAXXCompiler.capitalize(property); + try { + MethodDescriptor methodDescriptor = overrideType.getMethodDescriptor("get" + methodName, new ClassDescriptor[0]); + if (methodDescriptor != null) { + if (overrideType.getMethodDescriptor("set" + methodName, new ClassDescriptor[]{methodDescriptor.getReturnType()}) != null) { + // handle cases where object is overridden to be a different class + result = javaCode; + } + } + } catch (NoSuchMethodException e) { + // lazy error, do nothing + } + return result; + } + + /** + * 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(this.javaCode + delegateCode + ".add(" + javaCode + ", " + constraints + ");"); + //appendAdditionCode(getJavaCode() + delegateCode + ".add(" + javaCode + ", " + constraints + ");"); + } else { + appendAdditionCode(this.javaCode + delegateCode + ".add(" + javaCode + ");"); + //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; + } + + public boolean isJavaBean() { + return javaBean; + } + + public void setJavaBean(boolean javaBean) { + this.javaBean = javaBean; + } + + public ClassDescriptor getOverrideType() { + return overrideType; + } + + public void setOverrideType(ClassDescriptor overrideType) { + this.overrideType = overrideType; + } + + public String getJavaBeanInitCode() { + return javaBeanInitCode; + } + + public void setJavaBeanInitCode(String javaBeanInitCode) { + this.javaBeanInitCode = javaBeanInitCode; + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,186 +0,0 @@ -package jaxx.compiler; - -import java.io.File; - -/** - * Stores options which affect the jaxxc tool's operation. These options are generally specified by the - * user on the command line. - */ -public class CompilerOptions { - private File targetDirectory; - private File javacTargetDirectory; - private String classPath; - private String javacOpts; - private boolean keepJavaFiles; - private boolean optimize; - private boolean verbose; - /** a flag to enable or disable i18n generation */ - private boolean i18nable; - - /** a flag to add or not logger on generated jaxx files */ - private boolean addLogger; - - /** - * Returns the target directory, generally specified with the "-d" option on the command line. - * - * @return the target directory - * @see #setTargetDirectory - */ - public File getJavacTargetDirectory() { - if (javacTargetDirectory == null) { - // to use the old way : if javacTargetDirectory not specified, - // use same directory as targetDirectory (says where the java sources - // are generated) - return targetDirectory; - } - return javacTargetDirectory; - } - - /** - * Returns the target directory, generally specified with the "-d" option on the command line. - * - * @return the target directory - * @see #setTargetDirectory - */ - public File getTargetDirectory() { - return targetDirectory; - } - - - /** - * Sets the target directory into which compiled classes will be placed. - * - * @param targetDirectory the target directory - * @see #getTargetDirectory - */ - public void setTargetDirectory(File targetDirectory) { - this.targetDirectory = targetDirectory; - } - - public void setJavacTargetDirectory(File javacTargetDirectory) { - this.javacTargetDirectory = javacTargetDirectory; - } - - /** - * Returns the class path to be used during compilation. - * - * @return the class path to be used during compilation - * @see #setClassPath - */ - public String getClassPath() { - return classPath; - } - - /** - * Sets the class path to be used during compilation. - * - * @param classPath the compilation class path - * @see #getClassPath - */ - public void setClassPath(String classPath) { - this.classPath = classPath; - } - - - /** - * Returns the options to be passed into <code>javac</code>. - * - * @return options to be passed into <code>javac</code> - * @see #setJavacOpts - */ - public String getJavacOpts() { - return javacOpts; - } - - - /** - * Sets options to be passed into <code>javac</code>. - * - * @param javacOpts options to be passed into <code>javac</code> - * @see #getJavacOpts - */ - public void setJavacOpts(String javacOpts) { - this.javacOpts = javacOpts; - } - - - /** - * Returns whether or not generated Java files should be preserved after compilation. - * - * @return <code>true</code> if generated Java files should be preserved, <code>false</code> to delete - * @see #setKeepJavaFiles - */ - public boolean getKeepJavaFiles() { - return keepJavaFiles; - } - - - /** - * Sets whether or not generated Java files should be preserved after compilation. - * - * @param keepJavaFiles <code>true</code> if generated Java files should be preserved, <code>false</code> to delete - * @see #getKeepJavaFiles - */ - public void setKeepJavaFiles(boolean keepJavaFiles) { - this.keepJavaFiles = keepJavaFiles; - } - - - /** - * Returns whether or not optimization should be performed. - * - * @return whether or not optimizations should be performed - */ - public boolean getOptimize() { - return optimize; - } - - - /** - * Sets whether or not optimizations should be performed. - * - * @param optimize <code>true</code> to perform optimizations during compilation - * @see #getOptimize - */ - public void setOptimize(boolean optimize) { - this.optimize = optimize; - } - - public boolean isVerbose() { - return verbose; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } - - public boolean isI18nable() { - return i18nable; - } - - public void setI18nable(boolean i18nable) { - this.i18nable = i18nable; - } - - public boolean isAddLogger() { - return addLogger; - } - - public void setAddLogger(boolean addLogger) { - this.addLogger = addLogger; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(super.toString()); - sb.append("\nclassPath : ").append(getClassPath()); - sb.append("\njavaOut : ").append(getTargetDirectory()); - sb.append("\noutClass : ").append(getJavacTargetDirectory()); - sb.append("\njavacOpts : ").append(getJavacOpts()); - sb.append("\nverbose : ").append(isVerbose()); - sb.append("\noptiomize : ").append(getOptimize()); - sb.append("\ni18nable : ").append(isI18nable()); - sb.append("\naddLogger : ").append(isAddLogger()); - return sb.toString(); - } -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/CompilerOptions.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,223 @@ +package jaxx.compiler; + +import java.io.File; + +/** + * Stores options which affect the jaxxc tool's operation. These options are generally specified by the + * user on the command line. + */ +public class CompilerOptions { + private File targetDirectory; + private File javacTargetDirectory; + private String classPath; + private String javacOpts; + private boolean keepJavaFiles; + private boolean optimize; + private boolean verbose; + /** a flag to enable or disable i18n generation */ + private boolean i18nable; + + /** a flag to add or not logger on generated jaxx files */ + private boolean addLogger; + + /** a flag to not reset compiler after a compile */ + private boolean resetAfterCompile; + + /** the name of implementation of {@link jaxx.runtime.JAXXContext} to be used on {@link jaxx.runtime.JAXXObject}. */ + protected String jaxxContextImplementorClass; + + /** list of fqn of class toimport for all generated jaxx files */ + protected String[] extraImports; + /** + * Returns the target directory, generally specified with the "-d" option on the command line. + * + * @return the target directory + * @see #setTargetDirectory + */ + public File getJavacTargetDirectory() { + if (javacTargetDirectory == null) { + // to use the old way : if javacTargetDirectory not specified, + // use same directory as targetDirectory (says where the java sources + // are generated) + return targetDirectory; + } + return javacTargetDirectory; + } + + /** + * Returns the target directory, generally specified with the "-d" option on the command line. + * + * @return the target directory + * @see #setTargetDirectory + */ + public File getTargetDirectory() { + return targetDirectory; + } + + + /** + * Sets the target directory into which compiled classes will be placed. + * + * @param targetDirectory the target directory + * @see #getTargetDirectory + */ + public void setTargetDirectory(File targetDirectory) { + this.targetDirectory = targetDirectory; + } + + public void setJavacTargetDirectory(File javacTargetDirectory) { + this.javacTargetDirectory = javacTargetDirectory; + } + + /** + * Returns the class path to be used during compilation. + * + * @return the class path to be used during compilation + * @see #setClassPath + */ + public String getClassPath() { + return classPath; + } + + /** + * Sets the class path to be used during compilation. + * + * @param classPath the compilation class path + * @see #getClassPath + */ + public void setClassPath(String classPath) { + this.classPath = classPath; + } + + + /** + * Returns the options to be passed into <code>javac</code>. + * + * @return options to be passed into <code>javac</code> + * @see #setJavacOpts + */ + public String getJavacOpts() { + return javacOpts; + } + + + /** + * Sets options to be passed into <code>javac</code>. + * + * @param javacOpts options to be passed into <code>javac</code> + * @see #getJavacOpts + */ + public void setJavacOpts(String javacOpts) { + this.javacOpts = javacOpts; + } + + + /** + * Returns whether or not generated Java files should be preserved after compilation. + * + * @return <code>true</code> if generated Java files should be preserved, <code>false</code> to delete + * @see #setKeepJavaFiles + */ + public boolean getKeepJavaFiles() { + return keepJavaFiles; + } + + + /** + * Sets whether or not generated Java files should be preserved after compilation. + * + * @param keepJavaFiles <code>true</code> if generated Java files should be preserved, <code>false</code> to delete + * @see #getKeepJavaFiles + */ + public void setKeepJavaFiles(boolean keepJavaFiles) { + this.keepJavaFiles = keepJavaFiles; + } + + + /** + * Returns whether or not optimization should be performed. + * + * @return whether or not optimizations should be performed + */ + public boolean getOptimize() { + return optimize; + } + + + /** + * Sets whether or not optimizations should be performed. + * + * @param optimize <code>true</code> to perform optimizations during compilation + * @see #getOptimize + */ + public void setOptimize(boolean optimize) { + this.optimize = optimize; + } + + public boolean isVerbose() { + return verbose; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + public boolean isI18nable() { + return i18nable; + } + + public void setI18nable(boolean i18nable) { + this.i18nable = i18nable; + } + + public boolean isAddLogger() { + return addLogger; + } + + public void setAddLogger(boolean addLogger) { + this.addLogger = addLogger; + } + + public String getJaxxContextImplementorClass() { + return jaxxContextImplementorClass; + } + + public void setJaxxContextImplementorClass(String jaxxContextImplementorClass) { + this.jaxxContextImplementorClass = jaxxContextImplementorClass; + } + + public String[] getExtraImports() { + return extraImports; + } + + public void setExtraImports(String[] extraImports) { + this.extraImports = extraImports; + } + + public boolean isResetAfterCompile() { + return resetAfterCompile; + } + + public void setResetAfterCompile(boolean resetAfterCompile) { + this.resetAfterCompile = resetAfterCompile; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(super.toString()); + sb.append("\nclassPath : ").append(getClassPath()); + sb.append("\njavaOut : ").append(getTargetDirectory()); + sb.append("\noutClass : ").append(getJavacTargetDirectory()); + sb.append("\njavacOpts : ").append(getJavacOpts()); + sb.append("\nverbose : ").append(isVerbose()); + sb.append("\noptiomize : ").append(getOptimize()); + sb.append("\ni18nable : ").append(isI18nable()); + sb.append("\naddLogger : ").append(isAddLogger()); + sb.append("\nresetAfterCompile : ").append(isResetAfterCompile()); + sb.append("\njaxxContextImplementorClass : ").append(getJaxxContextImplementorClass()); + sb.append("\nextraImports : ").append(getExtraImports()); + return sb.toString(); + } + + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -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.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 Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataBinding.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,82 @@ +/* + * 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 "); + } else { + compiler.appendProcessDataBinding(" "); + } + compiler.appendProcessDataBinding("if (" + TypeManager.getJavaCode(id) + ".equals($dest)) {" + JAXXCompiler.getLineSeparator() +" "+ assignment + JAXXCompiler.getLineSeparator() + " }"); + return true; + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataSource.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataSource.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataSource.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,439 +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.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()); - } - } -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataSource.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/DataSource.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataSource.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/DataSource.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,448 @@ +/* + * 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.beans.PropertyChangeListener; +import java.io.StringReader; +import java.lang.reflect.Modifier; +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; + } + + public String getSource() { + return source; + } + + /** + * 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) { + //TC 20081108 prefer add a real JavaField instead of raw code + //compiler.appendBodyCode("private PropertyChangeListener " + id + " = " + propertyChangeListenerCode + ";\n"); + compiler.addSimpleField(new JavaField(Modifier.PRIVATE, PropertyChangeListener.class.getName(), id, propertyChangeListenerCode)); + } + + 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 current class context + * @param isMethod flag to search a method + * @param listenerId id of the listener + * @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; // 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 the node to scan + * @param listenerId id of the listener + * @return the class descriptor of the return type or null + */ + 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(" ").append(addCode); + if (objectCode != null) { + addListenerCode.append(" ").append("}"); + } + + if (objectCode != null) { + removeListenerCode.append("if (").append(objectCode).append(" != null) {").append(JAXXCompiler.getLineSeparator()); + removeListenerCode.append(" "); + } + removeListenerCode.append(" ").append(removeCode); + if (objectCode != null) { + removeListenerCode.append(" }"); + } + } + } + + private void compileListeners() { + String javaCodeId = TypeManager.getJavaCode(id); + if (addListenerCode.length() > 0) { + if (compiler.haveApplyDataBinding()) { + compiler.appendApplyDataBinding(" else "); + } + compiler.appendApplyDataBinding("if (" + javaCodeId + ".equals($binding)) {" + JAXXCompiler.getLineSeparator()); + compiler.appendApplyDataBinding(" " + addListenerCode + JAXXCompiler.getLineSeparator()); + compiler.appendApplyDataBinding("}"); + //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 (" + javaCodeId + ".equals($binding)) {" + JAXXCompiler.getLineSeparator()); + compiler.appendRemoveDataBinding(" " + removeListenerCode + JAXXCompiler.getLineSeparator()); + compiler.appendRemoveDataBinding("}"); + //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.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,1145 +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.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.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompiler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,1177 @@ +/* + * 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.lang.reflect.Modifier; +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(""); + + /** extra interfaces which can by passed to root object via the 'implements' attribute */ + private String[] extraInterfaces; + + /*---------------------------------------------------------------------------------*/ + /*-- 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); + } + // add extra imports from options + if (options.getExtraImports() != null) { + for (String extraImport : options.getExtraImports()) { + addImport(extraImport); + } + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- 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); + if (tag.getAttributeNode("javaBean") != null) { + // add java bean support for this property + String capitalizeName = capitalize(id); + // add method + symbolTable.getScriptMethods().add(new MethodDescriptor("get" + capitalizeName, Modifier.PUBLIC, fullClassName, new String[0], classLoader)); + if (Boolean.class.getName().equals(fullClassName)) { + symbolTable.getScriptMethods().add(new MethodDescriptor("is" + capitalizeName, Modifier.PUBLIC, fullClassName, new String[0], classLoader)); + } + symbolTable.getScriptMethods().add(new MethodDescriptor("set" + capitalizeName, Modifier.PUBLIC, "void", new String[]{fullClassName}, classLoader)); + } + } + } + // 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); + object.setOverrideType(f.getType()); + 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; + } + + public void setExtraInterfaces(String[] extraInterfaces) { + this.extraInterfaces = extraInterfaces; + } + + public String[] getExtraInterfaces() { + return extraInterfaces; + } + + public void addSimpleField(JavaField javaField) { + generator.getJavaFile().addSimpleField(javaField); + } +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,657 +0,0 @@ -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.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXCompilerHelper.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -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 jaxx.runtime.swing.Utils.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 (options.isResetAfterCompile() && 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); + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,674 +0,0 @@ -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"); - javaFile.addImport("jaxx.runtime.JAXXInitialContext"); - - if (compiler.getStylesheet() != null) { - javaFile.addField(new JavaField(0, "java.util.Map", "$previousValues", "new java.util.HashMap()")); - } - - javaFile.addMethod(createConstructor(className)); - javaFile.addMethod(createConstructorWithInitialContext(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 createConstructorWithInitialContext(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("initialContext.to(this);"); - code.append(JAXXCompiler.getLineSeparator()); - code.append("$initialize();"); - code.append(JAXXCompiler.getLineSeparator()); - JavaArgument arg = new JavaArgument("jaxx.runtime.JAXXInitialContext","initialContext"); - return new JavaMethod(Modifier.PUBLIC, null, className, new JavaArgument[]{arg}, 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; - } -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGenerator.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,640 @@ +package jaxx.compiler; + +import jaxx.Base64Coder; +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.runtime.validator.BeanValidator; +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.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.lang.reflect.Modifier; +import static java.lang.reflect.Modifier.FINAL; +import static java.lang.reflect.Modifier.PROTECTED; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * 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 extends JAXXObjectGeneratorConstants { + + /** 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)); + // can have extra interfaces from compiler + java.util.Set<String> interfaces = new java.util.HashSet<String>(); + interfaces.add(JAXXCompiler.getCanonicalName(JAXXObject.class)); + if (compiler.getExtraInterfaces() != null) { + interfaces.addAll(java.util.Arrays.asList(compiler.getExtraInterfaces())); + } + javaFile.setInterfaces(interfaces.toArray(new String[interfaces.size()])); + + for (CompiledObject object : compiler.getObjects().values()) { + if (!object.isOverride() && !(object instanceof ScriptInitializer)) { + String id = object.getId(); + int access = id.startsWith("$") ? Modifier.PRIVATE : Modifier.PROTECTED; + if (object == root) { + javaFile.addField(new JavaField(access, fullClassName, id, "this")); + } else { + //TC -20081017 can have generic on compiled Object + javaFile.addField(newField(access, JAXXCompiler.getCanonicalName(object), id), object.isJavaBean()); + } + } + + if (!compiler.inlineCreation(object) && object != root) { + javaFile.addMethod(newMethod(Modifier.PROTECTED, "void", object.getCreationMethodName(), getCreationCode(object))); + } + } + + String jaxxContextImplementorClass = compiler.getOptions().getJaxxContextImplementorClass(); + + if (!superclassIsJAXXObject) { + // add logger + if (getOptions().isAddLogger()) { + javaFile.addImport(org.apache.commons.logging.Log.class); + javaFile.addImport(org.apache.commons.logging.LogFactory.class); + javaFile.addField(newField(Modifier.PUBLIC + Modifier.STATIC + FINAL, "Log", "log", "LogFactory.getLog(" + fullClassName + ".class)")); + } + + // JAXXObject + javaFile.addField(OBJECT_MAP_FIELD); + javaFile.addMethod(GET_OBJECT_BY_ID_METHOD); + javaFile.addField(BINDING_SOURCES_FIELD); + javaFile.addField(ACTIVE_BINDINGS_FIELD); + + // JAXXContext + + javaFile.addField(newField(PROTECTED | FINAL, "jaxx.runtime.JAXXContext", "delegateContext", "new " + jaxxContextImplementorClass + "(this);")); + javaFile.addMethod(SET_CONTEXT_VALUE_METHOD); + javaFile.addMethod(SET_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(GET_CONTEXT_VALUE_METHOD); + javaFile.addMethod(GET_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(REMOVE_CONTEXT_VALUE_METHOD); + javaFile.addMethod(REMOVE_CONTEXT_VALUE_NAMED_METHOD); + javaFile.addMethod(GET_PARENT_CONTAINER_METHOD); + javaFile.addMethod(GET_PARENT_CONTAINER_MORE_METHOD); + + // JAXXValidator + javaFile.addField(VALIDATOR_IDS_FIELD); + javaFile.addMethod(GET_VALIDATOR_METHOD); + + // PropertyChangeSupport + addPropertyChangeSupport(root); + + // DataBinding + javaFile.addMethod(PROCESS_DATA_BINDING_METHOD); + } + + javaFile.addImport(BeanValidator.class); + //javaFile.addImport(JAXXInitialContext.class); + + javaFile.addField(ALL_COMPONENTS_CREATED_FIELD); + javaFile.addField(createJAXXObjectDescriptorField()); + + if (compiler.getStylesheet() != null) { + javaFile.addField(PREVIOUS_VALUES_FIELD); + } + + javaFile.addMethod(createConstructor(className, superclassIsJAXXObject)); + javaFile.addMethod(createConstructorWithInitialContext(className, superclassIsJAXXObject)); + javaFile.addMethod(createInitializer()); + javaFile.addMethod(GET_JAXX_OBJECT_DESCRIPTOR_METHOD); + + // DataBinding + 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()); + + javaFile.addMethod(createCompleteSetupMethod(initDataBindings)); + + if (superclassIsJAXXObject) { + boolean hasBind = applyDataBinding.length() > 0; + if (hasBind) { + applyDataBinding.append(" else {"); + applyDataBinding.append(JAXXCompiler.getLineSeparator()); + applyDataBinding.append(" "); + } + applyDataBinding.append("super.applyDataBinding($binding);"); + applyDataBinding.append(JAXXCompiler.getLineSeparator()); + + if (hasBind) { + applyDataBinding.append(" return;"); + applyDataBinding.append(JAXXCompiler.getLineSeparator()); + applyDataBinding.append("}"); + } + + + hasBind = removeDataBinding.length() > 0; + if (hasBind) { + removeDataBinding.append(" else {"); + removeDataBinding.append(JAXXCompiler.getLineSeparator()); + removeDataBinding.append(" "); + } + removeDataBinding.append("super.removeDataBinding($binding);"); + removeDataBinding.append(JAXXCompiler.getLineSeparator()); + + if (hasBind) { + removeDataBinding.append("}"); + } + } + + + javaFile.addMethod(newMethod(Modifier.PUBLIC, "void", "applyDataBinding", + applyDataBinding.toString() + JAXXCompiler.getLineSeparator() + "processDataBinding($binding);", + new JavaArgument("String", "$binding")) + ); + + javaFile.addMethod(newMethod(Modifier.PUBLIC, "void", "removeDataBinding", + removeDataBinding.toString(), new JavaArgument("String", "$binding")) + ); + + javaFile.addMethod(createProcessDataBindingMethod(superclassIsJAXXObject)); + + addEventHandlers(javaFile); + + if (ClassDescriptorLoader.getClassDescriptor(Application.class).isAssignableFrom(root.getObjectClass()) && !isMainDeclared()) { + // TODO: check for existing main method first + javaFile.addMethod(newMethod(Modifier.PUBLIC | Modifier.STATIC, "void", "main", + "SwingUtilities.invokeLater(new Runnable() { public void run() { new " + className + "().setVisible(true); } });", + new JavaArgument("String[]", "arg")) + ); + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create fields ----------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + protected JavaField createJAXXObjectDescriptorField() { + try { + JAXXObjectDescriptor descriptor = compiler.getJAXXObjectDescriptor(); + String data = Base64Coder.serialize(descriptor, true); + /*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 newField(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 newField(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 void addPropertyChangeSupport(CompiledObject root) { + 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(FIRE_PROPERTY_CHANGE_METHOD); + } else { + // either no support at all or firePropertyChange isn't accessible + javaFile.addField(PROPERTY_CHANGE_SUPPORT_FIELD); + javaFile.addMethod(GET_PROPERTY_CHANGE_SUPPORT_METHOD); + javaFile.addMethod(ADD_PROPERTY_CHANGE_SUPPORT_METHOD); + javaFile.addMethod(ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + javaFile.addMethod(REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD); + javaFile.addMethod(REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + javaFile.addMethod(FIRE_PROPERTY_CHANGE_NAMED_METHOD); + } + } + + 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(newMethod(Modifier.PUBLIC, "void", methodName, handler.getJavaCode(), + new JavaArgument(JAXXCompiler.getCanonicalName(listenerMethod.getParameterTypes()[0]), "event"))); + } + } + } + } + + protected JavaMethod createConstructor(String className, boolean superclassIsJAXXObject) throws CompilerException { + StringBuffer code = new StringBuffer(); + String constructorParams = compiler.getRootObject().getConstructorParams(); + if (constructorParams != null) { + code.append(" super(").append(constructorParams).append(");").append(JAXXCompiler.getLineSeparator()); + } else { + if (superclassIsJAXXObject) { + code.append(" super();").append(JAXXCompiler.getLineSeparator()); + } + } + /*if (!superclassIsJAXXObject) { + code.append("delegateContext = new ").append(jaxxContextImplementorClass).append("(this);"); + code.append(JAXXCompiler.getLineSeparator()); + }*/ + code.append("$initialize();"); + code.append(JAXXCompiler.getLineSeparator()); + return newMethod(Modifier.PUBLIC, null, className, code.toString()); + } + + protected JavaMethod createConstructorWithInitialContext(String className, boolean superclassIsJAXXObject) throws CompilerException { + StringBuffer code = new StringBuffer(); + String constructorParams = compiler.getRootObject().getConstructorParams(); + if (constructorParams != null) { + code.append(" super(").append(constructorParams).append(");").append(JAXXCompiler.getLineSeparator()); + } else { + if (superclassIsJAXXObject) { + code.append(" super(parentContext);").append(JAXXCompiler.getLineSeparator()); + } + } + if (!superclassIsJAXXObject) { + //code.append("delegateContext = new ").append(jaxxContextImplementorClass).append("(this);"); + //code.append(JAXXCompiler.getLineSeparator()); + code.append("if (parentContext instanceof jaxx.runtime.JAXXInitialContext) {"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" ((jaxx.runtime.JAXXInitialContext)parentContext).to(this);"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("} else {"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" setContextValue(parentContext);"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("}"); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append("$initialize();"); + code.append(JAXXCompiler.getLineSeparator()); + return newMethod(Modifier.PUBLIC, null, className, code.toString(), new JavaArgument("jaxx.runtime.JAXXContext", "parentContext")); + } + + protected JavaMethod createInitializer() throws CompilerException { + StringBuffer code = new StringBuffer(); + CompiledObject root = compiler.getRootObject(); + code.append("if (allComponentsCreated) {"); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" return;"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("}"); + code.append(JAXXCompiler.getLineSeparator()); + 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 newMethod(Modifier.PRIVATE, "void", "$initialize", code.toString()); + } + + + protected JavaMethod createCompleteSetupMethod(StringBuffer initDataBindings) { + 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() + " return;" + JAXXCompiler.getLineSeparator() + "}" + JAXXCompiler.getLineSeparator() + additionCode; + javaFile.addMethod(newMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), 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(JAXXCompiler.getLineSeparator()); + code.append("getValidator(").append(id).append(").validate();"); + code.append(JAXXCompiler.getLineSeparator()); + } + code.append("validatorIds = java.util.Collections.unmodifiableList(validatorIds);"); + code.append(JAXXCompiler.getLineSeparator()); + } + return newMethod(Modifier.PRIVATE, "void", "$completeSetup", code.toString()); + } + + protected JavaMethod createProcessDataBindingMethod(boolean superclassIsJAXXObject) { + 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)) { "); + code.append(JAXXCompiler.getLineSeparator()); + code.append(" return;"); + code.append(JAXXCompiler.getLineSeparator()); + code.append("}"); + 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 newMethod(Modifier.PUBLIC, "void", "processDataBinding", code.toString(), + new JavaArgument("String", "$dest"), new JavaArgument("boolean", "$force") + ); + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create methods code ----------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + 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(" = "); + if (object.isJavaBean() && object.getJavaBeanInitCode() != null) { + result.append(object.getJavaBeanInitCode()).append(";"); + } else { + 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; + } +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGeneratorConstants.java (from rev 1027, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGeneratorConstants.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGeneratorConstants.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JAXXObjectGeneratorConstants.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,163 @@ +package jaxx.compiler; + +import static java.lang.reflect.Modifier.PRIVATE; +import static java.lang.reflect.Modifier.PROTECTED; +import static java.lang.reflect.Modifier.PUBLIC; +import static java.lang.reflect.Modifier.STATIC; + +/** @author chemit */ +public class JAXXObjectGeneratorConstants { + + // fields + + protected static final JavaField ACTIVE_BINDINGS_FIELD = newField(PROTECTED, + "java.util.List<Object>", "$activeBindings", "new ArrayList<Object>()" + ); + + protected static final JavaField BINDING_SOURCES_FIELD = newField(PROTECTED, + "java.util.Map<String,Object>", "$bindingSources", "new HashMap<String,Object>()" + ); + + protected static final JavaField VALIDATOR_IDS_FIELD = newField(PROTECTED, + "java.util.List<String>", "validatorIds", "new ArrayList<String>()" + ); + + protected static final JavaField OBJECT_MAP_FIELD = newField(PROTECTED, + "Map<String,Object>", "$objectMap", "new HashMap<String,Object>()" + ); + + protected static final JavaField ALL_COMPONENTS_CREATED_FIELD = newField(PRIVATE, + "boolean", "allComponentsCreated" + ); + + protected static final JavaField PREVIOUS_VALUES_FIELD = newField(0, + "java.util.Map", "$previousValues", "new java.util.HashMap()" + ); + + protected static final JavaField DELEGATE_CONTEXT_FIELD = newField(PROTECTED, + "jaxx.runtime.JAXXContext", "delegateContext" + ); + + protected static final JavaField PROPERTY_CHANGE_SUPPORT_FIELD = newField(0, + "java.beans.PropertyChangeSupport", "$propertyChangeSupport" + ); + + // JAXXContext methods + + protected static final JavaMethod GET_CONTEXT_VALUE_METHOD = newMethod(PUBLIC, "<T> T", "getContextValue", + "return delegateContext.getContextValue(clazz, null);", + new JavaArgument("Class<T>", "clazz") + ); + protected static final JavaMethod GET_CONTEXT_VALUE_NAMED_METHOD = newMethod(PUBLIC, "<T> T", "getContextValue", + "return delegateContext.getContextValue(clazz, name);", + new JavaArgument("Class<T>", "clazz"), new JavaArgument("String", "name") + ); + + protected static final JavaMethod SET_CONTEXT_VALUE_NAMED_METHOD = newMethod(PUBLIC, "<T> void", "setContextValue", + "delegateContext.setContextValue(o, name);", + new JavaArgument("T", "o"), new JavaArgument("String", "name") + ); + + protected static final JavaMethod SET_CONTEXT_VALUE_METHOD = newMethod(PUBLIC, "<T> void", "setContextValue", + "delegateContext.setContextValue(o, null);", + new JavaArgument("T", "o") + ); + + protected static final JavaMethod REMOVE_CONTEXT_VALUE_NAMED_METHOD = newMethod(PUBLIC, "<T> void", "removeContextValue", + "delegateContext.removeContextValue(clazz, name);", + new JavaArgument("Class<T>", "clazz"), new JavaArgument("String", "name") + ); + + protected static final JavaMethod REMOVE_CONTEXT_VALUE_METHOD = newMethod(PUBLIC, "<T> void", "removeContextValue", + "delegateContext.removeContextValue(clazz, null);", + new JavaArgument("Class<T>", "clazz") + ); + + protected static final JavaMethod GET_PARENT_CONTAINER_MORE_METHOD = newMethod(PUBLIC, "<O extends Container> O", "getParentContainer", + "return delegateContext.getParentContainer(source, clazz);", + new JavaArgument("Object", "source"), new JavaArgument("Class<O>", "clazz") + ); + + protected static final JavaMethod GET_PARENT_CONTAINER_METHOD = newMethod(PUBLIC, "<O extends Container> O", "getParentContainer", + "return delegateContext.getParentContainer(clazz);", + new JavaArgument("Class<O>", "clazz") + ); + + // JAXXObject methods + + protected static final JavaMethod GET_OBJECT_BY_ID_METHOD = newMethod(PUBLIC, "java.lang.Object", "getObjectById", + "return $objectMap.get(id);", + new JavaArgument("String", "id") + ); + + protected static final JavaMethod GET_JAXX_OBJECT_DESCRIPTOR_METHOD = newMethod(PUBLIC | STATIC, "jaxx.runtime.JAXXObjectDescriptor", "$getJAXXObjectDescriptor", + "return jaxx.runtime.Util.decodeCompressedJAXXObjectDescriptor($jaxxObjectDescriptor);" + ); + + protected static final JavaMethod PROCESS_DATA_BINDING_METHOD = newMethod(PUBLIC, "void", "processDataBinding", + "processDataBinding(dest, false);", + new JavaArgument("String", "dest") + ); + + // JAXXValidator methods + + protected static final JavaMethod GET_VALIDATOR_METHOD = newMethod(PUBLIC, "BeanValidator<?>", "getValidator", + "return (BeanValidator) (validatorIds.contains(validatorId)?getObjectById(validatorId):null);", + new JavaArgument("String", "validatorId") + ); + + // PropertyChangeSupport methods + + + protected static final JavaMethod FIRE_PROPERTY_CHANGE_METHOD = newMethod(PUBLIC, "void", "firePropertyChange", + "super.firePropertyChange(propertyName, oldValue, newValue);", + new JavaArgument("String", "propertyName"), new JavaArgument("Object", "oldValue"), new JavaArgument("Object", "newValue") + ); + + protected static final JavaMethod FIRE_PROPERTY_CHANGE_NAMED_METHOD = newMethod(PUBLIC, "void", "firePropertyChange", + "$getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue);", + new JavaArgument("String", "propertyName"), new JavaArgument("Object", "oldValue"), new JavaArgument("Object", "newValue") + ); + + protected static final JavaMethod GET_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod(0, "java.beans.PropertyChangeSupport", "$getPropertyChangeSupport", + "if ($propertyChangeSupport == null)\n" + + " $propertyChangeSupport = new PropertyChangeSupport(this);\n" + + "return $propertyChangeSupport;"); + + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod(PUBLIC, "void", "addPropertyChangeListener", + "$getPropertyChangeSupport().addPropertyChangeListener(listener);", + new JavaArgument("java.beans.PropertyChangeListener", "listener") + ); + + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod(PUBLIC, "void", "addPropertyChangeListener", + "$getPropertyChangeSupport().addPropertyChangeListener(property, listener);", + new JavaArgument("String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener") + ); + + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod(PUBLIC, "void", "removePropertyChangeListener", + "$getPropertyChangeSupport().removePropertyChangeListener(listener);", + new JavaArgument("java.beans.PropertyChangeListener", "listener") + ); + + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod(PUBLIC, "void", "removePropertyChangeListener", + "$getPropertyChangeSupport().removePropertyChangeListener(property, listener);", + new JavaArgument("String", "property"), new JavaArgument("java.beans.PropertyChangeListener", "listener") + ); + + + protected static JavaField newField(int modifiers, String returnType, String name) { + return newField(modifiers, returnType, name, null); + } + + protected static JavaField newField(int modifiers, String returnType, String name, String initializer) { + return new JavaField(modifiers, returnType, name, initializer); + } + + protected static JavaMethod newMethod(int modifiers, String returnType, String name, String initializer, String[] exceptions, JavaArgument... arguments) { + return new JavaMethod(modifiers, returnType, name, arguments, exceptions, initializer); + } + + protected static JavaMethod newMethod(int modifiers, String returnType, String name, String initializer, JavaArgument... arguments) { + return newMethod(modifiers, returnType, name, initializer, new String[0], arguments); + } +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaField.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JavaField.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaField.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,109 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.compiler; - -/** - * Represents a field in a Java source file being generated for output. <code>JavaFields</code> are created - * and added to a {@link JavaFile}, which can then output Java source code. - */ -public class JavaField { - private int modifiers; - private String type; - private String name; - private String initializer; - - - /** - * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the - * constants from {@link java.lang.reflect.Modifier}, and the <code>type</code> of the field should be - * represented as it would appear in Java source code. - * - * @param modifiers the modifier keywords that should appear as part of the field's declaration - * @param type the type of the field as it would appear in Java source code - * @param name the field's name - */ - public JavaField(int modifiers, String type, String name) { - this(modifiers, type, name, null); - } - - - /** - * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the - * constants from <code>java.lang.reflect.Modifier</code>, and the <code>type</code> of the field should be - * represented as it would appear in Java source code. The <code>initializer</code> is the initial - * value of the field as it would appear in Java source code, or <code>null</code> to leave it at the - * default value. - * - * @param modifiers the modifier keywords that should appear as part of the field's declaration - * @param type the type of the field as it would appear in Java source code - * @param name the field's name - * @param initializer the initial value of the field, as it would appear in Java source code - */ - public JavaField(int modifiers, String type, String name, String initializer) { - this.modifiers = modifiers; - this.type = type; - this.name = name; - this.initializer = initializer; - } - - - /** - * Returns a bit mask describing the modifier keywords which should appear as part of this field's - * declaration. See <code>java.lang.reflect.Modifier</code> for more information on decoding this - * field. - * - * @return the modifier bit mask - */ - public int getModifiers() { - return modifiers; - } - - - /** - * Returns the field's name. - * - * @return the field's name - */ - public String getName() { - return name; - } - - - /** - * Returns the field's type, as it would be represented in Java source code. - * - * @return the field's type - */ - public String getType() { - return type; - } - - - /** - * Returns the Java source code for this field. - * - * @return the Java source code for this field - */ - @Override - public String toString() { - StringBuffer result = new StringBuffer(); - result.append(JavaFile.getModifiersText(modifiers)); - result.append(type); - result.append(' '); - result.append(name); - if (initializer != null) { - result.append(" = "); - result.append(initializer); - } - result.append(';'); - result.append(' '); - if (java.lang.reflect.Modifier.isProtected(modifiers)) { - result.append("public ").append(type).append(" get").append(name.substring(0, 1).toUpperCase()).append(name.substring(1)).append("() {return ").append(name).append(";}"); - } else if (java.lang.reflect.Modifier.isPrivate(modifiers)) { - result.append("protected ").append(type).append(" get").append(name.substring(0, 1).toUpperCase()).append(name.substring(1)).append("() {return ").append(name).append(";}"); - } - return result.toString(); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaField.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JavaField.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaField.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaField.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,180 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.compiler; + +import java.lang.reflect.Modifier; +import java.util.Comparator; + +/** + * Represents a field in a Java source file being generated for output. <code>JavaFields</code> are created + * and added to a {@link JavaFile}, which can then output Java source code. + */ +public class JavaField implements Comparable<JavaField> { + + private int modifiers; + private String type; + private String name; + private String initializer; + + + /** + * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the + * constants from {@link java.lang.reflect.Modifier}, and the <code>type</code> of the field should be + * represented as it would appear in Java source code. + * + * @param modifiers the modifier keywords that should appear as part of the field's declaration + * @param type the type of the field as it would appear in Java source code + * @param name the field's name + */ + public JavaField(int modifiers, String type, String name) { + this(modifiers, type, name, null); + } + + + /** + * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the + * constants from <code>java.lang.reflect.Modifier</code>, and the <code>type</code> of the field should be + * represented as it would appear in Java source code. The <code>initializer</code> is the initial + * value of the field as it would appear in Java source code, or <code>null</code> to leave it at the + * default value. + * + * @param modifiers the modifier keywords that should appear as part of the field's declaration + * @param type the type of the field as it would appear in Java source code + * @param name the field's name + * @param initializer the initial value of the field, as it would appear in Java source code + */ + public JavaField(int modifiers, String type, String name, String initializer) { + this.modifiers = modifiers; + this.type = type; + this.name = name; + this.initializer = initializer; + } + + + /** + * Returns a bit mask describing the modifier keywords which should appear as part of this field's + * declaration. See <code>java.lang.reflect.Modifier</code> for more information on decoding this + * field. + * + * @return the modifier bit mask + */ + public int getModifiers() { + return modifiers; + } + + + /** + * Returns the field's name. + * + * @return the field's name + */ + public String getName() { + return name; + } + + + /** + * Returns the field's type, as it would be represented in Java source code. + * + * @return the field's type + */ + public String getType() { + return type; + } + + + /** + * Returns the Java source code for this field. + * + * @return the Java source code for this field + */ + @Override + public String toString() { + StringBuffer result = new StringBuffer(); + result.append(JavaFile.getModifiersText(modifiers)); + result.append(type).append(' ').append(name); + if (initializer != null) { + result.append(" = ").append(initializer); + } + result.append(';').append(JAXXCompiler.getLineSeparator()); + return result.toString(); + } + + public int compareTo(JavaField o) { + return COMPARATOR.compare(this, o); + } + + public static final Comparator<JavaField> COMPARATOR = new Comparator<JavaField>() { + + public int compare(JavaField o1, JavaField o2) { + + int result; + if ((result = compareStatic(o1, o2)) != 0) { + return result; + } + + // data sources must be on the last after all other fields + if ((result = compareDataSource(o1, o2)) != 0) { + return result; + } + + // same static + if ((result = compareVisibility(o1, o2)) != 0) { + return result; + } + // same visibility, test name + return o1.name.compareTo(o2.name); + } + + public int compareStatic(JavaField o1, JavaField o2) { + // first comparator modifiers : static always before none static + if (Modifier.isStatic(o1.modifiers) && !Modifier.isStatic(o2.modifiers)) { + return -1; + } + if (!Modifier.isStatic(o1.modifiers) && Modifier.isStatic(o2.modifiers)) { + return 1; + } + return 0; + } + + public int compareDataSource(JavaField o1, JavaField o2) { + // first comparator modifiers : static always before none static + if (o1.name.startsWith("$DataSource") && !o2.name.startsWith("$DataSource")) { + return 1; + } + if (!o1.name.startsWith("$DataSource") && o2.name.startsWith("$DataSource")) { + return -1; + } + return 0; + } + + public int compareVisibility(JavaField o1, JavaField o2) { + // first comparator modifiers : static always before none static + if (!Modifier.isPublic(o1.modifiers) && Modifier.isPublic(o2.modifiers)) { + return 1; + } + + if (Modifier.isPublic(o1.modifiers) && !Modifier.isPublic(o2.modifiers)) { + return -1; + } + + if (Modifier.isProtected(o1.modifiers) && !Modifier.isProtected(o2.modifiers)) { + return -1; + } + if (!Modifier.isProtected(o1.modifiers) && Modifier.isProtected(o2.modifiers)) { + return 1; + } + + if (Modifier.isPrivate(o1.modifiers) && !Modifier.isPrivate(o2.modifiers)) { + return -1; + } + if (!Modifier.isPrivate(o1.modifiers) && Modifier.isPrivate(o2.modifiers)) { + return 1; + } + return 0; + } + }; + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,244 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.compiler; - -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * A Java source file being generated for output. Once the class is completely initialized, use the - * {@link #toString} method to generate source code for it. - */ -public class JavaFile { - private int modifiers; - private String className; - private List<String> imports = new ArrayList<String>(); - private List<JavaField> fields = new ArrayList<JavaField>(); - private List<JavaMethod> methods = new ArrayList<JavaMethod>(); - private List<JavaFile> innerClasses = new ArrayList<JavaFile>(); - private String superClass; - private String[] interfaces; - private StringBuffer rawBodyCode = new StringBuffer(); - - - public JavaFile() { - } - - - public JavaFile(int modifiers, String className, String superClass) { - this(modifiers, className, superClass, null); - } - - - public JavaFile(int modifiers, String className, String superClass, String[] interfaces) { - this.modifiers = modifiers; - this.className = className; - this.superClass = superClass; - this.interfaces = interfaces; - } - - - public void addImport(String importString) { - imports.add(importString); - } - - - public String[] getImports() { - return imports.toArray(new String[imports.size()]); - } - - - public int getModifiers() { - return modifiers; - } - - - public void setModifiers(int modifiers) { - this.modifiers = modifiers; - } - - - public String getClassName() { - return className; - } - - - public void setClassName(String className) { - this.className = className; - } - - - public String getSuperClass() { - return superClass; - } - - - public void setSuperClass(String superClass) { - this.superClass = superClass; - } - - - public String[] getInterfaces() { - return interfaces; - } - - - public void setInterfaces(String[] interfaces) { - this.interfaces = interfaces; - } - - - public void addMethod(JavaMethod method) { - methods.add(method); - } - - - public JavaMethod[] getMethods() { - return methods.toArray(new JavaMethod[methods.size()]); - } - - - public void addField(JavaField field) { - fields.add(field); - } - - - public JavaField[] getFields() { - return fields.toArray(new JavaField[fields.size()]); - } - - - public static String addIndentation(String source, int indentation) { - return indent(source, indentation, false); - } - - - public static String setIndentation(String source, int indentation) { - return indent(source, indentation, true); - } - - - public static String indent(String source, int indentation, boolean trim) { - if (trim) - source = source.trim(); - char[] spaces = new char[indentation]; - Arrays.fill(spaces, ' '); - StringBuffer result = new StringBuffer(); - String[] lines = source.split(System.getProperty("line.separator") + "|\n"); - for (int i = 0; i < lines.length; i++) { - if (i > 0) - result.append(JAXXCompiler.getLineSeparator()); - result.append(spaces); - result.append(trim ? lines[i].trim() : lines[i]); - } - return result.toString(); - } - - - public void addBodyCode(String bodyCode) { - rawBodyCode.append(bodyCode); - } - - - public String getClassBody() { - StringBuffer result = new StringBuffer(); - if (fields.size() > 0) { - for (JavaField field : fields) { - result.append(addIndentation(field.toString(), 4)); - result.append(JAXXCompiler.getLineSeparator()); - } - - result.append(JAXXCompiler.getLineSeparator()); - } - - if (rawBodyCode.length() > 0) { - result.append(addIndentation("/* begin raw body code */\n", 4)); - String s = rawBodyCode.toString(); - if (!s.startsWith("\n")) { - result.append('\n'); - } - result.append(addIndentation(s, 4)); - result.append('\n'); - result.append(addIndentation("/* end raw body code */", 4)); - result.append("\n"); - } - - for (JavaFile innerClass : innerClasses) { - result.append(addIndentation(innerClass.toString(), 4)); - result.append(JAXXCompiler.getLineSeparator()); - result.append(JAXXCompiler.getLineSeparator()); - } - - for (JavaMethod method : methods) { - result.append(addIndentation(method.toString(), 4)); - result.append(JAXXCompiler.getLineSeparator()); - result.append(JAXXCompiler.getLineSeparator()); - } - - return result.toString(); - } - - - public String getClassDefinition() { - StringBuffer result = new StringBuffer(); - result.append(getModifiersText(modifiers)); - result.append("class "); - result.append(className.substring(className.lastIndexOf(".") + 1)); - result.append(" extends "); - result.append(superClass); - if (interfaces != null && interfaces.length > 0) { - result.append(" implements "); - for (int i = 0; i < interfaces.length; i++) { - if (i > 0) - result.append(", "); - result.append(interfaces[i]); - } - } - result.append(" {"); - result.append(JAXXCompiler.getLineSeparator()); - result.append(getClassBody()); - result.append("}"); - return result.toString(); - } - - - public static String getModifiersText(int modifiers) { - if (modifiers == 0) - return ""; - else - return Modifier.toString(modifiers) + ' '; - } - - - /** - * Returns the Java source code for this class. - * - * @return a complete Java file for this class - */ - @Override - public String toString() { - StringBuffer result = new StringBuffer(); - if (className.indexOf(".") != -1) { - result.append("package ").append(className.substring(0, className.lastIndexOf("."))).append(";"); - result.append(JAXXCompiler.getLineSeparator()); - result.append(JAXXCompiler.getLineSeparator()); - } - - if (imports.size() > 0) { - for (String anImport : imports) { - result.append("import "); - result.append(anImport); - result.append(';'); - result.append(JAXXCompiler.getLineSeparator()); - } - result.append(JAXXCompiler.getLineSeparator()); - } - - result.append(getClassDefinition()); - return result.toString(); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaFile.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,288 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.compiler; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A Java source file being generated for output. Once the class is completely initialized, use the + * {@link #toString} method to generate source code for it. + */ +public class JavaFile { + + protected static final String GETTER_PATTERN = "return %1$s;"; + + protected static final String BOOLEAN_GETTER_PATTERN = "return %1$s !=null && %1$s;"; + + protected static final String SETTER_PATTERN = "%1$s oldValue = this.%2$s;\nthis.%2$s = newValue;\nfirePropertyChange(\"%2$s\", oldValue, newValue);"; + + private int modifiers; + private String className; + private List<String> imports = new ArrayList<String>(); + private List<JavaField> fields = new ArrayList<JavaField>(); + private List<JavaMethod> methods = new ArrayList<JavaMethod>(); + private List<JavaFile> innerClasses = new ArrayList<JavaFile>(); + private String superClass; + private String[] interfaces; + private StringBuffer rawBodyCode = new StringBuffer(); + + + public JavaFile() { + } + + + public JavaFile(int modifiers, String className, String superClass) { + this(modifiers, className, superClass, null); + } + + + public JavaFile(int modifiers, String className, String superClass, String[] interfaces) { + this.modifiers = modifiers; + this.className = className; + this.superClass = superClass; + this.interfaces = interfaces; + } + + + public void addImport(String importString) { + imports.add(importString); + } + + public void addImport(Class importString) { + imports.add(importString.getName()); + } + + + public String[] getImports() { + return imports.toArray(new String[imports.size()]); + } + + + public int getModifiers() { + return modifiers; + } + + + public void setModifiers(int modifiers) { + this.modifiers = modifiers; + } + + + public String getClassName() { + return className; + } + + + public void setClassName(String className) { + this.className = className; + } + + + public String getSuperClass() { + return superClass; + } + + + public void setSuperClass(String superClass) { + this.superClass = superClass; + } + + + public String[] getInterfaces() { + return interfaces; + } + + + public void setInterfaces(String[] interfaces) { + this.interfaces = interfaces; + } + + + public void addMethod(JavaMethod method) { + methods.add(method); + } + + + public JavaMethod[] getMethods() { + return methods.toArray(new JavaMethod[methods.size()]); + } + + public void addField(JavaField field) { + addField(field, false); + } + + public void addField(JavaField field, boolean javaBean) { + addSimpleField(field); + String id = field.getName(); + String capitalizedName = JAXXCompiler.capitalize(id); + + // add getter file + String content = String.format(GETTER_PATTERN, id); + addMethod(new JavaMethod( + Modifier.isProtected(field.getModifiers()) ? Modifier.PUBLIC : Modifier.PROTECTED, + field.getType(), "get" + capitalizedName, null, null, content)); + + if (javaBean) { + // add full javabean support + if (Boolean.class.getName().equals(field.getType())) { + content = String.format(BOOLEAN_GETTER_PATTERN, id); + addMethod(new JavaMethod(Modifier.PUBLIC, field.getType(), "is" + capitalizedName, null, null, content)); + } + content = String.format(SETTER_PATTERN, field.getType(), id); + JavaArgument arg = new JavaArgument(field.getType(), "newValue"); + addMethod(new JavaMethod(Modifier.PUBLIC, "void", "set" + capitalizedName, new JavaArgument[]{arg}, null, content)); + } + } + + public void addSimpleField(JavaField field) { + fields.add(field); + } + + + public JavaField[] getFields() { + return fields.toArray(new JavaField[fields.size()]); + } + + + public static String addIndentation(String source, int indentation) { + return indent(source, indentation, false); + } + + + public static String setIndentation(String source, int indentation) { + return indent(source, indentation, true); + } + + + public static String indent(String source, int indentation, boolean trim) { + if (trim) { + source = source.trim(); + } + char[] spaces = new char[indentation]; + Arrays.fill(spaces, ' '); + StringBuffer result = new StringBuffer(); + String[] lines = source.split(System.getProperty("line.separator") + "|\n"); + for (int i = 0; i < lines.length; i++) { + if (i > 0) { + result.append(JAXXCompiler.getLineSeparator()); + } + result.append(spaces); + result.append(trim ? lines[i].trim() : lines[i]); + } + return result.toString(); + } + + + public void addBodyCode(String bodyCode) { + rawBodyCode.append(bodyCode); + } + + + public String getClassBody() { + StringBuffer result = new StringBuffer(); + if (fields.size() > 0) { + java.util.Collections.sort(fields); // sort fields + + for (JavaField field : fields) { + result.append(addIndentation(field.toString(), 4)); + result.append(JAXXCompiler.getLineSeparator()); + } + + result.append(JAXXCompiler.getLineSeparator()); + } + + if (rawBodyCode.length() > 0) { + result.append(addIndentation("/* begin raw body code */\n", 4)); + String s = rawBodyCode.toString(); + if (!s.startsWith("\n")) { + result.append('\n'); + } + result.append(addIndentation(s, 4)); + result.append('\n'); + result.append(addIndentation("/* end raw body code */", 4)); + result.append("\n"); + } + + for (JavaFile innerClass : innerClasses) { + result.append(addIndentation(innerClass.toString(), 4)); + result.append(JAXXCompiler.getLineSeparator()); + result.append(JAXXCompiler.getLineSeparator()); + } + java.util.Collections.sort(methods); // sort methods + + for (JavaMethod method : methods) { + result.append(addIndentation(method.toString(), 4)); + result.append(JAXXCompiler.getLineSeparator()); + result.append(JAXXCompiler.getLineSeparator()); + } + + return result.toString(); + } + + + public String getClassDefinition() { + StringBuffer result = new StringBuffer(); + result.append(getModifiersText(modifiers)); + result.append("class "); + result.append(className.substring(className.lastIndexOf(".") + 1)); + result.append(" extends "); + result.append(superClass); + if (interfaces != null && interfaces.length > 0) { + result.append(" implements "); + for (int i = 0; i < interfaces.length; i++) { + if (i > 0) { + result.append(", "); + } + result.append(interfaces[i]); + } + } + result.append(" {"); + result.append(JAXXCompiler.getLineSeparator()); + result.append(getClassBody()); + result.append("}"); + return result.toString(); + } + + + public static String getModifiersText(int modifiers) { + if (modifiers == 0) { + return ""; + } else { + return Modifier.toString(modifiers) + ' '; + } + } + + + /** + * Returns the Java source code for this class. + * + * @return a complete Java file for this class + */ + @Override + public String toString() { + StringBuffer result = new StringBuffer(); + if (className.indexOf(".") != -1) { + result.append("package ").append(className.substring(0, className.lastIndexOf("."))).append(";"); + result.append(JAXXCompiler.getLineSeparator()); + result.append(JAXXCompiler.getLineSeparator()); + } + + if (imports.size() > 0) { + for (String anImport : imports) { + result.append("import "); + result.append(anImport); + result.append(';'); + result.append(JAXXCompiler.getLineSeparator()); + } + result.append(JAXXCompiler.getLineSeparator()); + } + + result.append(getClassDefinition()); + return result.toString(); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,205 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.compiler; - -/** - * Represents a method in a Java source file being generated for output. <code>JavaMethods</code> are created - * and added to a {@link JavaFile}, which can then output Java source code. In addition to normal methods, a - * <code>JavaMethod</code> can represent a constructor -- constructors should be named after their containing - * classes and have a return type of <code>null</code>. - */ -public class JavaMethod { - private int modifiers; - private String returnType; - private String name; - private JavaArgument[] arguments; - private String[] exceptions; - private StringBuffer bodyCode; - - - /** - * Constructs a new no-argument <code>JavaMethod</code> which throws no checked exceptions. The - * <code>modifiers</code> parameter is a bit mask of the constants from {@link java.lang.reflect.Modifier}, - * and the <code>returnType</code> of the method should be represented as it would appear in Java source - * code (<code>null</code> for a constructor). The method body is initially empty. - * - * @param modifiers the modifier keywords that should appear as part of the method's declaration - * @param returnType the return type of the method as it would appear in Java source code - * @param name the method's name - * @see #appendBodyCode - */ - public JavaMethod(int modifiers, String returnType, String name) { - this(modifiers, returnType, name, null); - } - - - /** - * Constructs a new <code>JavaMethod</code> which throws no checked exceptions. The <code>modifiers</code> - * parameter is a bit mask of the constants from {@link java.lang.reflect.Modifier}, and the - * <code>returnType</code> of the method should be represented as it would appear in Java source code - * (<code>null</code> for a constructor). The method body is initially empty. - * - * @param modifiers the modifier keywords that should appear as part of the method's declaration - * @param returnType the return type of the method as it would appear in Java source code - * @param name the method's name - * @param arguments the method's arguments - * @see #appendBodyCode - */ - public JavaMethod(int modifiers, String returnType, String name, JavaArgument[] arguments) { - this(modifiers, returnType, name, arguments, null); - } - - - /** - * Constructs a new <code>JavaMethod</code>. The <code>modifiers</code> parameter is a bit mask of the - * constants from {@link java.lang.reflect.Modifier}, and the <code>returnType</code> and <code>exceptions</code> - * of the method should be represented as they would appear in Java source code (<code>null</code> for a - * constructor). The method body is initially empty. - * - * @param modifiers the modifier keywords that should appear as part of the method's declaration - * @param returnType the return type of the method as it would appear in Java source code - * @param name the method's name - * @param arguments the method's arguments - * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code - * @see #appendBodyCode - */ - public JavaMethod(int modifiers, String returnType, String name, JavaArgument[] arguments, String[] exceptions) { - this(modifiers, returnType, name, arguments, exceptions, null); - } - - - /** - * Constructs a new <code>JavaMethod</code> containing the specified body code. The <code>modifiers</code> parameter - * is a bit mask of the constants from {@link java.lang.reflect.Modifier}, and the <code>returnType</code> and - * <code>exceptions</code> of the method should be represented as they would appear in Java source code (<code>null</code> - * for a constructor). The method body is initially empty. - * - * @param modifiers the modifier keywords that should appear as part of the method's declaration - * @param returnType the return type of the method as it would appear in Java source code - * @param name the method's name - * @param arguments the method's arguments - * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code - * @param bodyCode Java source code which should appear in the method body - */ - public JavaMethod(int modifiers, String returnType, String name, JavaArgument[] arguments, String[] exceptions, String bodyCode) { - this.modifiers = modifiers; - this.returnType = returnType; - this.name = name; - this.arguments = arguments; - this.exceptions = exceptions; - this.bodyCode = new StringBuffer(bodyCode != null ? bodyCode : ""); - } - - - /** - * Returns a bit mask describing the modifier keywords which should appear as part of this method's - * declaration. See <code>java.lang.reflect.Modifier</code> for more information on decoding this - * field. - * - * @return the modifier bit mask - */ - public int getModifiers() { - return modifiers; - } - - - /** - * Returns the method's return type, as it would be represented in Java source code. - * - * @return the method's return type - */ - public String getReturnType() { - return returnType; - } - - - /** - * Returns the method's name. - * - * @return the method's name - */ - public String getName() { - return name; - } - - - /** - * Returns a list of the method's arguments. - * - * @return the method's arguments - */ - public JavaArgument[] getArguments() { - return arguments; - } - - - /** - * Returns a list of exceptions the method can throw. - * - * @return the method's exceptions - */ - public String[] getExceptions() { - return exceptions; - } - - - /** - * Returns the Java source code for the method's body. - * - * @return the method's body code - */ - public String getBodyCode() { - return bodyCode.toString(); - } - - - /** - * Appends additional code to the method's body. - * - * @param extraCode Java source code to append to the method's body - */ - public void appendBodyCode(String extraCode) { - if (extraCode.length() == 0) - return; - if (bodyCode.length() > 0 && !bodyCode.toString().endsWith(JAXXCompiler.getLineSeparator())) - bodyCode.append(JAXXCompiler.getLineSeparator()); - bodyCode.append(extraCode); - } - - - /** - * Returns the Java source code for this method. - * - * @return the Java source code for this method - */ - public String toString() { - StringBuffer result = new StringBuffer(); - result.append(JavaFile.getModifiersText(modifiers)); - if (returnType != null) { - result.append(returnType); - result.append(' '); - } - result.append(name); - result.append('('); - if (arguments != null) { - for (int i = 0; i < arguments.length; i++) { - if (i > 0) - result.append(", "); - result.append(arguments[i].toString()); - } - } - result.append(") {"); - result.append(JAXXCompiler.getLineSeparator()); - if (bodyCode != null) { - String formattedBodyCode = JavaFile.addIndentation(bodyCode.toString().trim(), 4); - if (formattedBodyCode.length() > 0) { - result.append(formattedBodyCode); - result.append(JAXXCompiler.getLineSeparator()); - } - } - result.append("}"); - return result.toString(); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/compiler/JavaMethod.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,276 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.compiler; + +import java.lang.reflect.Modifier; +import java.util.Comparator; + +/** + * Represents a method in a Java source file being generated for output. <code>JavaMethods</code> are created + * and added to a {@link JavaFile}, which can then output Java source code. In addition to normal methods, a + * <code>JavaMethod</code> can represent a constructor -- constructors should be named after their containing + * classes and have a return type of <code>null</code>. + */ +public class JavaMethod implements Comparable<JavaMethod> { + private int modifiers; + private String returnType; + private String name; + private JavaArgument[] arguments; + private String[] exceptions; + private StringBuffer bodyCode; + + + /** + * Constructs a new no-argument <code>JavaMethod</code> which throws no checked exceptions. The + * <code>modifiers</code> parameter is a bit mask of the constants from {@link java.lang.reflect.Modifier}, + * and the <code>returnType</code> of the method should be represented as it would appear in Java source + * code (<code>null</code> for a constructor). The method body is initially empty. + * + * @param modifiers the modifier keywords that should appear as part of the method's declaration + * @param returnType the return type of the method as it would appear in Java source code + * @param name the method's name + * @see #appendBodyCode + */ + public JavaMethod(int modifiers, String returnType, String name) { + this(modifiers, returnType, name, null); + } + + + /** + * Constructs a new <code>JavaMethod</code> which throws no checked exceptions. The <code>modifiers</code> + * parameter is a bit mask of the constants from {@link java.lang.reflect.Modifier}, and the + * <code>returnType</code> of the method should be represented as it would appear in Java source code + * (<code>null</code> for a constructor). The method body is initially empty. + * + * @param modifiers the modifier keywords that should appear as part of the method's declaration + * @param returnType the return type of the method as it would appear in Java source code + * @param name the method's name + * @param arguments the method's arguments + * @see #appendBodyCode + */ + public JavaMethod(int modifiers, String returnType, String name, JavaArgument[] arguments) { + this(modifiers, returnType, name, arguments, null); + } + + + /** + * Constructs a new <code>JavaMethod</code>. The <code>modifiers</code> parameter is a bit mask of the + * constants from {@link java.lang.reflect.Modifier}, and the <code>returnType</code> and <code>exceptions</code> + * of the method should be represented as they would appear in Java source code (<code>null</code> for a + * constructor). The method body is initially empty. + * + * @param modifiers the modifier keywords that should appear as part of the method's declaration + * @param returnType the return type of the method as it would appear in Java source code + * @param name the method's name + * @param arguments the method's arguments + * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code + * @see #appendBodyCode + */ + public JavaMethod(int modifiers, String returnType, String name, JavaArgument[] arguments, String[] exceptions) { + this(modifiers, returnType, name, arguments, exceptions, null); + } + + + /** + * Constructs a new <code>JavaMethod</code> containing the specified body code. The <code>modifiers</code> parameter + * is a bit mask of the constants from {@link java.lang.reflect.Modifier}, and the <code>returnType</code> and + * <code>exceptions</code> of the method should be represented as they would appear in Java source code (<code>null</code> + * for a constructor). The method body is initially empty. + * + * @param modifiers the modifier keywords that should appear as part of the method's declaration + * @param returnType the return type of the method as it would appear in Java source code + * @param name the method's name + * @param arguments the method's arguments + * @param exceptions a list of exceptions the methods can throw, as they would be represented in Java source code + * @param bodyCode Java source code which should appear in the method body + */ + public JavaMethod(int modifiers, String returnType, String name, JavaArgument[] arguments, String[] exceptions, String bodyCode) { + this.modifiers = modifiers; + this.returnType = returnType; + this.name = name; + this.arguments = arguments; + this.exceptions = exceptions; + this.bodyCode = new StringBuffer(bodyCode != null ? bodyCode : ""); + } + + + /** + * Returns a bit mask describing the modifier keywords which should appear as part of this method's + * declaration. See <code>java.lang.reflect.Modifier</code> for more information on decoding this + * field. + * + * @return the modifier bit mask + */ + public int getModifiers() { + return modifiers; + } + + + /** + * Returns the method's return type, as it would be represented in Java source code. + * + * @return the method's return type + */ + public String getReturnType() { + return returnType; + } + + + /** + * Returns the method's name. + * + * @return the method's name + */ + public String getName() { + return name; + } + + + /** + * Returns a list of the method's arguments. + * + * @return the method's arguments + */ + public JavaArgument[] getArguments() { + return arguments; + } + + + /** + * Returns a list of exceptions the method can throw. + * + * @return the method's exceptions + */ + public String[] getExceptions() { + return exceptions; + } + + + /** + * Returns the Java source code for the method's body. + * + * @return the method's body code + */ + public String getBodyCode() { + return bodyCode.toString(); + } + + + /** + * Appends additional code to the method's body. + * + * @param extraCode Java source code to append to the method's body + */ + public void appendBodyCode(String extraCode) { + if (extraCode.length() == 0) { + return; + } + if (bodyCode.length() > 0 && !bodyCode.toString().endsWith(JAXXCompiler.getLineSeparator())) { + bodyCode.append(JAXXCompiler.getLineSeparator()); + } + bodyCode.append(extraCode); + } + + + /** + * Returns the Java source code for this method. + * + * @return the Java source code for this method + */ + @Override + public String toString() { + StringBuffer result = new StringBuffer(); + result.append(JavaFile.getModifiersText(modifiers)); + if (returnType != null) { + result.append(returnType); + result.append(' '); + } + result.append(name); + result.append('('); + if (arguments != null) { + for (int i = 0; i < arguments.length; i++) { + if (i > 0) { + result.append(", "); + } + result.append(arguments[i].toString()); + } + } + result.append(") {"); + result.append(JAXXCompiler.getLineSeparator()); + if (bodyCode != null) { + String formattedBodyCode = JavaFile.addIndentation(bodyCode.toString().trim(), 4); + if (formattedBodyCode.length() > 0) { + result.append(formattedBodyCode); + result.append(JAXXCompiler.getLineSeparator()); + } + } + result.append("}"); + return result.toString(); + } + + public int compareTo(JavaMethod o) { + return COMPARATOR.compare(this, o); + } + + public static final Comparator<JavaMethod> COMPARATOR = new Comparator<JavaMethod>() { + + public int compare(JavaMethod o1, JavaMethod o2) { + + int result; + if ((result = compareStatic(o1, o2)) != 0) { + return result; + } + if ((result = compareConstructor(o1, o2)) != 0) { + return result; + } + if ((result = compareVisibility(o1, o2)) != 0) { + return result; + } + return o1.name.compareTo(o2.name); + } + + public int compareStatic(JavaMethod o1, JavaMethod o2) { + if (Modifier.isStatic(o1.modifiers) && !Modifier.isStatic(o2.modifiers)) { + return -1; + } + if (!Modifier.isStatic(o1.modifiers) && Modifier.isStatic(o2.modifiers)) { + return 1; + } + return 0; + } + + public int compareConstructor(JavaMethod o1, JavaMethod o2) { + if (o1.returnType == null && o2.returnType != null) { + return -1; + } + if (o1.returnType != null && o2.returnType == null) { + return 1; + } + return 0; + } + + public int compareVisibility(JavaMethod o1, JavaMethod o2) { + if (Modifier.isPublic(o1.modifiers) && !Modifier.isPublic(o2.modifiers)) { + return -1; + } + if (!Modifier.isPublic(o1.modifiers) && Modifier.isPublic(o2.modifiers)) { + return 1; + } + if (Modifier.isProtected(o1.modifiers) && !Modifier.isProtected(o2.modifiers)) { + return -1; + } + if (!Modifier.isProtected(o1.modifiers) && Modifier.isProtected(o2.modifiers)) { + return 1; + } + if (Modifier.isPrivate(o1.modifiers) && !Modifier.isPrivate(o2.modifiers)) { + return -1; + } + if (!Modifier.isPrivate(o1.modifiers) && Modifier.isPrivate(o2.modifiers)) { + return 1; + } + return 0; + } + }; +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Rule.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/css/Rule.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Rule.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,79 +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 java.io.Serializable; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -public class Rule implements Serializable, Comparable { - public static final String INLINE_ATTRIBUTE = "<inline attribute>"; - public static final String DATA_BINDING = "<data binding>"; - - private Selector[] selectors; - private Map<String, String> properties; - private static final long serialVersionUID = -5314603817367239301L; - - - public Rule(Selector[] selectors, Map<String, String> properties) { - this.selectors = selectors; - Arrays.sort(selectors); - this.properties = properties; - } - - - public Rule(Selector[] selectors, String[] keys, String[] values) { - this.selectors = selectors; - Arrays.sort(selectors); - this.properties = new HashMap<String, String>(); - if (keys.length != values.length) - throw new IllegalArgumentException("keys and values must have the same number of entries"); - for (int i = 0; i < keys.length; i++) - properties.put(keys[i], values[i]); - } - - - public static Rule inlineAttribute(CompiledObject object, String propertyName, boolean dataBinding) { - Map<String, String> properties = new HashMap<String, String>(); - properties.put(propertyName, dataBinding ? DATA_BINDING : INLINE_ATTRIBUTE); - return new Rule(new Selector[]{new Selector(null, null, null, object.getId(), true)}, properties); - } - - - public Selector[] getSelectors() { - return selectors; - } - - - public Map<String, String> getProperties() { - return properties; - } - - - public int appliesTo(CompiledObject object) throws CompilerException { - int appliesTo = Selector.NEVER_APPLIES; - for (Selector selector : selectors) { - appliesTo = Math.max(selector.appliesTo(object), appliesTo); - if (appliesTo == Selector.ALWAYS_APPLIES || appliesTo == Selector.ALWAYS_APPLIES_INHERIT_ONLY) - break; - } - return appliesTo; - } - - - public int compareTo(Object o) { - Rule r = (Rule) o; - return selectors[0].compareTo(r.selectors[0]); // they are already sorted so we only need to compare the highest-ranked from each one - } - - @Override - public String toString() { - return "Rule[" + Arrays.asList(selectors) + ", " + properties + "]"; - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Rule.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/css/Rule.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Rule.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Rule.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,79 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.css; + +import jaxx.CompilerException; +import jaxx.compiler.CompiledObject; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class Rule implements Serializable, Comparable { + public static final String INLINE_ATTRIBUTE = "<inline attribute>"; + public static final String DATA_BINDING = "<data binding>"; + + private Selector[] selectors; + private Map<String, String> properties; + private static final long serialVersionUID = 1L; + + + public Rule(Selector[] selectors, Map<String, String> properties) { + this.selectors = selectors; + Arrays.sort(selectors); + this.properties = properties; + } + + + public Rule(Selector[] selectors, String[] keys, String[] values) { + this.selectors = selectors; + Arrays.sort(selectors); + this.properties = new HashMap<String, String>(); + if (keys.length != values.length) + throw new IllegalArgumentException("keys and values must have the same number of entries"); + for (int i = 0; i < keys.length; i++) + properties.put(keys[i], values[i]); + } + + + public static Rule inlineAttribute(CompiledObject object, String propertyName, boolean dataBinding) { + Map<String, String> properties = new HashMap<String, String>(); + properties.put(propertyName, dataBinding ? DATA_BINDING : INLINE_ATTRIBUTE); + return new Rule(new Selector[]{new Selector(null, null, null, object.getId(), true)}, properties); + } + + + public Selector[] getSelectors() { + return selectors; + } + + + public Map<String, String> getProperties() { + return properties; + } + + + public int appliesTo(CompiledObject object) throws CompilerException { + int appliesTo = Selector.NEVER_APPLIES; + for (Selector selector : selectors) { + appliesTo = Math.max(selector.appliesTo(object), appliesTo); + if (appliesTo == Selector.ALWAYS_APPLIES || appliesTo == Selector.ALWAYS_APPLIES_INHERIT_ONLY) + break; + } + return appliesTo; + } + + + public int compareTo(Object o) { + Rule r = (Rule) o; + return selectors[0].compareTo(r.selectors[0]); // they are already sorted so we only need to compare the highest-ranked from each one + } + + @Override + public String toString() { + return "Rule[" + Arrays.asList(selectors) + ", " + properties + "]"; + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Stylesheet.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/css/Stylesheet.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Stylesheet.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,449 +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.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 Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Stylesheet.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/css/Stylesheet.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Stylesheet.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/css/Stylesheet.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -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 = 1L; + + + 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.7/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,329 +0,0 @@ -package jaxx.reflect; - -import jaxx.CompilerException; -import jaxx.compiler.JAXXCompiler; -import jaxx.compiler.SymbolTable; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXObjectDescriptor; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.net.URL; -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; - -/** - * Mirrors the class <code>java.lang.ClassLoader</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> - * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled - * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle - * circular dependencies). - */ -public class ClassDescriptorLoader { - - private static Map<String, ClassDescriptor> descriptors = new HashMap<String, ClassDescriptor>(); - - private ClassDescriptorLoader() { - } - - - public static synchronized ClassDescriptor getClassDescriptor(String className) throws ClassNotFoundException { - return getClassDescriptor(className, ClassDescriptorLoader.class.getClassLoader()); - } - - public static synchronized ClassDescriptor getClassDescriptor(String className, ClassLoader classLoader) throws ClassNotFoundException { - ClassDescriptor result = descriptors.get(className); - if (result == null) { - if (JAXXCompiler.getSymbolTable(className) != null) - result = createClassDescriptorFromSymbolTable(className, classLoader); - else { - if (classLoader == null) - classLoader = ClassDescriptorLoader.class.getClassLoader(); - - String relativePath = className.replaceAll("\\.", "/"); - String relativePathPattern = ".*";// + className + ".*"; // used to ensure that the located resource has the right character cases - - // find the most recently updated source for the class -- Java source, JAXX source, or compiled class file - long javaLastModified = -1; - URL javaFile = classLoader.getResource(relativePath + ".java"); - if (javaFile != null && javaFile.toString().startsWith("file:") && javaFile.toString().matches(relativePathPattern)) - javaLastModified = JAXXCompiler.URLtoFile(javaFile).lastModified(); - - long classLastModified = -1; - URL classFile = classLoader.getResource(relativePath + ".class"); - if (classFile != null && classFile.toString().startsWith("file:") && classFile.toString().matches(relativePathPattern)) - classLastModified = JAXXCompiler.URLtoFile(classFile).lastModified(); - - long jaxxLastModified = -1; - URL jaxxFile = classLoader.getResource(relativePath + ".jaxx"); - if (jaxxFile != null && jaxxFile.toString().startsWith("file:") && jaxxFile.toString().matches(relativePathPattern)) { - File jaxxFilePath = JAXXCompiler.URLtoFile(jaxxFile); - jaxxLastModified = jaxxFilePath.lastModified(); - String simplePath = jaxxFilePath.getPath(); - simplePath = simplePath.substring(0, simplePath.length() - ".jaxx".length()); - File cssFilePath = new File(simplePath + ".css"); - if (cssFilePath.exists()) - jaxxLastModified = Math.max(jaxxLastModified, cssFilePath.lastModified()); - File scriptFilePath = new File(simplePath + ".script"); - if (scriptFilePath.exists()) - jaxxLastModified = Math.max(jaxxLastModified, scriptFilePath.lastModified()); - } - - if (jaxxLastModified != -1 && JAXXCompiler.getSymbolTable(className) == null) - jaxxLastModified = -1; // file has been modified, but wasn't included in this - // compilation set so we don't have a symbol table - - if (javaLastModified != -1 || classLastModified != -1 || jaxxLastModified != -1) { - if (jaxxLastModified > classLastModified && jaxxLastModified > javaLastModified) - result = createClassDescriptorFromSymbolTable(className, classLoader); - else - if (javaLastModified > classLastModified && javaLastModified > jaxxLastModified) - result = createClassDescriptorFromJavaSource(javaFile, classLoader); - } - // else work off of the class file. This also handles the case where the class is available, but wasn't in a location where - // we could check its last modified date (in a JAR, over the network, etc.) - if (result == null) { - Class javaClass = getClass(className, classLoader); - result = createClassDescriptorFromClass(javaClass); - } - } - descriptors.put(className, result); - } - return result; - } - - - public static ClassDescriptor getClassDescriptor(Class javaClass) { - try { - return getClassDescriptor(javaClass.getName(), javaClass.getClassLoader()); - } - catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - public static Class getClass(String className, ClassLoader classLoader) throws ClassNotFoundException { - if (className.equals("boolean")) - return boolean.class; - if (className.equals("byte")) { - return byte.class; - } - if (className.equals("short")) { - return short.class; - } - if (className.equals("int")) { - return int.class; - } - if (className.equals("long")) { - return long.class; - } - if (className.equals("float")) { - return float.class; - } - if (className.equals("double")) { - return double.class; - } - if (className.equals("char")) { - return char.class; - } - int arrayCount = 0; - while (className.endsWith("[]")) { - arrayCount++; - className = className.substring(0, className.length() - 2); - } - if (arrayCount > 0) { - className = "L" + className + ";"; - while (arrayCount > 0) { - className = "[" + className; - arrayCount--; - } - } - try { - return classLoader != null ? Class.forName(className, true, classLoader) : Class.forName(className); - } - catch (NoClassDefFoundError e) { - throw new ClassNotFoundException(e.toString()); - } - } - - - private static MethodDescriptor createMethodDescriptor(Method javaMethod, ClassLoader classLoader) { - String methodName = javaMethod.getName(); - int modifiers = javaMethod.getModifiers(); - String returnType = javaMethod.getReturnType().getName(); - Class[] javaParameters = javaMethod.getParameterTypes(); - String[] parameters = new String[javaParameters.length]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = javaParameters[i].getName(); - } - return new MethodDescriptor(methodName, modifiers, returnType, parameters, classLoader); - } - - - private static FieldDescriptor createFieldDescriptor(Field javaField, ClassLoader classLoader) { - String fieldName = javaField.getName(); - int modifiers = javaField.getModifiers(); - String type = javaField.getType().getName(); - return new FieldDescriptor(fieldName, modifiers, type, classLoader); - } - - - private static JAXXObjectDescriptor getJAXXObjectDescriptor(Class<?> jaxxClass) { - if (!JAXXObject.class.isAssignableFrom(jaxxClass) || jaxxClass == JAXXObject.class) - return null; - try { - Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor", new Class[0]); - return (JAXXObjectDescriptor) getJAXXObjectDescriptor.invoke(null); - } - catch (NoSuchMethodException e) { - throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + " to have a static method named $getJAXXObjectDescriptor"); - } - catch (IllegalAccessException e) { - throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + "'s $getJAXXObjectDescriptor method to be public"); - } - catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - - private static ClassDescriptor createClassDescriptorFromJavaSource(URL javaSource, ClassLoader classLoader) throws ClassNotFoundException { - try { - InputStream in = javaSource.openStream(); - Reader reader = new InputStreamReader(in); - ClassDescriptor result = JavaFileParser.parseJavaFile(javaSource.toString(), reader, classLoader); - reader.close(); - return result; - } - catch (IOException e) { - throw new ClassNotFoundException(e.toString()); - } - } - - - private static ClassDescriptor createClassDescriptorFromSymbolTable(String className, ClassLoader classLoader) throws ClassNotFoundException { - final JAXXCompiler compiler = JAXXCompiler.getJAXXCompiler(className); - final SymbolTable symbolTable = JAXXCompiler.getSymbolTable(className); - if (symbolTable == null) { - throw new CompilerException("Internal error: no symbol table was generated for class '" + className + "'"); - } - ClassDescriptor superclass = getClassDescriptor(symbolTable.getSuperclassName(), classLoader); - List<MethodDescriptor> publicMethods = symbolTable.getScriptMethods(); - List<FieldDescriptor> publicFields = symbolTable.getScriptFields(); - //List<MethodDescriptor> declaredMethods = new ArrayList<MethodDescriptor>(publicMethods); - //List<FieldDescriptor> declaredFields = new ArrayList<FieldDescriptor>(publicFields); - Iterator<MethodDescriptor> methods = publicMethods.iterator(); - while (methods.hasNext()) { - MethodDescriptor method = methods.next(); - if (!Modifier.isPublic(method.getModifiers())) { - methods.remove(); - } - } - Iterator<FieldDescriptor> fields = publicFields.iterator(); - while (fields.hasNext()) { - FieldDescriptor field = fields.next(); - if (!Modifier.isPublic(field.getModifiers())) { - fields.remove(); - } - } - publicMethods.addAll(Arrays.asList(superclass.getMethodDescriptors())); - publicFields.addAll(Arrays.asList(superclass.getFieldDescriptors())); - int dotPos = className.lastIndexOf("."); - String packageName = dotPos != -1 ? className.substring(0, dotPos) : null; - Set<String> interfaces = new HashSet<String>(); - ClassDescriptor[] superclassInterfaces = superclass.getInterfaces(); - for (ClassDescriptor superclassInterface : superclassInterfaces) { - interfaces.add(superclassInterface.getName()); - } - interfaces.add(JAXXObject.class.getName()); - return new ClassDescriptor(className, packageName, symbolTable.getSuperclassName(), - (String[]) interfaces.toArray(new String[interfaces.size()]), false, false, null, null, classLoader, - (MethodDescriptor[]) publicMethods.toArray(new MethodDescriptor[publicMethods.size()]), - (FieldDescriptor[]) publicFields.toArray(new FieldDescriptor[publicFields.size()])) { - public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { - String type = symbolTable.getClassTagIds().get(name); - if (type != null) { - return new FieldDescriptor(name, Modifier.PROTECTED, type, compiler.getClassLoader()); - } - throw new NoSuchFieldException(name); - } - - - public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor[] parameterTypes) throws NoSuchMethodException { - throw new NoSuchMethodException(name); - } - - @Override - public JAXXObjectDescriptor getJAXXObjectDescriptor() { - return compiler.getJAXXObjectDescriptor(); - } - }; - } - - - private static ClassDescriptor createClassDescriptorFromClass(final Class<?> javaClass) { - String name = javaClass.getName(); - Package p = javaClass.getPackage(); - String packageName = p != null ? p.getName() : null; - Class superclass = javaClass.getSuperclass(); - String superclassName = superclass != null ? superclass.getName() : null; - Class[] interfaces = javaClass.getInterfaces(); - String[] interfaceNames = new String[interfaces.length]; - for (int i = 0; i < interfaces.length; i++) { - interfaceNames[i] = interfaces[i].getName(); - } - boolean isInterface = javaClass.isInterface(); - boolean isArray = javaClass.isArray(); - String componentTypeName = isArray ? javaClass.getComponentType().getName() : null; - JAXXObjectDescriptor jaxxObjectDescriptor = getJAXXObjectDescriptor(javaClass); - ClassLoader classLoader = javaClass.getClassLoader(); - Method[] javaMethods = javaClass.getMethods(); - MethodDescriptor[] methods = new MethodDescriptor[javaMethods.length]; - for (int i = 0; i < methods.length; i++) { - methods[i] = createMethodDescriptor(javaMethods[i], javaClass.getClassLoader()); - } - Field[] javaFields = javaClass.getFields(); - FieldDescriptor[] fields = new FieldDescriptor[javaFields.length]; - for (int i = 0; i < fields.length; i++) { - fields[i] = createFieldDescriptor(javaFields[i], javaClass.getClassLoader()); - } - return new ClassDescriptor(name, packageName, superclassName, interfaceNames, isInterface, isArray, componentTypeName, jaxxObjectDescriptor, classLoader, methods, fields) { - public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { - return createFieldDescriptor(javaClass.getDeclaredField(name), javaClass.getClassLoader()); - } - - public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor[] parameterTypes) throws NoSuchMethodException { - try { - Class[] parameterTypeClasses = new Class[parameterTypes.length]; - for (int i = 0; i < parameterTypes.length; i++) { - parameterTypeClasses[i] = Class.forName(parameterTypes[i].getName()); - } - return createMethodDescriptor(javaClass.getDeclaredMethod(name, parameterTypeClasses), javaClass.getClassLoader()); - } - catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - }; - } - - public static void checkSupportClass(Class<?> handlerClass, ClassDescriptor beanClass, Class<?>... tagClasses) { - for (Class<?> tagClass : tagClasses) { - if (getClassDescriptor(tagClass).isAssignableFrom(beanClass)) { - return; - } - } - throw new IllegalArgumentException(handlerClass.getName() + " does not support the class " + beanClass.getName()); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java (from rev 1052, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/reflect/ClassDescriptorLoader.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,356 @@ +package jaxx.reflect; + +import jaxx.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.SymbolTable; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +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; + +/** + * Mirrors the class <code>java.lang.ClassLoader</code>. JAXX uses <code>ClassDescriptor</code> instead of <code>Class</code> + * almost everywhere so that it can handle circular dependencies (there can't be a <code>Class</code> object for an uncompiled + * JAXX or Java source file, and a compiler must be allow references to symbols in uncompiled source files in order to handle + * circular dependencies). + */ +public class ClassDescriptorLoader { + + private static Map<String, ClassDescriptor> descriptors = new HashMap<String, ClassDescriptor>(); + + private ClassDescriptorLoader() { + } + + + public static synchronized ClassDescriptor getClassDescriptor(String className) throws ClassNotFoundException { + return getClassDescriptor(className, ClassDescriptorLoader.class.getClassLoader()); + } + + public static synchronized ClassDescriptor getClassDescriptor(String className, ClassLoader classLoader) throws ClassNotFoundException { + ClassDescriptor result = descriptors.get(className); + if (result == null) { + if (JAXXCompiler.getSymbolTable(className) != null) { + result = createClassDescriptorFromSymbolTable(className, classLoader); + } else { + if (classLoader == null) { + classLoader = ClassDescriptorLoader.class.getClassLoader(); + } + + String relativePath = className.replaceAll("\\.", "/"); + String relativePathPattern = ".*";// + className + ".*"; // used to ensure that the located resource has the right character cases + + // find the most recently updated source for the class -- Java source, JAXX source, or compiled class file + long javaLastModified = -1; + URL javaFile = classLoader.getResource(relativePath + ".java"); + if (javaFile != null && javaFile.toString().startsWith("file:") && javaFile.toString().matches(relativePathPattern)) { + javaLastModified = JAXXCompiler.URLtoFile(javaFile).lastModified(); + } + + long classLastModified = -1; + URL classFile = classLoader.getResource(relativePath + ".class"); + if (classFile != null && classFile.toString().startsWith("file:") && classFile.toString().matches(relativePathPattern)) { + classLastModified = JAXXCompiler.URLtoFile(classFile).lastModified(); + } + + long jaxxLastModified = -1; + URL jaxxFile = classLoader.getResource(relativePath + ".jaxx"); + if (jaxxFile != null && jaxxFile.toString().startsWith("file:") && jaxxFile.toString().matches(relativePathPattern)) { + File jaxxFilePath = JAXXCompiler.URLtoFile(jaxxFile); + jaxxLastModified = jaxxFilePath.lastModified(); + String simplePath = jaxxFilePath.getPath(); + simplePath = simplePath.substring(0, simplePath.length() - ".jaxx".length()); + File cssFilePath = new File(simplePath + ".css"); + if (cssFilePath.exists()) { + jaxxLastModified = Math.max(jaxxLastModified, cssFilePath.lastModified()); + } + File scriptFilePath = new File(simplePath + ".script"); + if (scriptFilePath.exists()) { + jaxxLastModified = Math.max(jaxxLastModified, scriptFilePath.lastModified()); + } + } + + if (jaxxLastModified != -1 && JAXXCompiler.getSymbolTable(className) == null) { + jaxxLastModified = -1; // file has been modified, but wasn't included in this + } + // compilation set so we don't have a symbol table + + if (javaLastModified != -1 || classLastModified != -1 || jaxxLastModified != -1) { + if (jaxxLastModified > classLastModified && jaxxLastModified > javaLastModified) { + result = createClassDescriptorFromSymbolTable(className, classLoader); + } else if (javaLastModified > classLastModified && javaLastModified > jaxxLastModified) { + result = createClassDescriptorFromJavaSource(javaFile, classLoader); + } + } + // else work off of the class file. This also handles the case where the class is available, but wasn't in a location where + // we could check its last modified date (in a JAR, over the network, etc.) + if (result == null) { + Class javaClass = getClass(className, classLoader); + result = createClassDescriptorFromClass(javaClass); + } + } + descriptors.put(className, result); + } + return result; + } + + + public static ClassDescriptor getClassDescriptor(Class javaClass) { + try { + return getClassDescriptor(javaClass.getName(), javaClass.getClassLoader()); + } + catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + public static Class getClass(String className, ClassLoader classLoader) throws ClassNotFoundException { + if (className.equals("boolean")) { + return boolean.class; + } + if (className.equals("byte")) { + return byte.class; + } + if (className.equals("short")) { + return short.class; + } + if (className.equals("int")) { + return int.class; + } + if (className.equals("long")) { + return long.class; + } + if (className.equals("float")) { + return float.class; + } + if (className.equals("double")) { + return double.class; + } + if (className.equals("char")) { + return char.class; + } + int arrayCount = 0; + while (className.endsWith("[]")) { + arrayCount++; + className = className.substring(0, className.length() - 2); + } + if (arrayCount > 0) { + className = "L" + className + ";"; + while (arrayCount > 0) { + className = "[" + className; + arrayCount--; + } + } + try { + return classLoader != null ? Class.forName(className, true, classLoader) : Class.forName(className); + } catch (ClassNotFoundException e) { + // perharps we are in a inner class ? + int dotIndex = className.lastIndexOf("."); + if (dotIndex > -1) { + String parentFQN = className.substring(0, dotIndex); + String simpleName = className.substring(dotIndex + 1); + try { + Class<?> parentClass = classLoader != null ? Class.forName(parentFQN, true, classLoader) : Class.forName(parentFQN); + for (Class<?> innerClass : parentClass.getClasses()) { + if (simpleName.equals(innerClass.getSimpleName())) { + return innerClass; + } + } + } catch (ClassNotFoundException e1) { + // no super class,so let the first exception throw... + } + } + throw e; + } + catch (NoClassDefFoundError e) { + + throw new ClassNotFoundException(e.toString()); + } + } + + + private static MethodDescriptor createMethodDescriptor(Method javaMethod, ClassLoader classLoader) { + String methodName = javaMethod.getName(); + int modifiers = javaMethod.getModifiers(); + String returnType = javaMethod.getReturnType().getName(); + Class[] javaParameters = javaMethod.getParameterTypes(); + String[] parameters = new String[javaParameters.length]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = javaParameters[i].getName(); + } + return new MethodDescriptor(methodName, modifiers, returnType, parameters, classLoader); + } + + + private static FieldDescriptor createFieldDescriptor(Field javaField, ClassLoader classLoader) { + String fieldName = javaField.getName(); + int modifiers = javaField.getModifiers(); + String type = javaField.getType().getName(); + return new FieldDescriptor(fieldName, modifiers, type, classLoader); + } + + + private static JAXXObjectDescriptor getJAXXObjectDescriptor(Class<?> jaxxClass) { + if (!JAXXObject.class.isAssignableFrom(jaxxClass) || jaxxClass == JAXXObject.class) { + return null; + } + try { + Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor", new Class[0]); + return (JAXXObjectDescriptor) getJAXXObjectDescriptor.invoke(null); + } + catch (NoSuchMethodException e) { + throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + " to have a static method named $getJAXXObjectDescriptor"); + } + catch (IllegalAccessException e) { + throw new CompilerException("Expected JAXXObject " + jaxxClass.getName() + "'s $getJAXXObjectDescriptor method to be public"); + } + catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + + private static ClassDescriptor createClassDescriptorFromJavaSource(URL javaSource, ClassLoader classLoader) throws ClassNotFoundException { + try { + InputStream in = javaSource.openStream(); + Reader reader = new InputStreamReader(in); + ClassDescriptor result = JavaFileParser.parseJavaFile(javaSource.toString(), reader, classLoader); + reader.close(); + return result; + } + catch (IOException e) { + throw new ClassNotFoundException(e.toString()); + } + } + + + private static ClassDescriptor createClassDescriptorFromSymbolTable(String className, ClassLoader classLoader) throws ClassNotFoundException { + final JAXXCompiler compiler = JAXXCompiler.getJAXXCompiler(className); + final SymbolTable symbolTable = JAXXCompiler.getSymbolTable(className); + if (symbolTable == null) { + throw new CompilerException("Internal error: no symbol table was generated for class '" + className + "'"); + } + ClassDescriptor superclass = getClassDescriptor(symbolTable.getSuperclassName(), classLoader); + List<MethodDescriptor> publicMethods = symbolTable.getScriptMethods(); + List<FieldDescriptor> publicFields = symbolTable.getScriptFields(); + //List<MethodDescriptor> declaredMethods = new ArrayList<MethodDescriptor>(publicMethods); + //List<FieldDescriptor> declaredFields = new ArrayList<FieldDescriptor>(publicFields); + Iterator<MethodDescriptor> methods = publicMethods.iterator(); + while (methods.hasNext()) { + MethodDescriptor method = methods.next(); + if (!Modifier.isPublic(method.getModifiers())) { + methods.remove(); + } + } + Iterator<FieldDescriptor> fields = publicFields.iterator(); + while (fields.hasNext()) { + FieldDescriptor field = fields.next(); + if (!Modifier.isPublic(field.getModifiers())) { + fields.remove(); + } + } + publicMethods.addAll(Arrays.asList(superclass.getMethodDescriptors())); + publicFields.addAll(Arrays.asList(superclass.getFieldDescriptors())); + int dotPos = className.lastIndexOf("."); + String packageName = dotPos != -1 ? className.substring(0, dotPos) : null; + Set<String> interfaces = new HashSet<String>(); + ClassDescriptor[] superclassInterfaces = superclass.getInterfaces(); + for (ClassDescriptor superclassInterface : superclassInterfaces) { + interfaces.add(superclassInterface.getName()); + } + interfaces.add(JAXXObject.class.getName()); + return new ClassDescriptor(className, packageName, symbolTable.getSuperclassName(), + (String[]) interfaces.toArray(new String[interfaces.size()]), false, false, null, null, classLoader, + (MethodDescriptor[]) publicMethods.toArray(new MethodDescriptor[publicMethods.size()]), + (FieldDescriptor[]) publicFields.toArray(new FieldDescriptor[publicFields.size()])) { + public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { + String type = symbolTable.getClassTagIds().get(name); + if (type != null) { + return new FieldDescriptor(name, Modifier.PROTECTED, type, compiler.getClassLoader()); + } + throw new NoSuchFieldException(name); + } + + + public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor[] parameterTypes) throws NoSuchMethodException { + throw new NoSuchMethodException(name); + } + + @Override + public JAXXObjectDescriptor getJAXXObjectDescriptor() { + return compiler.getJAXXObjectDescriptor(); + } + }; + } + + + private static ClassDescriptor createClassDescriptorFromClass(final Class<?> javaClass) { + String name = javaClass.getName(); + Package p = javaClass.getPackage(); + String packageName = p != null ? p.getName() : null; + Class superclass = javaClass.getSuperclass(); + String superclassName = superclass != null ? superclass.getName() : null; + Class[] interfaces = javaClass.getInterfaces(); + String[] interfaceNames = new String[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + interfaceNames[i] = interfaces[i].getName(); + } + boolean isInterface = javaClass.isInterface(); + boolean isArray = javaClass.isArray(); + String componentTypeName = isArray ? javaClass.getComponentType().getName() : null; + JAXXObjectDescriptor jaxxObjectDescriptor = getJAXXObjectDescriptor(javaClass); + ClassLoader classLoader = javaClass.getClassLoader(); + Method[] javaMethods = javaClass.getMethods(); + MethodDescriptor[] methods = new MethodDescriptor[javaMethods.length]; + for (int i = 0; i < methods.length; i++) { + methods[i] = createMethodDescriptor(javaMethods[i], javaClass.getClassLoader()); + } + Field[] javaFields = javaClass.getFields(); + FieldDescriptor[] fields = new FieldDescriptor[javaFields.length]; + for (int i = 0; i < fields.length; i++) { + fields[i] = createFieldDescriptor(javaFields[i], javaClass.getClassLoader()); + } + return new ClassDescriptor(name, packageName, superclassName, interfaceNames, isInterface, isArray, componentTypeName, jaxxObjectDescriptor, classLoader, methods, fields) { + public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { + return createFieldDescriptor(javaClass.getDeclaredField(name), javaClass.getClassLoader()); + } + + public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor[] parameterTypes) throws NoSuchMethodException { + try { + Class[] parameterTypeClasses = new Class[parameterTypes.length]; + for (int i = 0; i < parameterTypes.length; i++) { + parameterTypeClasses[i] = Class.forName(parameterTypes[i].getName()); + } + return createMethodDescriptor(javaClass.getDeclaredMethod(name, parameterTypeClasses), javaClass.getClassLoader()); + } + catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + }; + } + + public static void checkSupportClass(Class<?> handlerClass, ClassDescriptor beanClass, Class<?>... tagClasses) { + for (Class<?> tagClass : tagClasses) { + if (getClassDescriptor(tagClass).isAssignableFrom(beanClass)) { + return; + } + } + throw new IllegalArgumentException(handlerClass.getName() + " does not support the class " + beanClass.getName()); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,49 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.runtime; - -import java.io.Serializable; - -public class ComponentDescriptor implements Serializable { - String id; - String javaClassName; - String styleClass; - ComponentDescriptor parent; - private static final long serialVersionUID = 3001121176691770788L; - - - public ComponentDescriptor(String id, String javaClassName, String styleClass, ComponentDescriptor parent) { - this.id = id; - this.javaClassName = javaClassName; - this.styleClass = styleClass; - this.parent = parent; - } - - - public String getId() { - return id; - } - - - public String getJavaClassName() { - return javaClassName; - } - - - public String getStyleClass() { - return styleClass; - } - - - public ComponentDescriptor getParent() { - return parent; - } - - - @Override - public String toString() { - return "ComponentDescriptor[" + id + ", " + javaClassName + ", " + styleClass + "]"; - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/ComponentDescriptor.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,49 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.runtime; + +import java.io.Serializable; + +public class ComponentDescriptor implements Serializable { + String id; + String javaClassName; + String styleClass; + ComponentDescriptor parent; + private static final long serialVersionUID = 1L; + + + public ComponentDescriptor(String id, String javaClassName, String styleClass, ComponentDescriptor parent) { + this.id = id; + this.javaClassName = javaClassName; + this.styleClass = styleClass; + this.parent = parent; + } + + + public String getId() { + return id; + } + + + public String getJavaClassName() { + return javaClassName; + } + + + public String getStyleClass() { + return styleClass; + } + + + public ComponentDescriptor getParent() { + return parent; + } + + + @Override + public String toString() { + return "ComponentDescriptor[" + id + ", " + javaClassName + ", " + styleClass + "]"; + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Decorator.java (from rev 1047, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Decorator.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Decorator.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Decorator.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,35 @@ +package jaxx.runtime; + +/** + * A simple contract to define a String decorator on any java objet. + * + * @author chemit + */ +public abstract class Decorator<O> implements java.io.Serializable { + + protected final Class<O> internalClass; + private static final long serialVersionUID = -1L; + + /** + * @param internalClass the class of objects to be decorated. + * @throws NullPointerException if internalClass parameter is null + */ + public Decorator(Class<O> internalClass) throws NullPointerException { + if (internalClass == null) { + throw new NullPointerException("internalClass can not be null."); + } + this.internalClass = internalClass; + } + + /** + * @param bean the bean to decorate + * @return the string value of the given bean + */ + public abstract String toString(Object bean); + + + public final Class<O> getInternalClass() { + return internalClass; + } + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/DefaultJAXXContext.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,188 @@ +package jaxx.runtime; + +import static jaxx.runtime.JAXXContextEntryDef.newDef; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Container; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/** + * The default {@link JAXXContext} to be used in a {@link JAXXObject} by delegation. + * <p/> + * The values are store in a {@link Map} but we can not use directly the values as key. + * <p/> + * Because, it does not work if we add for the same object multi entries (named and unamed)... + * <p/> + * We prefer use as entry the {@link JAXXContextEntryDef} associated with the value. + * + * @author chemit + */ +public class DefaultJAXXContext implements JAXXContext { + + protected static final JAXXContextEntryDef<JAXXContext> PARENT_CONTEXT_ENTRY = newDef(JAXXContext.class); + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final Log log = LogFactory.getLog(DefaultJAXXContext.class); + + /** l'ui auquel est rattache le context */ + protected JAXXObject ui; + + /** le context parent */ + protected JAXXContext parentContext; + + /** les données contenues dans le context */ + protected final Map<JAXXContextEntryDef, Object> data; + + public DefaultJAXXContext() { + data = new HashMap<JAXXContextEntryDef, Object>(); + } + + public DefaultJAXXContext(JAXXObject ui) { + this(); + this.ui = ui; + } + + public <T> void setContextValue(T o) { + setContextValue(o, null); + } + + public <T> void setContextValue(T o, String name) { + if (PARENT_CONTEXT_ENTRY.accept2(o.getClass(), null)) { + setParentContext((JAXXContext) o); + return; + } + JAXXContextEntryDef<?> entry = getKey(name, o.getClass()); + // first remove entry + Object oldValue = remove0(o.getClass(), name); + if (oldValue != null) { + if (log.isDebugEnabled()) { + log.debug("remove value " + oldValue.getClass() + " for " + entry); + } + } + // then can put safely + data.put(entry, o); + } + + public <T> T getContextValue(Class<T> clazz) { + return getContextValue(clazz, null); + } + + @SuppressWarnings({"unchecked"}) + public <T> T getContextValue(Class<T> clazz, String name) { + if (PARENT_CONTEXT_ENTRY.accept(clazz, name)) { + return (T) getParentContext(); + } + for (Entry<JAXXContextEntryDef, Object> entry : data.entrySet()) { + if (entry.getKey().accept(clazz, name)) { + return (T) entry.getValue(); + } + } + + // no value found in this context, will try in the parent context + if (JAXXContext.class == clazz) { + // no seek in the parent context, since we are already looking for it + return null; + } + + JAXXContext parentContext = getParentContext(); + if (parentContext == null) { + // no parent context, so no value find + return null; + } + // seek in parent context + return parentContext.getContextValue(clazz, name); + } + + public <T> void removeContextValue(Class<T> klazz) { + removeContextValue(klazz, null); + } + + public <T> void removeContextValue(Class<T> klazz, String name) { + remove0(klazz, name); + } + + public <O extends Container> O getParentContainer(Class<O> clazz) { + return this.getParentContainer(ui, clazz); + } + + @SuppressWarnings({"unchecked"}) + public <O extends Container> O getParentContainer(Object top, Class<O> clazz) { + if (ui == null) { + throw new IllegalStateException("no ui attached to this context"); + } + if (top == null) { + throw new IllegalArgumentException("top parameter can not be null"); + } + if (!Container.class.isAssignableFrom(top.getClass())) { + throw new IllegalArgumentException("top parameter " + top + " is not a " + Container.class); + } + Container parent = ((Container) top).getParent(); + if (parent != null && !clazz.isAssignableFrom(parent.getClass())) { + parent = getParentContainer(parent, clazz); + } + return (O) parent; + } + + protected JAXXObject getUi() { + return ui; + } + + protected void setUi(JAXXObject ui) { + this.ui = ui; + } + + protected JAXXContextEntryDef<?> getKey(String name, Class<?> klass) { + return JAXXContextEntryDef.newDef(name, klass); + } + + @SuppressWarnings({"unchecked"}) + protected <T> T remove0(Class<T> klazz, String name) { + if (PARENT_CONTEXT_ENTRY.accept(klazz, name)) { + JAXXContext old = getParentContext(); + setParentContext(null); + return (T) old; + } + JAXXContextEntryDef entry = null; + for (JAXXContextEntryDef entryDef : data.keySet()) { + if (entryDef.accept(klazz, name)) { + entry = entryDef; + break; + } + } + if (entry != null) { + return (T) data.remove(entry); + } + + if (JAXXContext.class == klazz) { + return null; + } + // try in parentContext + JAXXContext parentContext = getParentContext(); + + if (parentContext == null) { + return null; + } + + if (parentContext instanceof DefaultJAXXContext) { + return ((DefaultJAXXContext) parentContext).remove0(klazz, name); + } + + return null; + } + + protected JAXXContext getParentContext() { + return parentContext; + } + + protected void setParentContext(JAXXContext parentContext) { + if (parentContext instanceof JAXXObject) { + // keep the real context, not the ui + parentContext = ((JAXXObject) parentContext).getDelegateContext(); + } + this.parentContext = parentContext; + } + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXAction.java (from rev 1009, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXAction.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXAction.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXAction.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,19 @@ +package jaxx.runtime; + +/** + * This is the contract to be realized by any class to be used as Action class for an ui. + * + * @author chemit + */ +public interface JAXXAction { + + /** + * Prepare the initial context of the ui. + * + * @param parentContent the context of the parent of the ui (can be null if no parent is required) + * @param datas other datas to inject in initial context + * @return the {@link jaxx.runtime.JAXXInitialContext} to be injected in the ui via the constructor of the {@link jaxx.runtime.JAXXObject} + */ + JAXXInitialContext init(JAXXContext parentContent, Object... datas); + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,65 +0,0 @@ -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); -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContext.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,99 @@ +package jaxx.runtime; + +import java.awt.Container; + +/** + * The {@link jaxx.runtime.JAXXContext} contract defines a generic context. + * <p/> + * A context contains two king of entries : + * <p/> + * <h2>Unamed entry</h2> + * a such entry maps filter only on the clas of the object of the entry. + * <p/> + * To add a <b>unamed</b> entry, use {@link #setContextValue(Object)} and {@link #getContextValue(Class)} to reteave a + * such entry. + * <p/> + * <h2>named entry</h2> + * a such entry filter on class of the object and on the name of the entry. + * <p/> + * To add a <b>named</b> entry, use {@link #setContextValue(Object,String)} and {@link #getContextValue(Class,String)} + * to reteave a such entry. + * + * @author letellier + * @author chemit + */ +public interface JAXXContext { + + /** + * Push in the context a new unamed entry. + * <p/> + * If a previous entry exists in context (unamed and same class), it will be removed. + * + * @param o the value to push in context + */ + public <T> void setContextValue(T o); + + /** + * * Push in the context a new amed entry. + * <p/> + * If a previous entry exists in context (same name and class), it will be removed. + * + * @param o the value to push in context + * @param name the name of the new entry + */ + public <T> void setContextValue(T o, String name); + + /** + * Remove from context the value with the given klazz as an unamed entry + * + * @param klazz the klazz entry + */ + public <T> void removeContextValue(Class<T> klazz); + + /** + * Remove from context the value with the given klazz as an unamed (if name is null) or named entry + * + * @param klazz the klazz entry + * @param name extra name of the entry + */ + + public <T> void removeContextValue(Class<T> klazz, String name); + + /** + * Seek for a unamed entry in the context + * <p/> + * This is an exemple to call a method in JAXX : + * <p/> + * <code><JButton onActionPerformed='{getContextValue(Action.class).method(args[])}'/></code> + * + * @param clazz the class of unamed entry to seek in context + * @return the value of the unamed entry for the given class, or <code>null</code> if no such entry. + */ + public <T> T getContextValue(Class<T> clazz); + + /** + * Seek for a named entry in the context + * + * @param clazz the class of named entry to seek in context + * @param name the name of the entry to seek in context + * @return the value of the named entry for the given class, or <code>null</code> if no such entry. + */ + 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 the top container + * @param clazz desired + * @return parent's container + */ + public <O extends Container> O getParentContainer(Object top, Class<O> clazz); +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContextEntryDef.java (from rev 1047, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXContextEntryDef.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContextEntryDef.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXContextEntryDef.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,118 @@ +package jaxx.runtime; + +import java.util.Collections; +import java.util.List; + +/** + * To qualify an entry in a {@link JAXXContext}. + * <p/> + * Use the factory methods <code>newDef</code> and <code>newListDef</code< to obtain new instances. + * + * @author chemit + */ +public class JAXXContextEntryDef<O> implements java.io.Serializable { + + /** name of the entry, can be nuill for a unamed entry. */ + protected String name; + + /** class of the entry, can not be null */ + protected Class<O> klass; + + private static final long serialVersionUID = 1L; + + public static <O> JAXXContextEntryDef<O> newDef(Class<O> klass) { + return newDef(null, klass); + } + + public static <O> JAXXContextEntryDef<O> newDef(String name, Class<O> klass) { + return new JAXXContextEntryDef<O>(name, klass); + } + + public static <O> JAXXContextEntryDef<List<O>> newListDef() { + return newListDef(null); + } + + @SuppressWarnings({"unchecked"}) + public static <O> JAXXContextEntryDef<List<O>> newListDef(String name) { + JAXXContextEntryDef contextEntryDef = new JAXXContextEntryDef<List<O>>(name, JAXXContextEntryDef.<O>castList()); + contextEntryDef.klass = List.class; + return contextEntryDef; + } + + + public String getName() { + return name; + } + + public Class<O> getKlass() { + return klass; + } + + public O getContextValue(JAXXContext context) { + return context.getContextValue(klass, name); + } + + public void removeContextValue(JAXXContext context) { + context.removeContextValue(klass, name); + } + + public void setContextValue(JAXXContext context, O value) { + context.setContextValue(value, name); + } + + @Override + public String toString() { + return super.toString() + "<" + klass + ":" + name + ">"; + } + + protected JAXXContextEntryDef(Class<O> klass) { + this(null, klass); + } + + protected JAXXContextEntryDef(String name, Class<O> klass) { + if (klass == null) { + throw new IllegalArgumentException("class can not be null"); + } + this.name = name; + this.klass = klass; + } + + @SuppressWarnings({"unchecked"}) + protected static <O> Class<List<O>> castList() { + return (Class<List<O>>) Collections.emptyList().getClass(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof JAXXContextEntryDef)) { + return false; + } + JAXXContextEntryDef that = (JAXXContextEntryDef) o; + return klass.equals(that.klass) && !(name != null ? !name.equals(that.name) : that.name != null); + + } + + @Override + public int hashCode() { + int result = (name != null ? name.hashCode() : 0); + return 31 * result + klass.hashCode(); + } + + public boolean accept(Class<?> klass, String name) { + if (klass == Object.class && this.klass != Object.class) { + // try on name only + return (this.name != null && name != null && this.name.equals(name)); + } + return klass.isAssignableFrom(this.klass) && (this.name == null && name == null + || (this.name != null && name != null && this.name.equals(name))); + } + + public boolean accept2(Class<?> klass, String name) { + return !(klass == Object.class && this.klass != Object.class) && + this.klass.isAssignableFrom(klass) && (this.name == null && + name == null || (this.name != null && name != null && this.name.equals(name))); + } +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,133 +0,0 @@ -package jaxx.runtime; - -import java.awt.Container; -import java.util.LinkedHashSet; -import java.util.Map.Entry; -import java.util.Set; - -/** - * An initial context to be inject in a {@link JAXXObject}. - * <p/> - * The method {@link #add(Object)} register a simple value. - * <p/> - * The method {@link #add(String, Object)} register a named value. - * <p/> - * The method {@link #to(JAXXObject)} inject in the {@link JAXXObject} the values registred in the initial context. - * <p/> - * The initial context is also a "limited" {@link JAXXContext}, since we can only use the two methods - * <p/> - * {@link #getContextValue(Class)} or {@link #getContextValue(Class, String)}. - * - * @see JAXXContext - */ -public class JAXXInitialContext implements JAXXContext { - - public static class JAXXInitialContextEntry implements Entry<String, Object> { - - protected String key; - protected Object value; - - public JAXXInitialContextEntry(String key, Object value) { - this.key = key; - this.value = value; - } - - public String getKey() { - return key; - } - - public Object getValue() { - return value; - } - - public Object setValue(Object value) { - Object oldValue = this.value; - this.value = value; - return oldValue; - } - - } - - protected Set<Entry<String, Object>> entries; - - public JAXXInitialContext() { - entries = new LinkedHashSet<Entry<String, Object>>(); - } - - /** - * Register a simple (none named) value in the context. - * - * @param value the value to be registred in the context - * @return the instance of the context - */ - public JAXXInitialContext add(Object value) { - return add(null, value); - } - - /** - * Register a named value in the context. - * - * @param name the name of the value - * @param value the value to registred - * @return the instance of the context - */ - public JAXXInitialContext add(String name, Object value) { - entries.add(new JAXXInitialContextEntry(name, value)); - return this; - } - - /** - * Inject all the registed values into the {@link JAXXObject} - * - * @param dst the object to fill. - */ - public void to(JAXXObject dst) { - for (Entry<String, Object> entry : entries) { - if (entry.getKey() == null) { - dst.setContextValue(entry.getValue()); - } else { - dst.setContextValue(entry.getValue(), entry.getKey()); - } - } - } - - @SuppressWarnings({"unchecked"}) - public <T> T getContextValue(Class<T> clazz) { - T result = null; - for (Entry<String, Object> entry : entries) { - if (clazz.isAssignableFrom(entry.getValue().getClass())) { - result = (T) entry.getValue(); - break; - } - } - return result; - } - - @SuppressWarnings({"unchecked"}) - public <T> T getContextValue(Class<T> clazz, String name) { - T result = null; - for (Entry<String, Object> entry : entries) { - if (name.equals(entry.getKey()) && clazz.isAssignableFrom(entry.getValue().getClass())) { - result = (T) entry.getValue(); - } - } - return result; - } - - public void setContextValue(Object o) { - throw new RuntimeException("not implemented"); - } - - public void setContextValue(Object o, String name) { - throw new RuntimeException("not implemented"); - } - - public <O extends Container> O getParentContainer(Class<O> clazz) { - throw new RuntimeException("not implemented"); - } - - public <O extends Container> O getParentContainer(Object top, Class<O> clazz) { - throw new RuntimeException("not implemented"); - } - -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXInitialContext.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,93 @@ +package jaxx.runtime; + +import java.awt.Container; +import java.util.Map.Entry; + +/** + * An initial context to be inject in a {@link JAXXObject}. + * <p/> + * The method {@link #add(Object)} register a simple value. + * <p/> + * The method {@link #add(String, Object)} register a named value. + * <p/> + * The method {@link #to(JAXXContext)} inject in the {@link JAXXObject} the values registred in the initial context. + * <p/> + * The initial context is also a "limited" {@link JAXXContext}, since we can only use the two methods + * <p/> + * {@link #getContextValue(Class)} or {@link #getContextValue(Class, String)}. + * + * @see JAXXContext + */ +public class JAXXInitialContext extends DefaultJAXXContext { + + public JAXXInitialContext() { + super(); + } + + /** + * Register a simple (none named) value in the context. + * + * @param value the value to be registred in the context + * @return the instance of the context + */ + public JAXXInitialContext add(Object value) { + return add(null, value); + } + + /** + * Register a named value in the context. + * + * @param name the name of the value + * @param value the value to registred + * @return the instance of the context + */ + public JAXXInitialContext add(String name, Object value) { + super.setContextValue(value, name); + return this; + } + + /** + * Inject all the registed values into the {@link JAXXObject} + * + * @param dst the object to fill. + */ + public void to(JAXXContext dst) { + if (parentContext != null) { + dst.setContextValue(parentContext); + } + for (Entry<JAXXContextEntryDef, Object> entry : data.entrySet()) { + dst.setContextValue(entry.getValue(), entry.getKey().getName()); + } + } + + @Override + public void setContextValue(Object o) { + throw new RuntimeException("not implemented"); + } + + @Override + public void setContextValue(Object o, String name) { + throw new RuntimeException("not implemented"); + } + + @Override + public <T> void removeContextValue(Class<T> klazz) { + throw new RuntimeException("not implemented"); + } + + @Override + public <T> void removeContextValue(Class<T> klazz, String name) { + throw new RuntimeException("not implemented"); + } + + @Override + public <O extends Container> O getParentContainer(Class<O> clazz) { + throw new RuntimeException("not implemented"); + } + + @Override + public <O extends Container> O getParentContainer(Object top, Class<O> clazz) { + throw new RuntimeException("not implemented"); + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,51 +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, 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.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObject.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,52 @@ +/* + * 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); + + public jaxx.runtime.JAXXContext getDelegateContext(); + + /** + * 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 Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,32 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.runtime; - -import jaxx.css.Stylesheet; - -import java.io.Serializable; - -public class JAXXObjectDescriptor implements Serializable { - private ComponentDescriptor[] descriptors; - private Stylesheet stylesheet; - private static final long serialVersionUID = -1706159556633801154L; - - - public JAXXObjectDescriptor(ComponentDescriptor[] descriptors, - Stylesheet stylesheet) { - this.descriptors = descriptors; - this.stylesheet = stylesheet; - } - - - public ComponentDescriptor[] getComponentDescriptors() { - return descriptors; - } - - - public Stylesheet getStylesheet() { - return stylesheet; - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,42 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.runtime; + +import jaxx.css.Stylesheet; + +import java.io.Serializable; + +public class JAXXObjectDescriptor implements Serializable { + private ComponentDescriptor[] descriptors; + private Stylesheet stylesheet; + private static final long serialVersionUID = 1L; + + + public JAXXObjectDescriptor(ComponentDescriptor[] descriptors, + Stylesheet stylesheet) { + this.descriptors = descriptors; + this.stylesheet = stylesheet; + } + + + public ComponentDescriptor[] getComponentDescriptors() { + return descriptors; + } + + + public Stylesheet getStylesheet() { + return stylesheet; + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + for (ComponentDescriptor descriptor : descriptors) { + buffer.append("\n").append(descriptor); + } + buffer.append("\n").append(stylesheet); + return buffer.toString(); + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/JXPathDecorator.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,282 @@ +package jaxx.runtime; + +import org.apache.commons.beanutils.MethodUtils; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.jxpath.JXPathContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyDescriptor; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * JXPath decorator based on {@link String#format(String, Object[])} method. + * <p/> + * To use it, give to him a expression where all jxpath to apply on bean are boxed in <code>${}</code>. + * <p/> + * After the jxpath token you must specifiy the formatter to apply of the jxpath token. + * <p/> + * For example : + * <pre> + * Decorator<Object> d = JXPathDecorator.newDecorator(JXPathDecorator.class,"expr = ${expressions}$s"); + * assert "expr = %1$s" == d.getExpression(); + * assert 1 == d.getNbToken(); + * assert java.util.Arrays.asList("expression") == d.getTokens(); + * assert "expr = %1$s" == d.toString(d); + * </pre> + * + * @author chemit + * @see Decorator + */ +public class JXPathDecorator<O> extends Decorator<O> { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log = LogFactory.getLog(JXPathDecorator.class); + + private static final long serialVersionUID = 1L; + + /** + * Factory method to instanciate a new {@link JXPathDecorator} for the given class {@link O} and expression. + * + * @param internalClass the class of the objects decorated by the new decorator + * @param expression the expression to use to decorated objects + * @param <O> the generic type of class to be decorated by the new decorator + * @return the new instanciated decorator + * @throws IllegalArgumentException if the expression is not valid, says: + * <p/> + * - a missing right brace was detected. + * <p/> + * - a ${ was found in a jxpath token. + * @throws NullPointerException if internalClass parameter is null. + */ + public static <O> JXPathDecorator<O> newDecorator(Class<O> internalClass, String expression) + throws IllegalArgumentException, NullPointerException { + return new JXPathDecorator<O>(internalClass, expression, true); + } + + /** + * Sort a list of data based on the first token property of a given context + * in a given decorator. + * + * @param decorator the decorator to use to sort + * @param datas the list of data to sort + * @param pos the index of context to used in decorator to obtain sorted property. + */ + public static void sort(JXPathDecorator decorator, List<?> datas, int pos) { + Collections.sort(datas, decorator.getComparator(pos)); + } + + protected static class Context implements Serializable { + /** + * expression to format using {@link String#format(String, Object[])}, all variables are compute + * using using the jxpath tokens. + */ + protected String expression; + + /** list of jxpath tokens to apply on expression */ + protected String[] tokens; + + protected transient Comparator comparator; + + private static final long serialVersionUID = 1L; + + public Context(String expression, String[] tokens) { + this.expression = expression; + this.tokens = tokens; + } + + public String getFirstProperty() { + return tokens[0]; + } + + public Comparator getComparator(JXPathDecorator decorator, int pos) { + if (comparator == null) { + + final String property = tokens[pos]; + + Class<?> type = getType(decorator, pos); + + // does not work with javassist, a shame... + //Comparator<?> comparator = new BeanComparator(property); + + if (Number.class.isAssignableFrom(type) || Comparable.class.isAssignableFrom(type)) { + comparator = new Comparator() { + public int compare(Object o1, Object o2) { + Comparable c1 = getValue(o1); + Comparable c2 = getValue(o2); + return c1.compareTo(c2); + } + + public Comparable<Comparable> getValue(Object o) { + try { + Object r = PropertyUtils.getProperty(o, property); + return (Comparable) r; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + if (comparator == null) { + throw new IllegalStateException("could not find comparator for type " + type); + } + //todo fixme add a default comparator basedon toString() comparator ? + return comparator; + } + return comparator; + } + + protected Class<?> getType(JXPathDecorator decorator, int pos) { + ensureTokenIndex(decorator, pos); + + String property = getFirstProperty(); + + if (property == null) { + throw new NullPointerException("could not find property in " + this); + } + + for (PropertyDescriptor descriptor : decorator.getDescriptors()) { + if (property.equals(descriptor.getName())) { + Class<?> type = descriptor.getReadMethod().getReturnType(); + if (type.isPrimitive()) { + type = MethodUtils.getPrimitiveWrapper(type); + } + return type; + } + } + throw new IllegalStateException("could not find read method for property " + property); + } + + @Override + public String toString() { + return "<expression:" + expression + ", tokens:" + Arrays.toString(tokens) + ">"; + } + } + + /** the computed context of the decorator */ + protected Context context; + + /** nb jxpath tokens to compute */ + protected int nbToken; + + /** the initial expression used to compute the decorator context. */ + protected String initialExpression; + + /** cache of descriptors of the internal class (used for sorting) */ + protected transient PropertyDescriptor[] descriptors; + + public String toString(Object bean) { + if (bean == null) { + return null; + } + JXPathContext jxcontext = JXPathContext.newContext(bean); + Object[] args = new Object[nbToken]; + for (int i = 0; i < nbToken; i++) { + args[i] = jxcontext.getValue(context.tokens[i]); + } + return String.format(context.expression, args); + } + + public String getProperty(int pos) { + return getTokens()[pos]; + } + + public String getExpression() { + return context.expression; + } + + public String[] getTokens() { + return context.tokens; + } + + public int getNbToken() { + return nbToken; + } + + public String getInitialExpression() { + return initialExpression; + } + + @Override + public String toString() { + return super.toString() + "<" + context + ">"; + } + + public PropertyDescriptor[] getDescriptors() { + if (descriptors == null) { + descriptors = PropertyUtils.getPropertyDescriptors(internalClass); + } + return descriptors; + } + + public void setContext(Context context) { + this.context = context; + this.nbToken = context.tokens.length; + // always reset comparator + //this.context.comparator = null; + if (log.isDebugEnabled()) { + log.debug(context); + } + } + + protected JXPathDecorator(Class<O> internalClass, String expression, boolean creatContext) throws IllegalArgumentException, NullPointerException { + super(internalClass); + this.initialExpression = expression; + if (creatContext) { + setContext(createInitialContext(expression)); + if (log.isDebugEnabled()) { + log.debug(expression + " --> " + this.context); + } + } + } + + @SuppressWarnings({"unchecked"}) + protected Comparator<O> getComparator(int pos) { + ensureTokenIndex(this, pos); + return context.getComparator(this, pos); + } + + protected static Context createInitialContext(String expression) { + List<String> lTokens = new ArrayList<String>(); + StringBuilder buffer = new StringBuilder(); + int size = expression.length(); + int end = -1; + int start; + while ((start = expression.indexOf("${", end + 1)) > -1) { + if (start > end + 1) { + // prefix of next jxpath token + buffer.append(expression.substring(end + 1, start)); + } + // seek end of jxpath + end = expression.indexOf("}", start + 1); + if (end == -1) { + throw new IllegalArgumentException("could not find the rigth brace starting at car " + start + " : " + expression.substring(start + 2)); + } + String jxpath = expression.substring(start + 2, end); + // not allowed ${ inside a jxpath token + if (jxpath.indexOf("${") > -1) { + throw new IllegalArgumentException("could not find a ${ inside a jxpath expression at car " + (start + 2) + " : " + jxpath); + } + // save the jxpath token + lTokens.add(jxpath); + // replace jxpath token in expresion with a string format variable + buffer.append("%").append(lTokens.size()); + } + if (size > (end + 1)) { + // suffix after end jxpath (or all expression if no jxpath) + buffer.append(expression.substring(end + 1)); + } + return new Context(buffer.toString(), lTokens.toArray(new String[lTokens.size()])); + } + + protected static void ensureTokenIndex(JXPathDecorator decorator, int pos) { + if (pos < -1 || pos > decorator.getNbToken()) { + throw new ArrayIndexOutOfBoundsException("token index " + pos + " is out of bound, can be inside [" + 0 + "," + decorator.nbToken + "]"); + } + } +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/MultiJXPathDecorator.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,119 @@ +package jaxx.runtime; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.StringTokenizer; + +/** + * TODO + * + * @author chemit + * @see jaxx.runtime.Decorator + */ +public class MultiJXPathDecorator<O> extends JXPathDecorator<O> { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log = LogFactory.getLog(MultiJXPathDecorator.class); + + private static final long serialVersionUID = 1L; + + public static <O> MultiJXPathDecorator<O> newDecorator(Class<O> internalClass, + String expression, + String separator) + throws IllegalArgumentException, NullPointerException { + + return newDecorator(internalClass, expression, separator, separator); + } + + public static <O> MultiJXPathDecorator<O> newDecorator(Class<O> internalClass, + String expression, + String separator, + String separatorReplacement) + throws IllegalArgumentException, NullPointerException { + + Context[] contexts = createInitialContexts(expression, separator, separatorReplacement); + + return new MultiJXPathDecorator<O>(internalClass, expression, separator, separatorReplacement, contexts); + } + + protected Context[] contexts; + protected String separator; + protected String separatorReplacement; + + + protected MultiJXPathDecorator(Class<O> internalClass, String expression, + String separator, String separatorReplacement, + Context[] contexts) throws IllegalArgumentException, NullPointerException { + super(internalClass, expression, false); + this.separator = separator; + this.separatorReplacement = separatorReplacement; + this.contexts = contexts; + + setContextIndex(0); + + if (log.isDebugEnabled()) { + log.debug(expression + " --> " + this.context); + } + } + + public void setContextIndex(int index) { + ensureContextIndex(this, index); + setContext(contexts[index]); + } + + public int getNbContext() { + return contexts.length; + } + + public String getSeparator() { + return separator; + } + + public String getSeparatorReplacement() { + return separatorReplacement; + } + + @Override + protected Comparator<O> getComparator(int pos) { + ensureContextIndex(this, pos); + return contexts[pos].getComparator(this, 0); + } + + protected static Context[] createInitialContexts(String expression, String separator, String separatorReplacement) { + int sep = expression.indexOf(separator); + if (sep == -1) { + return new Context[]{createInitialContext(expression)}; + } + + List<String> tokens = new ArrayList<String>(); + StringTokenizer stk = new StringTokenizer(expression, separator); + while (stk.hasMoreTokens()) { + tokens.add(stk.nextToken()); + } + + int nbTokens = tokens.size(); + Context[] contexts = new Context[nbTokens]; + for (int i = 0; i < nbTokens; i++) { + StringBuilder buffer = new StringBuilder(expression.length()); + for (int j = 0; j < nbTokens; j++) { + int index = (i + j) % nbTokens; + String str = tokens.get(index); + //todo replace %index with %j + buffer.append(separatorReplacement).append(str); + } + contexts[i] = createInitialContext(buffer.substring(separatorReplacement.length())); + } + return contexts; + } + + protected static void ensureContextIndex(MultiJXPathDecorator decorator, int pos) { + if (pos < -1 || pos > decorator.contexts.length) { + throw new ArrayIndexOutOfBoundsException("context index " + pos + " is out of bound, can be inside [" + 0 + "," + decorator.contexts.length + "]"); + } + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Util.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,396 +0,0 @@ -package jaxx.runtime; - -import jaxx.runtime.validator.BeanValidator; -import jaxx.runtime.validator.ErrorListMouseListener; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jdesktop.jxlayer.JXLayer; - -import javax.swing.JComponent; -import javax.swing.JList; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.event.MouseListener; -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; - } - - /** - * Convert a value to a given type and then if was succesffull try to set it in the bean manage by the validator. - * - * @param validator validator to be involved - * @param fieldName the name of the bean property - * @param value the actual value to convert - * @param valueClass the type of the conversion - */ - public static void convert(BeanValidator<?> validator, String fieldName, String value, Class<?> valueClass) { - - Object result = validator.convert(fieldName, value, valueClass); - if (result != null) { - try { - BeanInfo info = Introspector.getBeanInfo(validator.getBean().getClass()); - - for (PropertyDescriptor descriptor : info.getPropertyDescriptors()) { - if (fieldName.equals(descriptor.getName()) && descriptor.getWriteMethod() != null) { - - descriptor.getWriteMethod().invoke(validator.getBean(), result); - break; - } - } - } catch (IntrospectionException e) { - log.error("could not obtain beanInfo for " + valueClass.getClass() + ", reason : " + e.getMessage(), e); - } catch (InvocationTargetException e) { - log.error("could not obtain beanInfo for " + valueClass.getClass() + ", reason : " + e.getMessage(), e); - } catch (IllegalAccessException e) { - log.error("could not obtain beanInfo for " + valueClass.getClass() + ", reason : " + e.getMessage(), e); - } - } - } - - /** - * 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; - } - - public static void registerErrorListMouseListener(JList list) { - if (list == null) { - return; - } - for (MouseListener listener : list.getMouseListeners()) { - if (listener instanceof ErrorListMouseListener) { - // already have a such listener - log.info("already registered a such MouseListener : " + listener); - return; - } - } - list.addMouseListener(new ErrorListMouseListener()); - } -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Util.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/Util.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Util.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/Util.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,528 @@ +package jaxx.runtime; + +import jaxx.Base64Coder; +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.ErrorListMouseListener; +import jaxx.runtime.validator.ErrorTableMouseListener; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JTable; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.event.MouseListener; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.IOException; +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; + +public class Util { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final 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 { + return (JAXXObjectDescriptor) Base64Coder.deserialize(descriptor, false); + /*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 { + return (JAXXObjectDescriptor) Base64Coder.deserialize(descriptor, true); + + /*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; + } + + /** + * Convert a value to a given type and then if was succesffull try to set it in the bean manage by the validator. + * + * @param validator validator to be involved + * @param fieldName the name of the bean property + * @param value the actual value to convert + * @param valueClass the type of the conversion + */ + public static void convert(BeanValidator<?> validator, String fieldName, String value, Class<?> valueClass) { + + Object result = validator.convert(fieldName, value, valueClass); + if (result != null) { + try { + BeanInfo info = Introspector.getBeanInfo(validator.getBean().getClass()); + + for (PropertyDescriptor descriptor : info.getPropertyDescriptors()) { + if (fieldName.equals(descriptor.getName()) && descriptor.getWriteMethod() != null) { + + descriptor.getWriteMethod().invoke(validator.getBean(), result); + break; + } + } + } catch (IntrospectionException e) { + log.error("could not obtain beanInfo for " + valueClass.getClass() + ", reason : " + e.getMessage(), e); + } catch (InvocationTargetException e) { + log.error("could not obtain beanInfo for " + valueClass.getClass() + ", reason : " + e.getMessage(), e); + } catch (IllegalAccessException e) { + log.error("could not obtain beanInfo for " + valueClass.getClass() + ", reason : " + e.getMessage(), e); + } + } else { + //fixme : conversion failed, we should be able to notify ui that values has changed ? + // otherwise, bean value has not changed,... + } + } + + /** + * 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; + } + + public static void registerErrorListMouseListener(JList list) { + if (list == null) { + return; + } + for (MouseListener listener : list.getMouseListeners()) { + if (listener instanceof ErrorListMouseListener) { + // already have a such listener + log.info("already registered a such MouseListener : " + listener); + return; + } + } + list.addMouseListener(new ErrorListMouseListener()); + } + + public static void registerErrorTableMouseListener(JTable table) { + if (table == null) { + return; + } + for (MouseListener listener : table.getMouseListeners()) { + if (listener instanceof ErrorTableMouseListener) { + // already have a such listener + log.info("already registered a such MouseListener : " + listener); + return; + } + } + table.addMouseListener(new ErrorTableMouseListener()); + } + + /** + * Compute the string representation of an object. + * <p/> + * Return empty string if given object is null + * + * @param value the value to write + * @return the string representation of the given object or an empty string if object is null. + */ + public static String getStringValue(Object value) { + String result; + result = value == null ? "" : value.toString(); + return result; + } + + /** + * Test if a type of entry exists in a given context and throw an IllegalArgumentException if not found. + * <p/> + * If entry is found, return his value in context. + * + * @param context the context to test + * @param def the definition of the entry to seek in context + * @return the value from the context + * @throws IllegalArgumentException if the entry is not found in context. + */ + public static <T> T checkJAXXContextEntry(JAXXContext context, JAXXContextEntryDef<T> def) throws IllegalArgumentException { + + T value = def.getContextValue(context); + + if (value == null) { + throw new IllegalArgumentException("the context entry [" + def + "] ] was not found in context " + context); + } + + return value; + } + + /** + * Convinient method to process more than one binding on a JAXX ui. + * + * @param src the ui to treate + * @param bindings the list of binding to process. + */ + public static void processDataBinding(JAXXObject src, String... bindings) { + for (String binding : bindings) { + src.processDataBinding(binding); + } + } + + /** + * Convinient method to attach a bean to all validators of an JAXXObject. + * <p/> + * It is possible to exclude some validator to be treated. + * + * @param ui the ui containing the validatros to treate + * @param bean the bean to attach in validators (can be null) + * @param excludeIds the list of validator id to exclude + */ + @SuppressWarnings({"unchecked"}) + public static void setValidatorBean(JAXXObject ui, Object bean, String... excludeIds) { + List<String> validatorIds = ui.getValidatorIds(); + if (excludeIds.length > 0) { + validatorIds = new ArrayList<String>(validatorIds); + for (String excludeId : excludeIds) { + validatorIds.remove(excludeId); + } + } + for (String validatorId : validatorIds) { + BeanValidator beanValidator = ui.getValidator(validatorId); + beanValidator.setBean(bean); + } + } + + /** + * Convinient method to set the changed property to all validators of an JAXXObject. + * <p/> + * It is possible to exclude some validator to be treated. + * + * @param ui the ui containing the validatros to treate + * @param newValue the new value to set in changed validator property + * @param excludeIds the list of validator id to exclude + */ + @SuppressWarnings({"unchecked"}) + public static void setValidatorChanged(JAXXObject ui, boolean newValue, String... excludeIds) { + List<String> validatorIds = ui.getValidatorIds(); + if (excludeIds.length > 0) { + validatorIds = new ArrayList<String>(validatorIds); + for (String excludeId : excludeIds) { + validatorIds.remove(excludeId); + } + } + for (String validatorId : validatorIds) { + BeanValidator beanValidator = ui.getValidator(validatorId); + beanValidator.setChanged(newValue); + } + } + + public static <O> DefaultListCellRenderer newDecoratedListCellRenderer(final Decorator<O> decorator) { + return new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String decorated; + if (value instanceof String) { + decorated = (String) value; + } else { + decorated = decorator.toString(value); + } + return super.getListCellRendererComponent(list, decorated, index, isSelected, cellHasFocus); + } + }; + } + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/CardLayout2.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/CardLayout2.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/CardLayout2.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/CardLayout2.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,87 @@ +package jaxx.runtime.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.Container; +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +/** + * An override of the awt {@link java.awt.CardLayout}. + * <p/> + * Because in the original layout is not overridable : everything is package level accessible. + * <p/> + * This new class offers to test if a constrains (as a Serializable) is actually dealed by the layout, + * via the method {@link #contains(java.io.Serializable)}. + * <p/> + * We had also another method to obtain the current visible component in a container layouted by the class, + * via the method {@link #getVisibleComponent(java.awt.Container)}. + * + * @author chemit + * @version 1.0 + */ +public class CardLayout2 extends CardLayout { + + /** log */ + static private Log log = LogFactory.getLog(CardLayout2.class); + + private static final long serialVersionUID = 1L; + + /** list of already loaded context (since the {@link #vector} attribute is package visible... */ + protected List<Serializable> contexts = new LinkedList<Serializable>(); + + @Override + public void addLayoutComponent(Component comp, Object constraints) { + super.addLayoutComponent(comp, constraints); + contexts.add((Serializable) constraints); + if (log.isDebugEnabled()) { + log.debug(this + " new constraints : " + constraints); + } + } + + /** + * Test if a constrains is contained in the layout. + * + * @param constraints l'identifiant a tester + * @return <code>true</code> si l'identifiant est deja present dans le layout, <code>false</code> autrement. + */ + public boolean contains(Serializable constraints) { + return contexts.contains(constraints); + } + + /** + * Obtain the visible component in the container. + * + * @param container the container using this layout + * @return the component visible in the container. + */ + public Component getVisibleComponent(Container container) { + if (container.getLayout() != this) { + throw new IllegalArgumentException("the container is not managed by the current layout"); + } + for (Component component : container.getComponents()) { + if (component.isVisible()) { + return component; + } + } + // no component actually visible + return null; + } + + public Component getComponent(Container container, String constraints) { + if (container.getLayout() != this) { + throw new IllegalArgumentException("the container is not manage by the current layout"); + } + if (!contexts.contains(constraints)) { + throw new IllegalArgumentException("the constraints '" + constraints + "' is not supported by this layout : " + contexts); + } + int index = contexts.indexOf(constraints); + return container.getComponents()[index]; + } + + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/I18nTableCellHeaderRenderer.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,38 @@ +package jaxx.runtime.swing; + +import static org.codelutin.i18n.I18n._; + +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * A simple TableCellRenderer using a delegate TableCellRenderer to render everything elese thant the text : + * the text is I18nalize. + * + * @author chemit + */ +public class I18nTableCellHeaderRenderer implements TableCellRenderer { + + /** the libelles to display */ + protected final String[] keys; + + /** the delegate cell renderer */ + protected TableCellRenderer delegate; + + public I18nTableCellHeaderRenderer(TableCellRenderer delegate, String... keys) { + this.delegate = delegate; + this.keys = keys; + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { + if (column > keys.length) { + throw new IndexOutOfBoundsException("colum can not be greater than " + keys.length); + } + JLabel rendererComponent = (JLabel) delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); + + rendererComponent.setText(_(keys[column])); + return rendererComponent; + } +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,103 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.runtime.swing; - -import javax.swing.AbstractButton; -import javax.swing.ButtonGroup; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.Enumeration; - -public class JAXXButtonGroup extends ButtonGroup { - public static final String SELECTED_VALUE_PROPERTY = "selectedValue"; - - private PropertyChangeSupport propertyChangeSupport; - private Object selectedValue; - private ChangeListener changeListener = new ChangeListener() { - public void stateChanged(ChangeEvent e) { - updateSelectedValue(); - } - }; - private static final long serialVersionUID = -2096340516687228691L; - - - @Override - public void add(AbstractButton button) { - super.add(button); - button.addChangeListener(changeListener); - updateSelectedValue(); - } - - @Override - public void remove(AbstractButton button) { - super.remove(button); - button.removeChangeListener(changeListener); - updateSelectedValue(); - } - - - public void updateSelectedValue() { - Enumeration<AbstractButton> e = getElements(); - while (e.hasMoreElements()) { - AbstractButton button = e.nextElement(); - if (button.isSelected()) { - Object selectedValue = button.getClientProperty("$value"); - if (selectedValue != getSelectedValue()) { - setSelectedValue(selectedValue); - } - } - } - } - - - public Object getSelectedValue() { - return selectedValue; - } - - - public void setSelectedValue(Object value) { - Object oldValue = getSelectedValue(); - this.selectedValue = value; - firePropertyChange(oldValue); - } - - - protected PropertyChangeSupport getPropertyChangeSupport() { - if (propertyChangeSupport == null) { - propertyChangeSupport = new PropertyChangeSupport(this); - } - return propertyChangeSupport; - } - - - public void addPropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(listener); - } - - - public void addPropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().addPropertyChangeListener(property, listener); - } - - - public void removePropertyChangeListener(PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(listener); - } - - - public void removePropertyChangeListener(String property, PropertyChangeListener listener) { - getPropertyChangeSupport().removePropertyChangeListener(property, listener); - } - - - private void firePropertyChange(Object oldValue) { - if (propertyChangeSupport != null) { - getPropertyChangeSupport().firePropertyChange(SELECTED_VALUE_PROPERTY, - oldValue, getSelectedValue()); - } - } -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,215 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.runtime.swing; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Enumeration; + +public class JAXXButtonGroup extends ButtonGroup { + public static final String SELECTED_VALUE_PROPERTY = "selectedValue"; + + public static final String BUTTON8GROUP_CLIENT_PROPERTY = "$buttonGroup"; + + public static final String VALUE_CLIENT_PROPERTY = "$value"; + + public static final String SELECTED_TIP_CLIENT_PROPERTY = "$selected.toolTipText"; + + public static final String NOT_SELECTED_TIP_CLIENT_PROPERTY = "$not.selected.toolTipText"; + + protected EventListenerList listenerList = new EventListenerList(); + + private PropertyChangeSupport propertyChangeSupport; + private transient Object selectedValue; + + protected boolean useToolTipText; + + protected transient ChangeEvent changeEvent = new ChangeEvent(this); + + private transient ChangeListener changeListener = new ChangeListener() { + public void stateChanged(ChangeEvent e) { + updateSelectedValue(); + if (useToolTipText) { + updateToolTipText(); + } + } + }; + + private static final long serialVersionUID = 1L; + + @Override + public void add(AbstractButton button) { + super.add(button); + button.addChangeListener(changeListener); + updateSelectedValue(); + } + + @Override + public void remove(AbstractButton button) { + super.remove(button); + button.removeChangeListener(changeListener); + updateSelectedValue(); + } + + + public void updateSelectedValue() { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + if (button.isSelected()) { + Object selectedValue = button.getClientProperty(VALUE_CLIENT_PROPERTY ); + if (selectedValue != getSelectedValue()) { + setSelectedValue(selectedValue); + } + } + } + } + + public void updateToolTipText() { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + String key = button.isSelected() ? SELECTED_TIP_CLIENT_PROPERTY : NOT_SELECTED_TIP_CLIENT_PROPERTY; + button.setToolTipText((String) button.getClientProperty(key)); + } + } + + public boolean isUseToolTipText() { + return useToolTipText; + } + + public Object getSelectedValue() { + return selectedValue; + } + + + public void setSelectedValue(Object value) { + Object oldValue = getSelectedValue(); + this.selectedValue = value; + firePropertyChange(oldValue); + } + + public void setUseToolTipText(boolean useToolTipText) { + this.useToolTipText = useToolTipText; + } + + public void setSelectedButton(Object value) { + setSelectedValue(value); + if (value == null) { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + setSelected(button.getModel(), false); + } + return; + } + + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + Object selectedValue = button.getClientProperty(VALUE_CLIENT_PROPERTY ); + if (value.equals(selectedValue)) { + button.setSelected(true); + break; + } + } + } + + protected PropertyChangeSupport getPropertyChangeSupport() { + if (propertyChangeSupport == null) { + propertyChangeSupport = new PropertyChangeSupport(this); + } + return propertyChangeSupport; + } + + + public void addPropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(listener); + } + + + public void addPropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().addPropertyChangeListener(property, listener); + } + + + public void removePropertyChangeListener(PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(listener); + } + + + public void removePropertyChangeListener(String property, PropertyChangeListener listener) { + getPropertyChangeSupport().removePropertyChangeListener(property, listener); + } + + + private void firePropertyChange(Object oldValue) { + if (propertyChangeSupport != null) { + getPropertyChangeSupport().firePropertyChange(SELECTED_VALUE_PROPERTY, + oldValue, getSelectedValue()); + } + fireStateChanged(); + } + + /** + * Adds a <code>ChangeListener</code> to the button. + * + * @param l the listener to be added + */ + public void addChangeListener(ChangeListener l) { + listenerList.add(ChangeListener.class, l); + } + + /** + * Removes a ChangeListener from the button. + * + * @param l the listener to be removed + */ + public void removeChangeListener(ChangeListener l) { + listenerList.remove(ChangeListener.class, l); + } + + /** + * Returns an array of all the <code>ChangeListener</code>s added + * to this AbstractButton with addChangeListener(). + * + * @return all of the <code>ChangeListener</code>s added or an empty + * array if no listeners have been added + * @since 1.4 + */ + public ChangeListener[] getChangeListeners() { + return listenerList.getListeners(ChangeListener.class); + } + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created. + * + * @see EventListenerList + */ + protected void fireStateChanged() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + // Lazily create the event: + if (changeEvent == null) { + changeEvent = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent); + } + } + } + + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,59 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.runtime.swing; - -import javax.swing.SwingUtilities; -import javax.swing.text.AbstractDocument; -import javax.swing.text.JTextComponent; -import java.lang.reflect.Field; - -public class Utils { - private static Field numReaders; - private static Field notifyingListeners; - - public static void setText(final JTextComponent c, final String text) { - try { - // AbstractDocument deadlocks if we try to acquire a write lock while a read lock is held by the current thread - // If there are any readers, dispatch an invokeLater. This should only happen in the event of circular bindings. - // Similarly, circular bindings can result in an "Attempt to mutate in notification" error, which we deal with - // by checking for the 'notifyingListeners' property. - AbstractDocument document = (AbstractDocument) c.getDocument(); - if (numReaders == null) { - numReaders = AbstractDocument.class.getDeclaredField("numReaders"); - numReaders.setAccessible(true); - } - if (notifyingListeners == null) { - notifyingListeners = AbstractDocument.class.getDeclaredField("notifyingListeners"); - notifyingListeners.setAccessible(true); - } - - if (notifyingListeners.get(document).equals(Boolean.TRUE)) - return; - - if (((Integer) numReaders.get(document)).intValue() > 0) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (!c.getText().equals(text)) - c.setText(text); - } - }); - return; - } - - String oldText = c.getText(); - if (oldText == null || !oldText.equals(text)) - c.setText(text); - } - catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - catch (SecurityException e) { - c.setText(text); - } - } -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java (from rev 1027, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/Utils.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,81 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.runtime.swing; + +import javax.swing.ImageIcon; +import javax.swing.SwingUtilities; +import javax.swing.text.AbstractDocument; +import javax.swing.text.JTextComponent; +import java.lang.reflect.Field; + +public class Utils { + private static Field numReaders; + private static Field notifyingListeners; + + public static void setText(final JTextComponent c, final String text) { + try { + // AbstractDocument deadlocks if we try to acquire a write lock while a read lock is held by the current thread + // If there are any readers, dispatch an invokeLater. This should only happen in the event of circular bindings. + // Similarly, circular bindings can result in an "Attempt to mutate in notification" error, which we deal with + // by checking for the 'notifyingListeners' property. + AbstractDocument document = (AbstractDocument) c.getDocument(); + if (numReaders == null) { + numReaders = AbstractDocument.class.getDeclaredField("numReaders"); + numReaders.setAccessible(true); + } + if (notifyingListeners == null) { + notifyingListeners = AbstractDocument.class.getDeclaredField("notifyingListeners"); + notifyingListeners.setAccessible(true); + } + + if (notifyingListeners.get(document).equals(Boolean.TRUE)) { + return; + } + + if (((Integer) numReaders.get(document)).intValue() > 0) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (!c.getText().equals(text)) { + c.setText(text); + } + } + }); + return; + } + + String oldText = c.getText(); + if (oldText == null || !oldText.equals(text)) { + c.setText(text); + } + } + catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + catch (SecurityException e) { + c.setText(text); + } + } + + public static ImageIcon createImageIcon(String path) { + java.net.URL imgURL = Utils.class.getResource("/icons/" + path); + if (imgURL != null) { + return new ImageIcon(imgURL); + } else { + throw new IllegalArgumentException("could not find icon " + path); + } + } + + public static ImageIcon createActionIcon(String name) { + return createImageIcon("action-" + name + ".png"); + } + + public static ImageIcon createI18nIcon(String name) { + return createImageIcon("i18n/" + name + ".png"); + } + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation (from rev 1019, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation) Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeCellRenderer.java (from rev 1036, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeCellRenderer.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeCellRenderer.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeCellRenderer.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,51 @@ +package jaxx.runtime.swing.navigation; + +import jaxx.runtime.JAXXContext; +import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; +import jaxx.runtime.swing.navigation.NavigationUtil.NodeRenderer; + +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeCellRenderer; +import java.awt.Component; + +/** + * A simple cell renderer which use the {@link NavigationTreeNode#renderer} to display node. + * + * @author chemit + */ +public class NavigationTreeCellRenderer extends DefaultTreeCellRenderer { + + protected JAXXContext context; + + public NavigationTreeCellRenderer(JAXXContext context) { + this.context = context; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { + + if (value != null) { + + NodeRenderer renderer = getNodeRenderer(value); + if (renderer != null) { + value = renderer.toString(context); + } + } + + return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + } + + protected NodeRenderer getNodeRenderer(Object value) { + NodeRenderer render = null; + + if (value != null && value instanceof NavigationTreeNode && ((NavigationTreeNode) value).getUserObject() instanceof NodeRenderer) { + + // NodeRenderer used as userObject + NavigationTreeNode navigationTreeNode = (NavigationTreeNode) value; + // could have a cached value ( + render = (NodeRenderer) navigationTreeNode.getUserObject(); + } + return render; + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java 2008-11-17 11:55:31 UTC (rev 1019) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,385 +0,0 @@ -package jaxx.runtime.swing.navigation; - - -import jaxx.runtime.JAXXAction; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXContextEntryDef; -import jaxx.runtime.JAXXObject; -import org.apache.commons.beanutils.BeanUtilsBean; -import org.apache.commons.beanutils.PropertyUtilsBean; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreeNode; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import java.util.Stack; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Le modele utilisé pour un arbre de navigation. - * <p/> - * Il est composé de {@link NavigationTreeModel.NavigationTreeNode} - * - * @author chemit - */ -public class NavigationTreeModel extends DefaultTreeModel { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private final Log log = LogFactory.getLog(NavigationTreeModel.class); - - private static final long serialVersionUID = 1L; - - /** la représentation d'un noeud dans le model {@link NavigationTreeModel} */ - public static class NavigationTreeNode extends DefaultMutableTreeNode { - - private static final long serialVersionUID = 1L; - - /** pour representer le context du noeud. */ - protected String context; - - /** the JAXXObject class associated with this node */ - protected Class<? extends JAXXObject> jaxxClass; - - /** the JAXXAction class associated with this node and will be put in ui context */ - protected Class<? extends JAXXAction> jaxxActionClass; - - /** the definition of the JAXXContext entry associated to this node, if null will seek in parent */ - protected JAXXContextEntryDef jaxxContextEntryDef; - - public NavigationTreeNode(String context, Class<? extends JAXXObject> jaxxClass, Class<? extends JAXXAction> jaxxActionClass, JAXXContextEntryDef jaxxContextEntryDef) { - this.context = context; - this.jaxxClass = jaxxClass; - this.jaxxActionClass = jaxxActionClass; - this.jaxxContextEntryDef = jaxxContextEntryDef; - } - - public NavigationTreeNode(Object userObject, String context, Class<? extends JAXXObject> jaxxClass, Class<? extends JAXXAction> jaxxActionClass, JAXXContextEntryDef jaxxContextEntryDef) { - super(userObject); - this.context = context; - this.jaxxClass = jaxxClass; - this.jaxxActionClass = jaxxActionClass; - this.jaxxContextEntryDef = jaxxContextEntryDef; - } - - public NavigationTreeNode(Object userObject, boolean allowsChildren, String context, Class<? extends JAXXObject> jaxxClass, Class<? extends JAXXAction> jaxxActionClass, JAXXContextEntryDef jaxxContextEntryDef) { - super(userObject, allowsChildren); - this.context = context; - this.jaxxClass = jaxxClass; - this.jaxxActionClass = jaxxActionClass; - this.jaxxContextEntryDef = jaxxContextEntryDef; - } - - public String getContext() { - return context; - } - - public void setContext(String context) { - this.context = context; - } - - public Class<? extends JAXXObject> getJaxxClass() { - return jaxxClass; - } - - public void setJaxxClass(Class<? extends JAXXObject> jaxxClass) { - this.jaxxClass = jaxxClass; - } - - public Class<? extends JAXXAction> getJaxxActionClass() { - return jaxxActionClass; - } - - public void setJaxxActionClass(Class<? extends JAXXAction> jaxxActionClass) { - this.jaxxActionClass = jaxxActionClass; - } - - public JAXXContextEntryDef getJaxxContextEntryDef() { - return jaxxContextEntryDef; - } - - public void setJaxxContextEntryDef(JAXXContextEntryDef jaxxContextEntryDef) { - this.jaxxContextEntryDef = jaxxContextEntryDef; - } - - /** @return the fully context pathof the node from the root node to this. */ - public String getContextPath() { - TreeNode[] path = getPath(); - StringBuilder sb = new StringBuilder(); - for (TreeNode treeNode : path) { - NavigationTreeNode myNode = (NavigationTreeNode) treeNode; - sb.append('.').append(myNode.getContext()); - } - return sb.substring(1); - } - - @Override - public NavigationTreeNode getChildAt(int index) { - return (NavigationTreeNode) super.getChildAt(index); - } - - @Override - public NavigationTreeNode getParent() { - return (NavigationTreeNode) super.getParent(); - } - - /** - * @param context the name of the {@link #context} to be matched in the cild of this node. - * @return the child of this node with given {@link #context} value. - */ - public NavigationTreeNode getChild(String context) { - for (int i = 0, max = getChildCount(); i < max; i++) { - NavigationTreeNode son = getChildAt(i); - if (context.equals(son.getContext())) { - return son; - } - } - return null; - } - - /** - * @return the first ancestor with a none null {@link #jaxxContextEntryDef} - * or <code>null</code> if none find.. - */ - protected NavigationTreeNode getFirstAncestorWithDef() { - if (jaxxContextEntryDef != null) { - return this; - } - return getParent() == null ? null : getParent().getFirstAncestorWithDef(); - } - - protected NavigationTreeNode findNode(Stack<String> stack) { - if (log.isDebugEnabled()) { - log.debug(context + " : enter with " + stack); - } - if (stack.isEmpty()) { - return this; - } - // nextcontext to search - String currentPath = stack.pop(); - if (getContext().equals(currentPath)) { - // this node matchs - return findNode(stack); - } - // find the next matching son - NavigationTreeNode son = getChild(currentPath); - return son == null ? null : son.findNode(stack); - } - - } - - @Override - public NavigationTreeNode getRoot() { - return (NavigationTreeNode) super.getRoot(); - } - - - public NavigationTreeModel(TreeNode root) { - super(root); - } - - public NavigationTreeModel(TreeNode root, boolean asksAllowsChildren) { - super(root, asksAllowsChildren); - } - - /** - * Search from the root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#context} valued separated by dot. - * <p/> - * Example : - * <p/> - * <pre>$root.child1.leaf1</pre> - * - * @param path the fully path of the searched node. - * @return the node matching the fully context from the root node, or <code>null</code> if not find. - */ - public NavigationTreeNode findNode(String path) { - return findNode(getRoot(), path, (Pattern) null); - } - - /** - * Apply first the regex pattern to obtain the searched node. - * <p/> - * Search then from the root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#context} valued separated by dot. - * <p/> - * <p/> - * Example : - * <p/> - * <pre>$root.child1.leaf1</pre> - * - * @param path the fully path of the searched node. - * @param regex a optional regex to apply to path before searching - * @return the node matching the fully context from the root node, or <code>null</code> if not find. - */ - public NavigationTreeNode findNode(String path, String regex) { - return findNode(getRoot(), path, regex); - } - - /** - * Apply first the regex pattern to obtain the searched node. - * <p/> - * Search then from the root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#context} valued separated by dot. - * <p/> - * Example : - * <p/> - * <pre>$root.child1.leaf1</pre> - * - * @param path the fully path of the searched node. - * @param regex a optional regex to apply to path before searching - * @return the node matching the fully context from the root node, or <code>null</code> if not find. - */ - public NavigationTreeNode findNode(String path, Pattern regex) { - return findNode(getRoot(), path, regex); - } - - - /** - * Search from a given root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#context} valued separated by dot. - * - * @param root root node to be used - * @param path the fully path of the searched node. - * @return the node matching the fully context from the given root node, or <code>null</code> if not find. - */ - public NavigationTreeNode findNode(NavigationTreeNode root, String path) { - return findNode(root, path, (Pattern) null); - } - - /** - * Apply first the regex pattern to obtain the searched node. - * <p/> - * Search then from a given root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#context} valued separated by dot. - * - * @param root root node to be used - * @param path the fully path of the searched node. - * @param regex a previous regex to apply to path : must have a matches - * @return the node matching the fully context from the given root node, or <code>null</code> if not find. - */ - public NavigationTreeNode findNode(NavigationTreeNode root, String path, String regex) { - return findNode(root, path, regex == null ? null : Pattern.compile(regex)); - } - - /** - * Apply first the regex pattern to obtain the searched node. - * <p/> - * Search then from a given root node a node named by his fully path (concatenation of nodes - * {@link NavigationTreeNode#context} valued separated by dot. - * - * @param root root node to be used - * @param path the fully path of the searched node. - * @param regex a previous regex to apply to path : must have a matches - * @return the node matching the fully context from the given root node, or <code>null</code> if not find. - */ - public NavigationTreeNode findNode(NavigationTreeNode root, String path, Pattern regex) { - if (regex != null) { - Matcher matcher = regex.matcher(path); - if (!matcher.matches() || matcher.groupCount() < 1) { - log.warn("no matching regex " + regex + " to " + path); - return null; - } - path = matcher.group(1); - log.info("matching regex " + regex + " : " + path); - } - String[] paths = path.split("\\."); - Stack<String> stack = new Stack<String>(); - for (int i = paths.length - 1; i > -1; i--) { - stack.push(paths[i]); - } - return root.findNode(stack); - } - - - /** - * Obtain the associated bean value from context corresponding to node from given contextPath. - * - * @param context the context to seek - * @param contextPath the current context path of the node - * @return the value associated in context with the given context path - * @throws InvocationTargetException todo - * @throws NoSuchMethodException todo - * @throws IllegalAccessException todo - */ - public Object getJAXXContextValue(JAXXContext context, String contextPath) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { - Object result; - NavigationTreeNode node = findNode(contextPath, (Pattern) null); - result = getJAXXContextValue(context, node); - return result; - } - - /** - * Obtain the associated bean value from context corresponding to node - * - * @param context the context to seek - * @param node the current node - * @return the value associated in context with the given context path - * @throws InvocationTargetException todo - * @throws NoSuchMethodException todo - * @throws IllegalAccessException todo - */ - public Object getJAXXContextValue(JAXXContext context, NavigationTreeNode node) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { - Object result; - if (node == null) { - return null; - } - if (node.getJaxxContextEntryDef() != null) { - // the node maps directly a value in context - result = node.getJaxxContextEntryDef().getContextValue(context); - return result; - } - // find the first ancestor node with a context def - NavigationTreeNode parentNode = node.getFirstAncestorWithDef(); - if (parentNode == null) { - // no parent found - return null; - } - - Object parentBean = getJAXXContextValue(context, parentNode); - if (parentBean == null) { - return null; - } - result = parentBean; - // descend from parentNode to node (says descending into parentBean following node contexts) - TreeNode[] path = node.getPath(); - PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance().getPropertyUtils(); - - int level = parentNode.getLevel() + 1; - - if (List.class.isAssignableFrom(parentBean.getClass())) { - // parent bean is a list, returnindexed node - NavigationTreeNode sonNode = (NavigationTreeNode) path[level]; - //TODO Finish it... - int index = parentNode.getIndex(sonNode); - result = ((List) parentBean).get(index); - level++; - } - - for (int i = level, length = path.length; i < length; i++) { - NavigationTreeNode treeNode = (NavigationTreeNode) path[i]; - - String propertyName = treeNode.getContext(); - Object sonBean = propertyUtils.getProperty(result, propertyName); - if (sonBean == null) { - // can be null (for example a leaf list) - result = null; - break; - } - if (!(List.class.isAssignableFrom(sonBean.getClass())) || treeNode.isLeaf() || i == length - 1) { - // simple property and last node - result = sonBean; - continue; - } - // indexed node - NavigationTreeNode sonNode = (NavigationTreeNode) path[++i]; - int index = treeNode.getIndex(sonNode); - result = propertyUtils.getIndexedProperty(result, propertyName, index); - } - return result; - } - -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java (from rev 1036, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModel.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,493 @@ +package jaxx.runtime.swing.navigation; + + +import jaxx.runtime.JAXXAction; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXContextEntryDef; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.swing.navigation.NavigationUtil.NodeRenderer; +import org.apache.commons.jxpath.JXPathContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Le modele utilisé pour un arbre de navigation. + * <p/> + * Il est composé de {@link NavigationTreeModel.NavigationTreeNode} + * + * @author chemit + */ +public class NavigationTreeModel extends DefaultTreeModel { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final Log log = LogFactory.getLog(NavigationTreeModel.class); + + static private final long serialVersionUID = 1L; + + /** the separator char used to produce the navigation path of a node. */ + protected final String navigationPathSeparator; + + public NavigationTreeModel(TreeNode root, String navigationPathSeparator) { + super(root); + this.navigationPathSeparator = navigationPathSeparator; + } + + @Override + public NavigationTreeNode getRoot() { + return (NavigationTreeNode) super.getRoot(); + } + + /** + * Search from the root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#navigationPath} valued separated by dot. + * <p/> + * Example : + * <p/> + * <pre>$root.child1.leaf1</pre> + * + * @param path the fully path of the searched node. + * @return the node matching the fully context from the root node, or <code>null</code> if not find. + */ + public NavigationTreeNode findNode(String path) { + return findNode(getRoot(), path, (Pattern) null); + } + + /** + * Apply first the regex pattern to obtain the searched node fi the given <code>regex</code> is not null. + * <p/> + * Search then from the root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#navigationPath} valued separated by {@link #navigationPathSeparator}. + * <p/> + * <p/> + * Example : + * <p/> + * <pre>$root.child1.leaf1</pre> + * + * @param path the fully path of the searched node. + * @param regex a optional regex to apply to path before searching + * @return the node matching the fully context from the root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(String path, String regex) { + return findNode(getRoot(), path, regex); + } + + /** + * Apply first the regex pattern to obtain the searched node. + * <p/> + * Search then from the root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#navigationPath} valued separated by {@link #navigationPathSeparator}. + * <p/> + * Example : + * <p/> + * <pre>$root.child1.leaf1</pre> + * + * @param path the fully path of the searched node. + * @param regex a optional regex to apply to path before searching + * @return the node matching the fully context from the root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(String path, Pattern regex) { + return findNode(getRoot(), path, regex); + } + + + /** + * Search from a given root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#navigationPath} valued separated by {@link #navigationPathSeparator}. + * + * @param root root node to be used + * @param path the fully path of the searched node. + * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path) { + return findNode(root, path, (Pattern) null); + } + + /** + * Apply first the regex pattern to obtain the searched node. + * <p/> + * Search then from a given root node a node named by his fully path (concatenation of nodes) + * {@link NavigationTreeNode#navigationPath} valued separated by {@link #navigationPathSeparator}. + * + * @param root root node to be used + * @param path the fully path of the searched node. + * @param regex a previous regex to apply to path : must have a matches + * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path, String regex) { + return findNode(root, path, regex == null ? null : Pattern.compile(regex)); + } + + /** + * Apply first the regex pattern to obtain the searched node. + * <p/> + * Search then from a given root node a node named by his fully path (concatenation of nodes + * {@link NavigationTreeNode#navigationPath} valued separated by {@link #navigationPathSeparator}. + * + * @param root root node to be used + * @param path the fully path of the searched node. + * @param regex a previous regex to apply to path : must have a matches + * @return the node matching the fully context from the given root node, or <code>null</code> if not found. + */ + public NavigationTreeNode findNode(NavigationTreeNode root, String path, Pattern regex) { + if (regex != null) { + Matcher matcher = regex.matcher(path); + if (!matcher.matches() || matcher.groupCount() < 1) { + log.warn("no matching regex " + regex + " to " + path); + return null; + } + path = matcher.group(1); + if (log.isDebugEnabled()) { + log.debug("matching regex " + regex + " : " + path); + } + } + StringTokenizer stk = new StringTokenizer(path, navigationPathSeparator); + NavigationTreeNode result = root; + // pas the first token (matches the root node) + if (root.isRoot() && stk.hasMoreTokens()) { + String rootPath = stk.nextToken(); + if (!rootPath.equals(root.getNavigationPath())) { + return null; + } + } + while (stk.hasMoreTokens()) { + result = result.getChild(stk.nextToken()); + } + return result; + } + + + /** + * Obtain the associated bean value from context corresponding to node from given navigation path. + * + * @param context the context where to seek value + * @param navigationPath the current context path of the node + * @return the value associated in context with the given navigation path + */ + public Object getJAXXContextValue(JAXXContext context, String navigationPath) { + Object result; + NavigationTreeNode node = findNode(navigationPath, (Pattern) null); + result = getJAXXContextValue(context, node); + return result; + } + + /** + * Obtain the associated bean value from context corresponding to node + * + * @param context the context where to seek value + * @param node the current node + * @return the value associated in context with the given node. + */ + public Object getJAXXContextValue(JAXXContext context, NavigationTreeNode node) { + if (node == null) { + return null; + //fixme should throw a NPE exception + //throw new NullPointerException("node can not be null"); + } + return node.getJAXXContextValue(context); + } + + /** + * la représentation d'un noeud dans le modele {@link NavigationTreeModel} + * + * @author chemit + */ + public class NavigationTreeNode extends DefaultMutableTreeNode { + + private static final long serialVersionUID = 1L; + + /** pour representer le context du noeud. */ + protected String navigationPath; + + /** the JAXXObject class associated with this node (can be null) */ + protected Class<? extends JAXXObject> jaxxClass; + + /** the JAXXAction class associated with this node and will be put in ui context */ + protected Class<? extends JAXXAction> jaxxActionClass; + + /** the definition of the JAXXContext entry associated to this node, if null will seek in parent */ + protected JAXXContextEntryDef jaxxContextEntryDef; + + /** jxPath to process to obtain real value associated from context with the node (can be null) */ + protected String jaxxContextEntryPath; + + /** renderer of the node */ + protected NodeRenderer renderer; + + public NavigationTreeNode(Object renderer, + Object jaxxContextEntryDef, + String navigationPath, + Class<? extends JAXXObject> jaxxClass, + Class<? extends JAXXAction> jaxxActionClass) { + super(renderer); + if (renderer instanceof NodeRenderer) { + // the renderer must keep a reference of the node + ((NodeRenderer) renderer).setNode(this); + } else if (renderer instanceof String) { + // nothing special to be done + } else if (renderer != null) { + // wrong renderer type + throw new IllegalArgumentException("to define a renderer, must be a String (simple libelle) or a " + NodeRenderer.class + ", but was " + renderer); + } + this.navigationPath = navigationPath; + this.jaxxClass = jaxxClass; + this.jaxxActionClass = jaxxActionClass; + + if (jaxxContextEntryDef instanceof JAXXContextEntryDef) { + this.jaxxContextEntryDef = ((JAXXContextEntryDef) jaxxContextEntryDef); + } else if (jaxxContextEntryDef instanceof String) { + this.jaxxContextEntryPath = (String) jaxxContextEntryDef; + } else if (jaxxContextEntryDef != null) { + // wrong context definition type + throw new IllegalArgumentException("to define a context link, must be a String (jxpath) or a " + JAXXContextEntryDef.class + ", but was " + jaxxContextEntryDef); + } + } + + public NavigationTreeNode(Object renderer, + JAXXContextEntryDef jaxxContextEntryDef, + String jaxxContextEntryPath, + String navigationPath, + Class<? extends JAXXObject> jaxxClass, + Class<? extends JAXXAction> jaxxActionClass) { + super(renderer); + if (renderer instanceof NodeRenderer) { + // the renderer must keep a reference of the node + ((NodeRenderer) renderer).setNode(this); + } else if (renderer instanceof String) { + // nothing special to be done + } else if (renderer != null) { + // wrong renderer type + throw new IllegalArgumentException("to define a renderer, must be a String (simple libelle) or a " + NodeRenderer.class + ", but was " + renderer); + } + this.navigationPath = navigationPath; + this.jaxxClass = jaxxClass; + this.jaxxActionClass = jaxxActionClass; + this.jaxxContextEntryDef = jaxxContextEntryDef; + this.jaxxContextEntryPath = jaxxContextEntryPath; + } + + public String getNavigationPath() { + return navigationPath; + } + + public void setNavigationPath(String navigationPath) { + this.navigationPath = navigationPath; + } + + public Class<? extends JAXXObject> getJaxxClass() { + return jaxxClass; + } + + public void setJaxxClass(Class<? extends JAXXObject> jaxxClass) { + this.jaxxClass = jaxxClass; + } + + public Class<? extends JAXXAction> getJaxxActionClass() { + return jaxxActionClass; + } + + public void setJaxxActionClass(Class<? extends JAXXAction> jaxxActionClass) { + this.jaxxActionClass = jaxxActionClass; + } + + public JAXXContextEntryDef getJaxxContextEntryDef() { + return jaxxContextEntryDef; + } + + public void setJaxxContextEntryDef(JAXXContextEntryDef jaxxContextEntryDef) { + this.jaxxContextEntryDef = jaxxContextEntryDef; + } + + public String getJaxxContextEntryPath() { + return jaxxContextEntryPath; + } + + public void setJaxxContextEntryPath(String jaxxContextEntryPath) { + this.jaxxContextEntryPath = jaxxContextEntryPath; + } + + public Class<?> getInternalClass() { + return renderer.getInternalClass(); + } + + /** @return the fully context pathof the node from the root node to this. */ + public String getContextPath() { + TreeNode[] path = getPath(); + StringBuilder sb = new StringBuilder(); + for (TreeNode treeNode : path) { + NavigationTreeNode myNode = (NavigationTreeNode) treeNode; + sb.append(navigationPathSeparator).append(myNode.getNavigationPath()); + } + return sb.substring(1); + } + + @Override + public NavigationTreeNode getChildAt(int index) { + return (NavigationTreeNode) super.getChildAt(index); + } + + @Override + public NavigationTreeNode getParent() { + return (NavigationTreeNode) super.getParent(); + } + + /** + * @param navigationPath the name of the {@link #navigationPath} to be matched in the cild of this node. + * @return the child of this node with given {@link # navigationPath} value. + */ + public NavigationTreeNode getChild(String navigationPath) { + for (int i = 0, max = getChildCount(); i < max; i++) { + NavigationTreeNode son = getChildAt(i); + if (navigationPath.equals(son.getNavigationPath())) { + return son; + } + } + return null; + } + + /** + * Obtain the associated bean value from context corresponding to node + * + * @param context the context to seek + * @return the value associated in context with the given context path + */ + public Object getJAXXContextValue(JAXXContext context) { + Object result; + + if (getJaxxContextEntryDef() != null && jaxxContextEntryPath == null) { + // the node maps directly a value in context, with no jxpath resolving + result = getJaxxContextEntryDef().getContextValue(context); + return result; + } + // find the first ancestor node with a context def + NavigationTreeNode parentNode = getFirstAncestorWithDef(); + if (parentNode == null) { + log.warn("could not find a ancestor node with a definition of a context entry from node (" + this + ")"); + // todo must be an error + // no parent found + return null; + } + + Object parentBean = parentNode.getJaxxContextEntryDef().getContextValue(context); + + if (parentBean == null) { + // must be an error no bean found + log.warn("culd not find a bean attached in context from context entry definition " + parentNode.getJaxxContextEntryDef()); + return null; + } + + if (parentNode.jaxxContextEntryPath != null) { + // apply the jxpath on parentBean + JXPathContext jxcontext = JXPathContext.newContext(parentBean); + + parentBean = jxcontext.getValue(parentNode.jaxxContextEntryPath); + } + + if (this == parentNode) { + // current node is the node matching the context entry value and no jxpath is found + return parentBean; + } + + if (jaxxContextEntryPath == null) { + // todo must be an error + log.warn("must find a jaxxContextEntryPath on node (" + this + ")"); + return null; + } + + String jxpathExpression = computeJXPath(jaxxContextEntryPath, parentNode); + + if (jxpathExpression == null) { + /// todo must be an error + log.warn("could not build jxpath from node " + parentNode + " to " + this); + // could not retreave the jxpath... + return null; + } + if (jxpathExpression.startsWith("[")) { + // special case when we want to access a collection + jxpathExpression = '.' + jxpathExpression; + } + if (log.isDebugEnabled()) { + log.debug("jxpath : " + jxpathExpression); + } + + JXPathContext jxcontext = JXPathContext.newContext(parentBean); + + result = jxcontext.getValue(jxpathExpression); + + return result; + } + + /** + * @return the first ancestor with a none null {@link #jaxxContextEntryDef} + * or <code>null</code> if none find.. + */ + protected NavigationTreeNode getFirstAncestorWithDef() { + if (jaxxContextEntryDef != null) { + return this; + } + return getParent() == null ? null : getParent().getFirstAncestorWithDef(); + } + + protected String computeJXPath(String expr, NavigationTreeNode parentNode) { + if (parentNode == this) { + // reach the parent limit node, return the expr computed + return expr; + } + int firstIndex = expr.indexOf(".."); + int lastIndex = expr.lastIndexOf(".."); + + if (firstIndex == -1) { + // this is a error, since current node is not parent limit node, + // we must find somewhere a way to go up in nodes + throw new IllegalArgumentException(expr + " should contains at least one \"..\""); + } + + if (firstIndex != 0) { + // this is a error, the ../ must be at the beginning of the expression + throw new IllegalArgumentException("\"..\" must be at the beginning but was : " + expr); + } + + NavigationTreeNode ancestor = getParent(); + + if (firstIndex == lastIndex) { + // found only one go up, so must be substitute by the parent node context + + String newExpr = expr.substring(2); + //String newExpr = expr.substring(expr.startsWith("../") ? 3 : 2); + + if (getParent().equals(parentNode)) { + + // parent node is the final parent node, so no substitution needed + return newExpr; + //return parentNode.computeJXPath(newExpr, parentNode); + } + + // ancestor must have a jaxxContextEntryPath + if (ancestor.jaxxContextEntryPath == null) { + throw new IllegalArgumentException("with the expression " + expr + ", the ancestor node (" + ancestor + ") must have a jaxxContextEntryPath definition, but was not "); + } + + newExpr = ancestor.jaxxContextEntryPath + newExpr; + + return ancestor.computeJXPath(newExpr, parentNode); + } + + // have more than one go up, so the ancestor node can not have a jaxxContextEntryPath + if (ancestor.jaxxContextEntryPath != null) { + throw new IllegalArgumentException("with the expression " + expr + ", the ancestor node can not have a jaxxContextEntryPath definition"); + } + + // substitute the last ..[/] and delegate to ancestor + String newExpr = expr.substring(0, lastIndex - 1) + expr.substring(lastIndex + (expr.charAt(lastIndex + 3) == '/' ? 3 : 2)); + + return ancestor.computeJXPath(newExpr, parentNode); + } + } + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java (from rev 1035, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeModelBuilder.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,98 @@ +package jaxx.runtime.swing.navigation; + +import jaxx.runtime.Decorator; +import jaxx.runtime.JAXXAction; +import jaxx.runtime.JAXXContextEntryDef; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; +import jaxx.runtime.swing.navigation.NavigationUtil.NodeRenderer; + +/** @author chemit */ +public class NavigationTreeModelBuilder { + + protected NavigationTreeModel model; + + public NavigationTreeModelBuilder(String navigationSeparator) { + model = new NavigationTreeModel(null, navigationSeparator); + } + + public NavigationTreeModel getModel() { + return model; + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + JAXXContextEntryDef entryDef, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeNode node = model.new NavigationTreeNode(new NodeRenderer(libelle), entryDef, entryPath, contextName, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + JAXXContextEntryDef entryDef, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeNode node = model.new NavigationTreeNode(new NodeRenderer(libelle), entryDef, contextName, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, String libelle, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeNode node = model.new NavigationTreeNode(new NodeRenderer(libelle), entryPath, contextName, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + JAXXContextEntryDef entryDef, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeNode node = model.new NavigationTreeNode(new NodeRenderer(decorator), entryDef, entryPath, contextName, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + JAXXContextEntryDef entryDef, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeNode node = model.new NavigationTreeNode(new NodeRenderer(decorator), entryDef, contextName, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + public NavigationTreeNode build(NavigationTreeNode parentNode, Decorator<?> decorator, + String entryPath, + String contextName, + Class<? extends JAXXObject> uiClass, + Class<? extends JAXXAction> actionClass) { + NavigationTreeNode node = model.new NavigationTreeNode(new NodeRenderer(decorator), entryPath, contextName, uiClass, actionClass); + return addChildNode(parentNode, node); + } + + protected NavigationTreeNode addChildNode(NavigationTreeNode parentNode, NavigationTreeNode node) { + if (parentNode == null) { + model.setRoot(node); + } else { + parentNode.add(node); + } + model.nodeStructureChanged(parentNode); + return node; + } + + public NavigationTreeNode removeChildNode(NavigationTreeNode node) { + NavigationTreeNode parentNode = node.getParent(); + /*if (parentNode != null) { + parentNode.remove(node); + }*/ + model.removeNodeFromParent(node); + return parentNode; + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java 2008-11-17 11:55:31 UTC (rev 1019) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,181 +0,0 @@ -package jaxx.runtime.swing.navigation; - -import jaxx.runtime.JAXXObject; -import jaxx.runtime.JAXXAction; -import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JTree; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.TreePath; -import java.awt.Component; -import java.lang.reflect.InvocationTargetException; - -/** A {@link javax.swing.event.TreeSelectionListener} implementation@author chemit */ -public abstract class NavigationTreeSelectionAdapter implements TreeSelectionListener { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private final Log log = LogFactory.getLog(NavigationTreeSelectionAdapter.class); - - static public final String NAVIGATION_CONTEXT_PATH = "navigation-context-path"; - - /** la classe d'ui par defaut, associé à un noeud de l'arbe */ - protected Class<? extends JAXXObject> defaultUIClass; - - protected Class<? extends JAXXAction> defaultUIHandlerClass; - - /** l'ui contenant l'arbre de navigation */ - protected JAXXObject context; - - protected NavigationTreeSelectionAdapter(Class<? extends JAXXObject> defaultUIClass, Class<? extends JAXXAction> defaultUIHandlerClass, JAXXObject context) { - this.defaultUIClass = defaultUIClass; - this.defaultUIHandlerClass = defaultUIHandlerClass; - this.context = context; - } - - protected abstract NavigationTreeModel getNavigationTreeModel(); - - /** - * @return le composent actuellement visible associé au noeud courant ou au noeud précédent - * lors d'un changement de noeud. - */ - protected abstract Component getCurrentUI(); - - /** - * @param path le chemin du noeud selectionne dont on veut afficher l'ui associée - * @return l'ui associé au novueau noeud sélectionné - */ - protected abstract Component getNewUI(String path); - - /** - * @param event l'evenement de selection de noeud - * @param component le composent actuellement visible - * @return <code>true</code> si le composent a bien été fermé, <code>false</code> sinon - * @throws Exception if any - */ - protected abstract boolean closeUI(TreeSelectionEvent event, Component component) throws Exception; - - /** - * Instancie une nouvelle ui associé à un noeud de l'arbre de navigation - * - * @param node le noeud associé à l'ui à créer - * @return la nouvelle ui associée au noeud - * @throws Exception if any - */ - protected abstract Component createUI(NavigationTreeNode node) throws Exception; - - /** - * Ouvre l'ui associée au noeud sélectionné dans l'arbre de navigation. - * - * @param newUI l'ui associé au noeud sélectionné à ouvrir - * @param path le path dans le context de navigation - * @throws Exception if any - */ - protected abstract void openUI(Component newUI, NavigationTreeNode path) throws Exception; - - /** - * Retourne au noeud précdemment sélectionné dans l'arbre de navigation, avec la possibilité de notifier - * une erreure survenue. - * - * @param event l'évènement de changement de noeud sélectionné. - * @param e l'erreur recontrée (ou null si pas d"erreur) - */ - protected abstract void goBackToPreviousNode(TreeSelectionEvent event, Exception e); - - public void valueChanged(TreeSelectionEvent event) { - if (event.getOldLeadSelectionPath() != null && event.getOldLeadSelectionPath().equals(event.getPath())) { - // do not treate this if no path changed - return; - } - - try { - - NavigationTreeNode node = (NavigationTreeNode) event.getPath().getLastPathComponent(); - - if (node.getJaxxClass() == null) { - // no ui is associated with this node, display a empty content - node.setJaxxClass(defaultUIClass); - } - - if (node.getJaxxActionClass()==null) { - node.setJaxxActionClass(defaultUIHandlerClass); - } - - String path = node.getContextPath(); - - if (log.isDebugEnabled()) { - log.debug(path); - } - - Component newUI = getNewUI(path); - Component component = getCurrentUI(); - - if (newUI != null && newUI.equals(component)) { - // call back from goto back to previous node, do nothing - return; - } - - - if (!closeUI(event, component)) { - // previous ui was not closed, so reselect the previous node in navigation - goBackToPreviousNode(event, null); - // and quit - return; - } - - // now, we are free to open the ui associated with the selected node in navigation - - // before all, attach bean in context associated with the selected node in naivgation tree - attachBeanFromNodeToContext(node); - - - if (newUI == null) { - // instanciate a new ui associated with the selected node - newUI = createUI(node); - - } - - // save in context current node context path - context.setContextValue(node.getContextPath(), NAVIGATION_CONTEXT_PATH); - - // really open the ui associated with the selected node - openUI(newUI, node); - - } catch (Exception e) { - // if any error, go back to previvous node - goBackToPreviousNode(event, e); - } - - } - - protected void attachBeanFromNodeToContext(NavigationTreeNode node) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { - - String path = node.getContextPath(); - - NavigationTreeModel navigationModel = getNavigationTreeModel(); - - //if (navigationModel != null) { - - Object data = navigationModel.getJAXXContextValue(context, path); - if (data != null) { - if (log.isInfoEnabled()) { - log.info("find data for contextPath <" + path + "> : " + data.getClass()); - } - context.setContextValue(data); - } - //} - } - - protected void returnToPreviousNode(JTree tree, TreeSelectionEvent event) { - // go back to previous node - // put in context a tag to not come back again here - TreePath oldPath = event.getOldLeadSelectionPath(); - //NavigationTreeNode oldNode = (NavigationTreeNode) oldPath.getLastPathComponent(); - if (oldPath != null) { - tree.setSelectionPath(oldPath); - } - } - -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java (from rev 1055, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,233 @@ +package jaxx.runtime.swing.navigation; + +import jaxx.runtime.JAXXAction; +import jaxx.runtime.JAXXContextEntryDef; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTree; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import java.awt.Component; + +/** A {@link javax.swing.event.TreeSelectionListener} implementation@author chemit */ +public abstract class NavigationTreeSelectionAdapter implements TreeSelectionListener { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final Log log = LogFactory.getLog(NavigationTreeSelectionAdapter.class); + + static public final String NAVIGATION_CONTEXT_PATH = "navigation-context-path"; + + static public final String NAVIGATION_SELECTED_NODE = "navigation-selected-node"; + + static public final String NAVIGATION_SELECTED_BEAN = "navigation-selected-bean"; + + static public final JAXXContextEntryDef<Boolean> GO_BACK_DEF = JAXXContextEntryDef.newDef("goBack", Boolean.class); + + /** defined the stategy of instanciation of ui */ + public enum Strategy { + /** instanciate a ui for a node */ + PER_NODE, + /** instanciate only one a ui for a type,nodes will share the instanciation */ + PER_UI_TYPE + } + + /** la classe d'ui par defaut, associé à un noeud de l'arbe */ + protected Class<? extends JAXXObject> defaultUIClass; + + protected Class<? extends JAXXAction> defaultUIHandlerClass; + + /** l'ui contenant l'arbre de navigation */ + protected JAXXObject context; + + protected Strategy strategy; + + protected NavigationTreeSelectionAdapter(Class<? extends JAXXObject> defaultUIClass, Class<? extends JAXXAction> defaultUIHandlerClass, JAXXObject context, Strategy strategy) { + this.defaultUIClass = defaultUIClass; + this.defaultUIHandlerClass = defaultUIHandlerClass; + this.context = context; + this.strategy = strategy; + } + + + protected abstract NavigationTreeModel getNavigationTreeModel(); + + /** + * @return le composent actuellement visible associé au noeud courant ou au noeud précédent + * lors d'un changement de noeud. + */ + protected abstract Component getCurrentUI(); + + /** + * @param node le noeud associé à l'ui à retrouver + * @return l'ui associé au novueau noeud sélectionné + */ + protected abstract Component getUI(NavigationTreeNode node); + + /** + * @param event l'evenement de selection de noeud + * @param component le composent actuellement visible + * @return <code>true</code> si le composent a bien été fermé, <code>false</code> sinon + * @throws Exception if any + */ + protected abstract boolean closeUI(TreeSelectionEvent event, Component component) throws Exception; + + /** + * Instancie une nouvelle ui associé à un noeud de l'arbre de navigation + * + * @param node le noeud associé à l'ui à créer + * @return la nouvelle ui associée au noeud + * @throws Exception if any + */ + protected abstract Component createUI(NavigationTreeNode node) throws Exception; + + /** + * Ouvre l'ui associée au noeud sélectionné dans l'arbre de navigation. + * + * @param newUI l'ui associé au noeud sélectionné à ouvrir + * @param node le node de l'ui a ouvrir + * @throws Exception if any + */ + protected abstract void openUI(Component newUI, NavigationTreeNode node) throws Exception; + + /** + * Retourne au noeud précdemment sélectionné dans l'arbre de navigation, avec la possibilité de notifier + * une erreure survenue. + * + * @param event l'évènement de changement de noeud sélectionné. + * @param e l'erreur recontrée (ou null si pas d"erreur) + */ + protected abstract void goBackToPreviousNode(TreeSelectionEvent event, Exception e); + + /** + * Prepare le nouveau noeud sélectionné. + * + * @param event l'évènement de selection du noeud + * @return le noeud selectionné et preparé + */ + protected NavigationTreeNode prepareNode(TreeSelectionEvent event) { + NavigationTreeNode node = (NavigationTreeNode) event.getPath().getLastPathComponent(); + + if (node.getJaxxClass() == null) { + // no ui is associated with this node, display a empty content + node.setJaxxClass(defaultUIClass); + } + + if (node.getJaxxActionClass() == null) { + node.setJaxxActionClass(defaultUIHandlerClass); + } + return node; + } + + public void valueChanged(TreeSelectionEvent event) { + if (event.getOldLeadSelectionPath() != null && event.getOldLeadSelectionPath().equals(event.getPath())) { + // do not treate this if no path changed + return; + } + + Boolean goBack = GO_BACK_DEF.getContextValue(context); + if (goBack != null && goBack) { + // do not treate this, apsecial flag told us :) + GO_BACK_DEF.removeContextValue(context); + return; + } + + try { + + NavigationTreeNode node = prepareNode(event); + + String path = node.getContextPath(); + + if (log.isTraceEnabled()) { + log.trace(path); + } + + Component newUI = getUI(node); + Component component = getCurrentUI(); + + if (newUI != null && strategy == Strategy.PER_NODE && newUI.equals(component)) { + // call back from goto back to previous node, do nothing + return; + } + + if (!closeUI(event, component)) { + GO_BACK_DEF.setContextValue(context, Boolean.TRUE); + // previous ui was not closed, so reselect the previous node in navigation + goBackToPreviousNode(event, null); + // and quit + return; + } + + // now, we are free to open the ui associated with the selected node in navigation + + // before all, attach bean in context associated with the selected node in naivgation tree + Object data = getNavigationTreeModel().getJAXXContextValue(context, path); + + addSelectedBeanInContext(node, data); + + if (newUI == null) { + // instanciate a new ui associated with the selected node + newUI = createUI(node); + } + + // save in context current node context path + context.setContextValue(node.getContextPath(), NAVIGATION_CONTEXT_PATH); + + // save in context current node + context.setContextValue(node, NAVIGATION_SELECTED_NODE); + + // really open the ui associated with the selected node + openUI(newUI, node); + + } catch (Exception e) { + // remove data from context + + // if any error, go back to previvous node + goBackToPreviousNode(event, e); + } + } + + protected void addSelectedBeanInContext(NavigationTreeNode node, Object data) { + + if (log.isDebugEnabled()) { + log.debug("find data for contextPath <" + node.getContextPath() + "> : " + (data == null ? null : data.getClass())); + } + + context.removeContextValue(Object.class, NAVIGATION_SELECTED_BEAN); + + if (data != null) { + context.setContextValue(data, NAVIGATION_SELECTED_BEAN); + //todo should we not use this to avoid conflict in context ? + context.setContextValue(data); + } + } + + protected String getNodeConstraints(NavigationTreeNode node) { + String constraints; + switch (strategy) { + case PER_NODE: + constraints = node.getContextPath(); + break; + case PER_UI_TYPE: + constraints = node.getJaxxClass().getName(); + break; + default: + throw new IllegalArgumentException("could not find constraint for node : " + node); + } + return constraints; + } + + protected void returnToPreviousNode(JTree tree, TreeSelectionEvent event) { + // go back to previous node + // put in context a tag to not come back again here + TreePath oldPath = event.getOldLeadSelectionPath(); + //NavigationTreeNode oldNode = (NavigationTreeNode) oldPath.getLastPathComponent(); + if (oldPath != null) { + tree.setSelectionPath(oldPath); + } + } + +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapterWithCardLayout.java (from rev 1053, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapterWithCardLayout.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapterWithCardLayout.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationTreeSelectionAdapterWithCardLayout.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,108 @@ +package jaxx.runtime.swing.navigation; + +import jaxx.runtime.JAXXAction; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXInitialContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.swing.CardLayout2; +import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JPanel; +import javax.swing.event.TreeSelectionEvent; +import java.awt.Component; + +/** + * Simple {@link NavigationTreeSelectionAdapter} implementation with a {@link jaxx.runtime.swing.CardLayout2} to manage components to + * associated with tree's nodes. + * <p/> + * For each node, the ui associated has a constraints in a cardlayout which is the node context path. + * <p/> + * A single container managed by the cardlayout is used to display the components associated with tree's nodes. + * + * @author chemit + */ +public abstract class NavigationTreeSelectionAdapterWithCardLayout extends NavigationTreeSelectionAdapter { + + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final Log log = LogFactory.getLog(NavigationTreeSelectionAdapterWithCardLayout.class); + + /** + * All components associated with a tree's node is displayed in a single container. + * + * @return the containter of components + */ + protected abstract JPanel getContentContainer(); + + /** + * the cardlayout managing components associated with tree node. The constraints + * of each component is the node contextPath. + * + * @return the layout used to display components associated with tree's nodes. + */ + protected abstract CardLayout2 getContentLayout(); + + public NavigationTreeSelectionAdapterWithCardLayout(Class<? extends JAXXObject> defaultUIClass, Class<? extends JAXXAction> defaultUIHandlerClass, JAXXObject context, Strategy strategy) { + super(defaultUIClass, defaultUIHandlerClass, context,strategy); + + if (getContentContainer() == null) { + throw new IllegalArgumentException("could not have a null 'contentContainer' in ui " + context); + } + if (getContentLayout() == null) { + throw new IllegalArgumentException("could not have a null 'contentLayout' in ui " + context); + } + } + + protected Component getCurrentUI() { + CardLayout2 layout = getContentLayout(); + JPanel container = getContentContainer(); + return layout.getVisibleComponent(container); + } + + protected Component getUI(NavigationTreeNode node) { + CardLayout2 layout = getContentLayout(); + JPanel container = getContentContainer(); + String path = getNodeConstraints(node); + return layout.contains(path) ? layout.getComponent(container, path) : null; + } + + protected void openUI(Component newUI, NavigationTreeNode node) throws Exception { + + CardLayout2 layout = getContentLayout(); + JPanel container = getContentContainer(); + // switch layout + layout.show(container, getNodeConstraints(node)); + } + + protected boolean closeUI(TreeSelectionEvent event, Component component) throws Exception { + // by default, we says that component was succesfull closed + return true; + } + + protected Component createUI(NavigationTreeNode node) throws Exception { + JAXXObject newUI; + + if (node.getJaxxActionClass() != null) { + JAXXAction action = node.getJaxxActionClass().newInstance(); + // init context with + JAXXInitialContext context = action.init(this.context); + // must instanciate the ui with an JAXXInitialContext + newUI = node.getJaxxClass().getConstructor(JAXXContext.class).newInstance(context); + } else { + if (log.isWarnEnabled()) { + log.warn("no action associated with ui " + node.getJaxxClass()); + } + // no action associated, just + newUI = node.getJaxxClass().getConstructor(JAXXContext.class).newInstance(this.context); + } + if (log.isDebugEnabled()) { + log.debug("instanciate new ui " + newUI); + } + + getContentContainer().add((Component) newUI, getNodeConstraints(node)); + return (Component) newUI; + } +} + Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationUtil.java (from rev 1036, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationUtil.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationUtil.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationUtil.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,134 @@ +package jaxx.runtime.swing.navigation; + +import jaxx.runtime.Decorator; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; +import static org.codelutin.i18n.I18n._; + +import java.lang.reflect.InvocationTargetException; +import java.util.regex.Pattern; + +/** + * Usefull methods on {@link NavigationTreeModel} and others. + * + * @author chemit + * @see jaxx.runtime.swing.navigation.NavigationTreeModel + * @see jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode + */ +public class NavigationUtil { + + public static String getCurrentNavigationNath(JAXXContext context) { + return context.getContextValue(String.class, NavigationTreeSelectionAdapter.NAVIGATION_CONTEXT_PATH); + } + + public static NavigationTreeNode getSelectedNode(JAXXContext context) { + return context.getContextValue(NavigationTreeNode.class, NavigationTreeSelectionAdapter.NAVIGATION_SELECTED_NODE); + } + + public static <O> O getSelectedBean(JAXXContext context, Class<O> clazz) { + return context.getContextValue(clazz, NavigationTreeSelectionAdapter.NAVIGATION_SELECTED_BEAN); + } + + public static Object getContextValue(JAXXContext context, String contextKey, String navigationPath) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { + + NavigationTreeModel navigationModel = context.getContextValue(NavigationTreeModel.class, contextKey); + + return navigationModel.getJAXXContextValue(context, navigationPath); + } + + public static NavigationTreeNode findNode(JAXXContext context, String contextKey, String navigationPath) { + + NavigationTreeModel navigationModel = context.getContextValue(NavigationTreeModel.class, contextKey); + + return navigationModel.findNode(navigationPath); + } + + public static NavigationTreeNode findNode(JAXXContext context, String contextKey, String navigationPath, String regex) { + + NavigationTreeModel navigationModel = context.getContextValue(NavigationTreeModel.class, contextKey); + + return navigationModel.findNode(navigationPath, regex); + } + + + public static NavigationTreeNode findNode(JAXXContext context, String contextKey, String navigationPath, Pattern regex) { + + NavigationTreeModel navigationModel = context.getContextValue(NavigationTreeModel.class, contextKey); + + return navigationModel.findNode(navigationPath, regex); + } + + public static NavigationTreeNode findNode(JAXXContext context, String contextKey, String navigationPath, String regex, String suffix) { + + NavigationTreeModel navigationModel = context.getContextValue(NavigationTreeModel.class, contextKey); + + NavigationTreeNode navigationTreeNode = navigationModel.findNode(navigationPath, regex); + if (navigationTreeNode != null && suffix != null) { + navigationTreeNode = navigationModel.findNode(navigationTreeNode, suffix); + } + return navigationTreeNode; + } + + public static NavigationTreeNode findNode(JAXXContext context, String contextKey, String navigationPath, Pattern regex, String suffix) { + + NavigationTreeModel navigationModel = context.getContextValue(NavigationTreeModel.class, contextKey); + + NavigationTreeNode navigationTreeNode = navigationModel.findNode(navigationPath, regex); + if (navigationTreeNode != null && suffix != null) { + navigationTreeNode = navigationModel.findNode(navigationTreeNode, suffix); + } + return navigationTreeNode; + } + + public static class NodeRenderer implements java.io.Serializable { + + protected String libelle; + + protected Decorator decorator; + + protected NavigationTreeNode node; + + protected Class<?> internalClass; + + private static final long serialVersionUID = -1238962588426200861L; + + public NodeRenderer(String libelle) { + this.libelle = libelle; + this.internalClass = String.class; + } + + public NodeRenderer(Decorator decorator) { + this.decorator = decorator; + this.internalClass = decorator.getInternalClass(); + } + + public String toString(JAXXContext context) { + if (libelle != null) { + // simple libelle renderer + return _(libelle); + } + + // with decorator renderer + String result; + + try { + Object bean = node.getJAXXContextValue(context); + result = decorator.toString(bean); + + } catch (Exception e) { + result = ""; + } + + return result; + } + + public void setNode(NavigationTreeNode node) { + this.node = node; + } + + public Class<?> getInternalClass() { + return internalClass; + } + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationtreeSelectionAdapterWithCardLayout.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationtreeSelectionAdapterWithCardLayout.java 2008-11-17 11:55:31 UTC (rev 1019) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/swing/navigation/NavigationtreeSelectionAdapterWithCardLayout.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,106 +0,0 @@ -package jaxx.runtime.swing.navigation; - -import jaxx.runtime.JAXXAction; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXInitialContext; -import jaxx.runtime.JAXXObject; -import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; -import jaxx.runtime.swing.CardLayout2; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JPanel; -import javax.swing.event.TreeSelectionEvent; -import java.awt.Component; - -/** - * Simple {@link NavigationTreeSelectionAdapter} implementation with a {@link jaxx.runtime.swing.CardLayout2} to manage components to - * associated with tree's nodes. - * <p/> - * For each node, the ui associated has a constraints in a cardlayout which is the node context path. - * <p/> - * A single container managed by the cardlayout is used to display the components associated with tree's nodes. - * - * @author chemit - */ -public abstract class NavigationtreeSelectionAdapterWithCardLayout extends NavigationTreeSelectionAdapter { - - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private final Log log = LogFactory.getLog(NavigationtreeSelectionAdapterWithCardLayout.class); - - /** - * All components associated with a tree's node is displayed in a single container. - * - * @return the containter of components - */ - protected abstract JPanel getContentContainer(); - - /** - * the cardlayout managing components associated with tree node. The constraints - * of each component is the node contextPath. - * - * @return the layout used to display components associated with tree's nodes. - */ - protected abstract CardLayout2 getContentLayout(); - - public NavigationtreeSelectionAdapterWithCardLayout(Class<? extends JAXXObject> defaultUIClass, Class<? extends JAXXAction> defaultUIHandlerClass, JAXXObject context) { - super(defaultUIClass, defaultUIHandlerClass, context); - - if (getContentContainer() == null) { - throw new IllegalArgumentException("could not have a null 'contentContainer' in ui " + context); - } - if (getContentLayout() == null) { - throw new IllegalArgumentException("could not have a null 'contentLayout' in ui " + context); - } - } - - protected Component getCurrentUI() { - CardLayout2 layout = getContentLayout(); - JPanel container = getContentContainer(); - return layout.getVisibleComponent(container); - } - - protected Component getNewUI(String path) { - CardLayout2 layout = getContentLayout(); - JPanel container = getContentContainer(); - return layout.contains(path) ? layout.getComponent(container, path) : null; - } - - protected void openUI(Component newUI, NavigationTreeNode node) throws Exception { - CardLayout2 layout = getContentLayout(); - JPanel container = getContentContainer(); - // switch layout - layout.show(container, node.getContextPath()); - } - - protected boolean closeUI(TreeSelectionEvent event, Component component) throws Exception { - // by default, we says that component was succesfull closed - return true; - } - - protected Component createUI(NavigationTreeNode node) throws Exception { - JAXXObject newUI; - - if (node.getJaxxActionClass() != null) { - JAXXAction action = node.getJaxxActionClass().newInstance(); - // init context with - JAXXInitialContext context = action.init(this.context); - // must instanciate the ui with an JAXXInitialContext - newUI = node.getJaxxClass().getConstructor(JAXXContext.class).newInstance(context); - } else { - if (log.isWarnEnabled()) { - log.warn("no action associated with ui " + node.getJaxxClass()); - } - // no action associated, just - newUI = node.getJaxxClass().getConstructor(JAXXContext.class).newInstance(this.context); - } - if (log.isDebugEnabled()) { - log.debug("instanciate new ui " + newUI); - } - - getContentContainer().add((Component) newUI, node.getContextPath()); - return (Component) newUI; - } -} - Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,500 +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.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.beanutils.ConversionException; -import org.apache.commons.beanutils.Converter; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codelutin.util.ConverterUtil; -import org.jdesktop.jxlayer.JXLayer; - -import javax.swing.JComponent; -import javax.swing.SwingUtilities; -import java.awt.Container; -import java.beans.Introspector; -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.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - -/** - * <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; - - /** ui renderer class */ - protected Class<? extends AbstractBeanValidatorUI> uiClass; - - /** validator context */ - protected ActionContext context; - - protected Map<String, String> conversionErrors; - - public BeanValidator() { - pcs = new PropertyChangeSupport(this); - validationSupport = new ValidationAwareSupport(); - validationContext = new DelegatingValidatorContext(validationSupport); - fieldRepresentation = new HashMap<String, JComponent>(); - conversionErrors = new TreeMap<String, String>(); - } - - 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; - - // clean conversions of previous bean - conversionErrors.clear(); - 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() || !conversionErrors.isEmpty(); - //return validationContext.hasFieldErrors() || validationContext.hasActionErrors(); - } - - public Map getFieldErrors() { - return validationContext.getFieldErrors(); - } - - public Collection getActionErrors() { - return validationContext.getActionErrors(); - } - - public Collection getActionMessages() { - return validationContext.getActionMessages(); - } - - public Map<String, String> getConversionErrors() { - return conversionErrors; - } - - /** 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); - } - } - } - }); - - } - - /** - * Convert a value. - * <p/> - * If an error occurs, then add an error in validator. - * - * @param fieldName the name of the bean property - * @param value the value to convert - * @param valueClass the type of converted value - * @return the converted value, or null if conversion was not ok - */ - public <T> T convert(String fieldName, String value, Class<T> valueClass) { - if (valueClass == null) { - throw new IllegalArgumentException("valueClass can not be null"); - } - - // on ne convertit pas 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 || value == null) { - return null; - } - - // remove the previous conversion error for the field - conversionErrors.remove(fieldName); - - T result; - try { - Converter converter = ConverterUtil.getConverter(valueClass); - if (converter == null) { - throw new RuntimeException("could not find converter for the type " + valueClass); - } - result = (T) converter.convert(valueClass, value); - if (result != null && !value.equals(result.toString())) { - conversionErrors.put(fieldName, "error.convertor." + Introspector.decapitalize(valueClass.getSimpleName())); - result = null; - validate(); - } - } catch (ConversionException e) { - // get - conversionErrors.put(fieldName, "error.convertor." + Introspector.decapitalize(valueClass.getSimpleName())); - result = null; - validate(); - } - - return result; - } - - /** - * 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); - - // add the registred conversion errors - transfertConversionErrorsToFieldErrors(); - - 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(); - context = new ActionContext(vs.getContext()); - ActionContext.setContext(context); - - validator = conf.getContainer().getInstance( - ActionValidatorManager.class, "no-annotations"); - } - //TC - 20081024 : since context is in a ThreadLocal variable, we must do the check - if (ActionContext.getContext() == null) { - ActionContext.setContext(context); - } - 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); - } - } - } - } - - /** - * Transfer the registred conversion errors to fieldErrors. - * <p/> - * The previously filed errors of a given field where a conversion error occurs will be removed. - */ - protected void transfertConversionErrorsToFieldErrors() { - Map map = getFieldErrors(); - for (Entry<String, String> entry : conversionErrors.entrySet()) { - // remove from validation, errors occurs on this field - List errors = (List) map.get(entry.getKey()); - if (errors != null) { - errors.clear(); - errors.add(entry.getValue()); - } else { - errors = Collections.singletonList(entry.getValue()); - } - // add the concrete conversion error - map.put(entry.getKey(), errors); - } - validationContext.setFieldErrors(map); - } - - - 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.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java (from rev 1052, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidator.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,609 @@ +/* *##% + * 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.beanutils.ConversionException; +import org.apache.commons.beanutils.Converter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.util.ConverterUtil; +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import java.awt.Container; +import java.beans.Introspector; +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.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +/** + * <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 + * @author chemit + * @version 1.0 + * <p/> + * Last update: $Date$ + * by : chemit + */ +public class BeanValidator<T> { + + /** + * Pour definir le niveau de validation. + * <p/> + * Par défaut, le validateur est supposé géré des erreurs, mais on peut aussi l'utiliser + * pour consigner des warnings sur le bean surveiller. + */ + public enum Scope { + ERROR, + WARNING + } + + static public final String BEAN_PROERTY = "bean"; + + private static final String CONTEXT_NAME_PROPERTY = "contextName"; + + static public final String VALID_PROERTY = "valid"; + + static public final String CHANGED_PROERTY = "changed"; + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private final Log log = LogFactory.getLog(BeanValidator.class); + + /** Constant name of the default ui renderer to be used. */ + static private final Class<? extends AbstractBeanValidatorUI> DEFAULT_UI_CLASS = IconValidationUI.class; + + /** delgate property change support */ + 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; + + /** state of the validator */ + protected boolean valid; + + /** le bean a surveiller */ + protected T bean = null; + + /** l'objet qui recoit les notifications de modification du bean */ + protected PropertyChangeListener l; + + /** 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; + + /** Object servant a contenir la liste des erreurs */ + protected BeanValidatorErrorTableModel errorTableModel; + + /** ui renderer class */ + protected Class<? extends AbstractBeanValidatorUI> uiClass; + + /** validator context */ + protected ActionContext context; + + /** map of conversion errors detected by this validator */ + protected Map<String, String> conversionErrors; + + /** the validation named context */ + protected String contextName; + + protected Scope scope = Scope.ERROR; + + public BeanValidator() { + pcs = new PropertyChangeSupport(this); + validationSupport = new ValidationAwareSupport(); + validationContext = new DelegatingValidatorContext(validationSupport); + fieldRepresentation = new HashMap<String, JComponent>(); + conversionErrors = new TreeMap<String, String>(); + l = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + validate(); + setValid(!hasErrors()); + setChanged(true); + } + }; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public BeanValidatorErrorListModel getErrorListModel() { + return errorListModel; + } + + public BeanValidatorErrorTableModel getErrorTableModel() { + return errorTableModel; + } + + public JComponent getFieldRepresentation(String fieldname) { + return fieldRepresentation.get(fieldname); + } + + public Scope getScope() { + return scope; + } + + /** + * 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; + } + + public boolean isValid() { + return valid; + } + + public T getBean() { + return bean; + } + + public Class<? extends AbstractBeanValidatorUI> getUiClass() { + return uiClass; + } + + public Map getFieldErrors() { + return validationContext.getFieldErrors(); + } + + public Collection getActionErrors() { + return validationContext.getActionErrors(); + } + + public Collection getActionMessages() { + return validationContext.getActionMessages(); + } + + public Map<String, String> getConversionErrors() { + return conversionErrors; + } + + public void setErrorListModel(BeanValidatorErrorListModel errorListModel) { + this.errorListModel = errorListModel; + if (errorListModel != null) { + // register the validator in the model list + errorListModel.registerValidator(this); + } + } + + public void setErrorTableModel(BeanValidatorErrorTableModel errorTableModel) { + this.errorTableModel = errorTableModel; + if (errorTableModel != null) { + // register the validator in the model table + errorTableModel.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()); + } + } + + /** + * 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_PROERTY, oldChanged, changed); + } + + public void setValid(boolean valid) { + boolean oldValid = this.valid; + this.valid = valid; + if (oldValid != valid) { + pcs.firePropertyChange(VALID_PROERTY, oldValid, valid); + } + } + + public void setBean(T bean) { + T oldBean = this.bean; + + // clean conversions of previous bean + conversionErrors.clear(); + if (oldBean != null) { + try { + Method method = this.bean.getClass().getMethod("removePropertyChangeListener", PropertyChangeListener.class); + method.invoke(oldBean, l); + } catch (Exception eee) { + log.info("Can't register as listener", eee); + } + } + this.bean = bean; + if (bean != null) { + try { + Method method = this.bean.getClass().getMethod("addPropertyChangeListener", PropertyChangeListener.class); + method.invoke(bean, l); + } catch (Exception eee) { + log.info("Can't register as listener", eee); + } + validate(); + } else { + // must remove all errors from this validator on errorListModel + validationSupport.clearErrorsAndMessages(); + addErrors(); + } + setValid(!hasErrors()); + setChanged(false); + pcs.firePropertyChange(BEAN_PROERTY, oldBean, bean); + } + + public void setContextName(String contextName) { + String oldValidationContextName = this.contextName; + this.contextName = contextName; + pcs.firePropertyChange(CONTEXT_NAME_PROPERTY, oldValidationContextName, contextName); + } + + public void setUiClass(Class<? extends AbstractBeanValidatorUI> uiClass) { + this.uiClass = uiClass; + } + + public void setScope(Scope scope) { + this.scope = scope; + } + + /** @return <code>true</code> if errors are detected, <code>false</code> otherwise */ + public boolean hasErrors() { + //todo should also detecte actionErrors ? + return scope == Scope.ERROR && (validationContext.hasFieldErrors() || !conversionErrors.isEmpty()); + //return validationContext.hasFieldErrors() || validationContext.hasActionErrors(); + } + + public boolean hasWarnings() { + return scope == Scope.WARNING && (validationContext.hasFieldErrors() || !conversionErrors.isEmpty()); + } + + /** 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); + } + } + } + }); + + } + + /** + * Convert a value. + * <p/> + * If an error occurs, then add an error in validator. + * + * @param fieldName the name of the bean property + * @param value the value to convert + * @param valueClass the type of converted value + * @return the converted value, or null if conversion was not ok + */ + public <T> T convert(String fieldName, String value, Class<T> valueClass) { + if (fieldName == null) { + throw new IllegalArgumentException("fieldName can not be null"); + } + if (valueClass == null) { + throw new IllegalArgumentException("valueClass can not be null"); + } + + // on ne convertit pas si il y a un bean et que le resultat de la validation + // pourra etre affiche quelque part + if (checkState() || value == null) { + return null; + } + + // remove the previous conversion error for the field + conversionErrors.remove(fieldName); + + T result; + try { + Converter converter = ConverterUtil.getConverter(valueClass); + if (converter == null) { + throw new RuntimeException("could not find converter for the type " + valueClass); + } + result = (T) converter.convert(valueClass, value); + /* Why this test ? if (result != null && !value.equals(result.toString())) { + conversionErrors.put(fieldName, "error.convertor." + Introspector.decapitalize(valueClass.getSimpleName())); + result = null; + validate(); + }*/ + } catch (ConversionException e) { + // get + conversionErrors.put(fieldName, "error.convertor." + Introspector.decapitalize(valueClass.getSimpleName())); + result = null; + validate(); + } + + return result; + } + + /** + * 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 (checkState()) { + return; + } + + try { + + validationSupport.clearErrorsAndMessages(); + + getValidator().validate(bean, contextName, validationContext); + + // add the registred conversion errors + transfertConversionErrorsToFieldErrors(); + + if (log.isTraceEnabled()) { + log.trace("Action errors: " + validationContext.getActionErrors()); + log.trace("Action messages: " + validationContext.getActionMessages()); + log.trace("Field errors: " + validationContext.getFieldErrors()); + } + + if (log.isDebugEnabled()) { + log.debug(this + " : " + validationContext.getFieldErrors()); + } + // add errors + addErrors(); + + 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); + } + } + + @Override + public String toString() { + return super.toString() + "<contextName:" + contextName + ">"; + } + + /** @return <code>true</code> if validation is not active , <code>false</code> otherwise. */ + protected boolean checkState() { + return bean == null || (getErrorListModel() == null && getErrorTableModel() == null) || fieldRepresentation.size() == 0; + } + + 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(); + context = new ActionContext(vs.getContext()); + ActionContext.setContext(context); + + validator = conf.getContainer().getInstance( + ActionValidatorManager.class, "no-annotations"); + } + //TC - 20081024 : since context is in a ThreadLocal variable, we must do the check + if (ActionContext.getContext() == null) { + ActionContext.setContext(context); + } + 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); + } + } + } + } + + /** + * Transfer the registred conversion errors to fieldErrors. + * <p/> + * The previously filed errors of a given field where a conversion error occurs will be removed. + */ + protected void transfertConversionErrorsToFieldErrors() { + Map map = getFieldErrors(); + for (Entry<String, String> entry : conversionErrors.entrySet()) { + // remove from validation, errors occurs on this field + List errors = (List) map.get(entry.getKey()); + if (errors != null) { + errors.clear(); + errors.add(entry.getValue()); + } else { + errors = Collections.singletonList(entry.getValue()); + } + // add the concrete conversion error + map.put(entry.getKey(), errors); + } + validationContext.setFieldErrors(map); + } + + protected void addErrors() { + if (errorListModel != null) { + errorListModel.addErrors(this); + } + if (errorTableModel != null) { + errorTableModel.addErrors(this); + } + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,83 +0,0 @@ -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.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java (from rev 1042, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorError.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,89 @@ +package jaxx.runtime.validator; + +import org.codelutin.i18n.I18n; + +import javax.swing.JComponent; + +import jaxx.runtime.validator.BeanValidator.Scope; + +/** + * 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; + } + + public Scope getScope() { + return validator.getScope(); + } + + @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; + } +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,139 +0,0 @@ -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.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java (from rev 1042, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorListModel.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,139 @@ +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; + + /** comporator of 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.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java (from rev 1054, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/BeanValidatorErrorTableModel.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,163 @@ +package jaxx.runtime.validator; + +import jaxx.runtime.validator.BeanValidator.Scope; + +import javax.swing.JComponent; +import javax.swing.table.DefaultTableModel; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +/** + * The model of the list of errors + * + * @author chemit + */ +public class BeanValidatorErrorTableModel extends DefaultTableModel { + + private static final long serialVersionUID = 1L; + + public static final String[] columnNames = {"validator.scope", "validator.field", "validator.message"}; + + /** list of registred validators */ + protected transient List<BeanValidator<?>> validators; + + /** comporator of errors */ + protected transient Comparator<BeanValidatorError> comparator; + + public BeanValidatorErrorTableModel() { + super(columnNames, 0); + validators = new ArrayList<BeanValidator<?>>(); + } + + public int getErrorColumn() { + return findColumn(BeanValidatorErrorTableModel.columnNames[2]); + } + + @Override + public boolean isCellEditable(int row, int column) { + // cells are never editable in this model + return false; + } + + 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 + getDataVector().clear(); + // reinject in list model, all the errors + for (BeanValidatorError error : newErrors) { + addRow(new Object[]{error.getScope(), error.getFieldName(), error}); + } + + // notify thaht the model has changed + fireTableDataChanged(); + } + } + + 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() || validator.hasWarnings()) { + // 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) { + + int col = getErrorColumn(); + for (Object o : super.getDataVector()) { + Vector row = (Vector) o; + BeanValidatorError<?> error = (BeanValidatorError<?>) row.get(col); + 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) { + // first sort on scope + int scope = o1.getScope().ordinal() - o2.getScope().ordinal(); + if (scope != 0) { + return scope; + } + int field = o1.getFieldName().compareTo(o2.getFieldName()); + if (field != 0) { + return field; + } + return o1.getError().compareTo(o2.getError()); + } + }; + } + return comparator; + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,62 +0,0 @@ -package jaxx.runtime.validator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.JComponent; -import javax.swing.JList; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -/** - * A mouse listener to put on a {@link JList} with a {@link BeanValidatorErrorListModel} as a model. - * <p/> - * When a double click occurs, find the selected error in model and then focus to the associated component of error. - * - * @author chemit - */ -public class ErrorListMouseListener extends MouseAdapter { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(ErrorListMouseListener.class); - - @Override - public void mouseClicked(MouseEvent e) { - super.mouseClicked(e); - if (e.getClickCount() == 2) { - - BeanValidatorError<?> entry = getSelectedError(e); - if (entry == null) { - // no entry found - return; - } - JComponent component = entry.getComponent(); - if (component == null) { - return; - } - component.requestFocus(); - } - } - - - protected BeanValidatorError<?> getSelectedError(MouseEvent e) { - JList list = (JList) e.getSource(); - if (!(list.getModel() instanceof BeanValidatorErrorListModel)) { - log.warn("model must ne a " + BeanValidatorErrorListModel.class + ", but was " + list.getModel()); - return null; - } - - BeanValidatorErrorListModel model = (BeanValidatorErrorListModel) list.getModel(); - int index = list.getSelectionModel().getMinSelectionIndex(); - if (index == -1) { - // nothing is selected - return null; - } - BeanValidatorError<?> entry = (BeanValidatorError) model.getElementAt(index); - if (log.isDebugEnabled()) { - log.debug("selected index: " + index + " : error: " + entry); - } - return entry; - } - -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorListMouseListener.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,61 @@ +package jaxx.runtime.validator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JList; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * A mouse listener to put on a {@link JList} with a {@link BeanValidatorErrorListModel} as a model. + * <p/> + * When a double click occurs, find the selected error in model and then focus to the associated component of error. + * + * @author chemit + */ +public class ErrorListMouseListener extends MouseAdapter { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(ErrorListMouseListener.class); + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + BeanValidatorError<?> entry = getSelectedError(e); + if (entry == null) { + // no entry found + return; + } + JComponent component = entry.getComponent(); + if (component != null) { + component.requestFocus(); + } + } + } + + + protected BeanValidatorError<?> getSelectedError(MouseEvent e) { + JList list = (JList) e.getSource(); + if (!(list.getModel() instanceof BeanValidatorErrorListModel)) { + log.warn("model must be a " + BeanValidatorErrorListModel.class + ", but was " + list.getModel()); + return null; + } + + BeanValidatorErrorListModel model = (BeanValidatorErrorListModel) list.getModel(); + int index = list.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + BeanValidatorError<?> entry = (BeanValidatorError) model.getElementAt(index); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java (from rev 1042, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableMouseListener.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,62 @@ +package jaxx.runtime.validator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JTable; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * A mouse listener to put on a {@link javax.swing.JList} with a {@link jaxx.runtime.validator.BeanValidatorErrorListModel} as a model. + * <p/> + * When a double click occurs, find the selected error in model and then focus to the associated component of error. + * + * @author chemit + */ +public class ErrorTableMouseListener extends MouseAdapter { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(ErrorTableMouseListener.class); + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + BeanValidatorError<?> entry = getSelectedError(e); + if (entry == null) { + // no entry found + return; + } + JComponent component = entry.getComponent(); + if (component != null) { + component.requestFocus(); + } + } + } + + + protected BeanValidatorError<?> getSelectedError(MouseEvent e) { + JTable table = (JTable) e.getSource(); + if (!(table.getModel() instanceof BeanValidatorErrorTableModel)) { + log.warn("model must be a " + BeanValidatorErrorTableModel.class + ", but was " + table.getModel()); + return null; + } + + BeanValidatorErrorTableModel model = (BeanValidatorErrorTableModel) table.getModel(); + int index = table.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + int col = model.getErrorColumn(); + BeanValidatorError<?> entry = (BeanValidatorError) model.getValueAt(index, col); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableRenderer.java (from rev 1043, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableRenderer.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableRenderer.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/runtime/validator/ErrorTableRenderer.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,55 @@ +package jaxx.runtime.validator; + +import jaxx.runtime.swing.Utils; +import jaxx.runtime.validator.BeanValidator.Scope; +import static org.codelutin.i18n.I18n._; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Component; + +/** @author chemit */ +public class ErrorTableRenderer extends DefaultTableCellRenderer { + + ImageIcon errorIcon; + ImageIcon warningIcon; + + public ErrorTableRenderer() { + errorIcon = Utils.createImageIcon("error.png"); + warningIcon = Utils.createImageIcon("warning.png"); + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel rendererComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + ImageIcon icon = null; + String text = null; + if (value instanceof Scope) { + + Scope scope = (Scope) value; + switch (scope) { + case ERROR: + icon = errorIcon; + break; + case WARNING: + icon = warningIcon; + break; + } + } else if (value instanceof BeanValidatorError) { + text = _(((BeanValidatorError) value).getError()); + } else { + // keep text rendered + text = rendererComponent.getText(); + } + rendererComponent.setText(text); + rendererComponent.setIcon(icon); + return rendererComponent; + } + + @Override + protected void setValue(Object value) { + super.setValue(value); + } +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,1109 +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 = 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 Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/DefaultObjectHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,1135 @@ +/* + * 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 CompilerException(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("javaBean")) { + continue; + } + 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 + continue; + } + if (name.equals("javaBean")) { + object.setJavaBean(true); + if (!value.isEmpty()) { + object.setJavaBeanInitCode(value); + } + return; + } + if (name.equals("implements")) { + if (object != compiler.getRootObject()) { + // can ony be apply to root object + compiler.reportError("'implements' attribute can only be found on root tag but was found on tag " + tag); + return; + } + String[] interfaces = value.split(","); + compiler.setExtraInterfaces(interfaces); + return; + } + + if (isEventHandlerName(name)) { + // event handler + if (!value.endsWith(";")) { + value += ";"; + } + addEventHandler(object, Introspector.decapitalize(name.substring(2)), value, compiler); + continue; + } + // simple property + 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.getJavaCodeForProperty(name), 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.7/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,78 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.tags.swing; - -import jaxx.CompilerException; -import jaxx.UnsupportedAttributeException; -import jaxx.compiler.CompiledObject; -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.runtime.swing.JAXXButtonGroup; -import jaxx.tags.DefaultComponentHandler; -import jaxx.types.TypeManager; - -import javax.swing.AbstractButton; -import javax.swing.event.ChangeListener; - -public class JRadioButtonHandler extends DefaultComponentHandler { - private static final String VALUE_PROPERTY = "value"; - private static final String BUTTON_GROUP_PROPERTY = "buttonGroup"; - - public JRadioButtonHandler(ClassDescriptor beanClass) { - super(beanClass); - ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, AbstractButton.class); - } - - @Override - protected void configureProxyEventInfo() { - super.configureProxyEventInfo(); - addProxyEventInfo("isSelected", ChangeListener.class, "model"); - } - - @Override - public ClassDescriptor getPropertyType(CompiledObject object, String name, JAXXCompiler compiler) throws CompilerException { - if (name.equals(BUTTON_GROUP_PROPERTY)) - return null; // accepts either a String or a ButtonGroup - else if (name.equals(VALUE_PROPERTY)) - return ClassDescriptorLoader.getClassDescriptor(Object.class); - else - return super.getPropertyType(object, name, compiler); - } - - @Override - public boolean isMemberBound(String name) throws UnsupportedAttributeException { - return !(name.equals(BUTTON_GROUP_PROPERTY) || name.equals(VALUE_PROPERTY)) && super.isMemberBound(name); - } - - // handle buttonGroup assignment in addition block rather than initialization block - @Override - public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) { - if (name.equals(BUTTON_GROUP_PROPERTY)) - object.appendAdditionCode(getSetPropertyCode(object.getJavaCode(), name, TypeManager.getJavaCode(value), compiler)); - else - super.setProperty(object, name, value, compiler); - } - - @Override - public String getSetPropertyCode(String id, String name, String valueCode, JAXXCompiler compiler) throws CompilerException { - if (name.equals(BUTTON_GROUP_PROPERTY)) { - if (valueCode.startsWith("\"") && valueCode.endsWith("\"")) { - valueCode = valueCode.substring(1, valueCode.length() - 1); - CompiledObject buttonGroup = compiler.getCompiledObject(valueCode); - if (buttonGroup == null) { - buttonGroup = new CompiledObject(valueCode, ClassDescriptorLoader.getClassDescriptor(JAXXButtonGroup.class), compiler); - compiler.registerCompiledObject(buttonGroup); - } - } - return "{ javax.swing.ButtonGroup $buttonGroup = " + valueCode + "; " + id + ".putClientProperty(\"$buttonGroup\", $buttonGroup); $buttonGroup.add(" + id + "); }\n"; - } else if (name.equals(VALUE_PROPERTY)) - return "{ " + id + ".putClientProperty(\"$value\", " + valueCode + "); Object $buttonGroup = " + id + ".getClientProperty(\"$buttonGroup\");" + - " if ($buttonGroup instanceof jaxx.runtime.swing.JAXXButtonGroup) { ((jaxx.runtime.swing.JAXXButtonGroup) $buttonGroup).updateSelectedValue(); } }\n"; - else - return super.getSetPropertyCode(id, name, valueCode, compiler); - } - -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/JRadioButtonHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,78 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.tags.swing; + +import jaxx.CompilerException; +import jaxx.UnsupportedAttributeException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.runtime.swing.JAXXButtonGroup; +import jaxx.tags.DefaultComponentHandler; +import jaxx.types.TypeManager; + +import javax.swing.AbstractButton; +import javax.swing.event.ChangeListener; + +public class JRadioButtonHandler extends DefaultComponentHandler { + private static final String VALUE_PROPERTY = JAXXButtonGroup.VALUE_CLIENT_PROPERTY.substring(1); + private static final String BUTTON_GROUP_PROPERTY = JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY.substring(1); + + public JRadioButtonHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorLoader.checkSupportClass(getClass(), beanClass, AbstractButton.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("isSelected", ChangeListener.class, "model"); + } + + @Override + public ClassDescriptor getPropertyType(CompiledObject object, String name, JAXXCompiler compiler) throws CompilerException { + if (name.equals(BUTTON_GROUP_PROPERTY)) + return null; // accepts either a String or a ButtonGroup + else if (name.equals(VALUE_PROPERTY)) + return ClassDescriptorLoader.getClassDescriptor(Object.class); + else + return super.getPropertyType(object, name, compiler); + } + + @Override + public boolean isMemberBound(String name) throws UnsupportedAttributeException { + return !(name.equals(BUTTON_GROUP_PROPERTY) || name.equals(VALUE_PROPERTY)) && super.isMemberBound(name); + } + + // handle buttonGroup assignment in addition block rather than initialization block + @Override + public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) { + if (name.equals(BUTTON_GROUP_PROPERTY)) + object.appendAdditionCode(getSetPropertyCode(object.getJavaCode(), name, TypeManager.getJavaCode(value), compiler)); + else + super.setProperty(object, name, value, compiler); + } + + @Override + public String getSetPropertyCode(String id, String name, String valueCode, JAXXCompiler compiler) throws CompilerException { + if (name.equals(BUTTON_GROUP_PROPERTY)) { + if (valueCode.startsWith("\"") && valueCode.endsWith("\"")) { + valueCode = valueCode.substring(1, valueCode.length() - 1); + CompiledObject buttonGroup = compiler.getCompiledObject(valueCode); + if (buttonGroup == null) { + buttonGroup = new CompiledObject(valueCode, ClassDescriptorLoader.getClassDescriptor(JAXXButtonGroup.class), compiler); + compiler.registerCompiledObject(buttonGroup); + } + } + return "{ javax.swing.ButtonGroup $buttonGroup = " + valueCode + "; " + id + ".putClientProperty(\"$buttonGroup\", $buttonGroup); $buttonGroup.add(" + id + "); }\n"; + } else if (name.equals(VALUE_PROPERTY)) + return "{ " + id + ".putClientProperty(\""+JAXXButtonGroup.VALUE_CLIENT_PROPERTY+"\", " + valueCode + "); Object $buttonGroup = " + id + ".getClientProperty(\""+JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY+"\");" + + " if ($buttonGroup instanceof jaxx.runtime.swing.JAXXButtonGroup) { ((jaxx.runtime.swing.JAXXButtonGroup) $buttonGroup).updateSelectedValue(); } }\n"; + else + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,90 +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.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))); - - 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.7/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/swing/SwingInitializer.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,105 @@ +/* + * 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.DefaultObjectHandler; +import jaxx.tags.TagManager; +import jaxx.tags.validator.BeanValidatorHandler; +import jaxx.tags.validator.ExcludeFieldValidatorHandler; +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 { + + protected static String[] extraBeanInfoSearchPath; + + public static String[] getExtraBeanInfoSearchPath() { + return extraBeanInfoSearchPath; + } + + public static void setExtraBeanInfoSearchPath(String[] extraBeanInfoSearchPath) { + SwingInitializer.extraBeanInfoSearchPath = extraBeanInfoSearchPath; + } + + public void initialize() { + String[] searchPath = Introspector.getBeanInfoSearchPath(); + String[] newSearchPath = new String[searchPath.length + 1 + (extraBeanInfoSearchPath == null ? 0 : extraBeanInfoSearchPath.length)]; + System.arraycopy(searchPath, 0, newSearchPath, 0, searchPath.length); + + newSearchPath[searchPath.length] = "jaxx.beaninfos"; + if (extraBeanInfoSearchPath != null && extraBeanInfoSearchPath.length > 0) { + System.arraycopy(extraBeanInfoSearchPath, 0, newSearchPath, searchPath.length + 1, extraBeanInfoSearchPath.length); + } + Introspector.setBeanInfoSearchPath(newSearchPath); + + TagManager.registerTag("java.awt.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorLoader.getClassDescriptor(JAXXButtonGroup.class))); + + 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.TAG, new FieldValidatorHandler()); + TagManager.registerTag(JAXXCompiler.JAXX_NAMESPACE, ExcludeFieldValidatorHandler.TAG, new FieldValidatorHandler()); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,448 +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.Util; -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 BEAN_CLASS_ATTRIBUTE = "beanClass"; - public static final String BEAN_INITIALIZER_ATTRIBUTE = "beanInitializer"; - - public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; - public static final String ERROR_LIST_ATTRIBUTE = "errorList"; - public static final String ERROR_LIST_MODEL_DEFAULT = "errors"; - public static final String ERROR_LIST_DEFAULT = "errorList"; - - 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); - - 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); - - boolean error = info.addErrorListModel(tag, this, compiler); - - if (!error) { - error = info.addErrorList(tag, compiler); - } - - if (!error) { - error = info.addUiClass(this, compiler); - } - - if (!error) { - error = info.addBean(tag, this, compiler); - } - - if (error) { - log.warn("error were detected in second compile pass of CompiledObject [" + 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); - } - // delegate to the compiled object with is statefull (but not the tag handler) - object.addProperty(propertyName, stringValue); - } - - /** - * The compiled objet representing a BeanValidator to be generated in JAXXObject - * - * @author chemit - */ - public static class CompiledBeanValidator extends CompiledObject { - - protected Map<String, String> fields; - protected String bean; - protected String beanClass; - protected String beanInitializer; - protected String uiClass; - protected String errorListModel; - protected String errorList; - 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 (BEAN_CLASS_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - beanClass = value; - } - return; - } - if (BEAN_INITIALIZER_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - beanInitializer = value; - } - return; - } - - if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorListModel = value; - } - return; - } - if (ERROR_LIST_ATTRIBUTE.equals(property)) { - if (value != null && !value.trim().isEmpty()) { - errorList = 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 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 String getBeanClass() { - return beanClass; - } - - public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { - if (beanDescriptor == null && foundBean()) { - - String beanClassName = null; - try { - // get the real bean class name (from bean or beanClass) - if (beanClass != null) { - beanClassName = beanClass; - } else { - 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 = DefaultObjectHandler.getJAXXBeanInfo(beanClassDescriptor); - } catch (ClassNotFoundException e) { - compiler.reportError("could not load class " + beanClassName); - } catch (IntrospectionException e) { - compiler.reportError("could not load class " + beanClassName); - } - } - 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)"); - } - - public boolean foundBean() { - return !(bean == null && beanClass == null); - } - - protected boolean addUiClass(BeanValidatorHandler handler, JAXXCompiler compiler) { - boolean withError = false; - if (uiClass != null) { - try { - ClassDescriptor uiClazz = ClassDescriptorLoader.getClassDescriptor(uiClass); - if (!ClassDescriptorLoader.getClassDescriptor(AbstractBeanValidatorUI.class).isAssignableFrom(uiClazz)) { - compiler.reportError("attribute 'ui' :'" + uiClass + "' is not assignable from class " + AbstractBeanValidatorUI.class); - withError = true; - } else { - String code = handler.getSetPropertyCode(getJavaCode(), UI_CLASS_ATTRIBUTE, uiClazz.getName() + ".class", compiler); - appendAdditionCode(code); - } - } catch (ClassNotFoundException e) { - compiler.reportError("class not found '" + uiClass + "'"); - withError = true; - } - } - return withError; - } - - protected boolean addErrorListModel(Element tag, BeanValidatorHandler handler, JAXXCompiler compiler) { - if (errorListModel == null) { - // try with the default "errors" - if (!compiler.checkReference(tag, ERROR_LIST_MODEL_DEFAULT, false, ERROR_LIST_MODEL_ATTRIBUTE)) { - return false; - } - errorListModel = ERROR_LIST_MODEL_DEFAULT; - } else { - if (!compiler.checkReference(tag, errorListModel, true, ERROR_LIST_MODEL_ATTRIBUTE)) { - return true; - } - } - - String code = handler.getSetPropertyCode(getJavaCode(), ERROR_LIST_MODEL_ATTRIBUTE, errorListModel, compiler); - appendAdditionCode(code); - - return false; - - } - - protected boolean addErrorList(Element tag, JAXXCompiler compiler) { - - if (errorList == null) { - // try with the default "errorList" - if (!compiler.checkReference(tag, ERROR_LIST_DEFAULT, false, ERROR_LIST_ATTRIBUTE)) { - return false; - } - errorList = ERROR_LIST_DEFAULT; - } else { - if (!compiler.checkReference(tag, errorList, true, ERROR_LIST_ATTRIBUTE)) { - return true; - } - } - - String code = Util.class.getName() + ".registerErrorListMouseListener(" + errorList + ");"; - appendAdditionCode(code); - - return false; - - } - - protected boolean addBean(Element tag, BeanValidatorHandler handler, JAXXCompiler compiler) { - - if (!foundBean()) { - compiler.reportError("tag '" + tag + "' requires a 'bean' or a 'beanClass' attribute"); - return true; - } - - if (bean != null) { - - if (!compiler.checkReference(tag, bean, true, BEAN_ATTRIBUTE)) { - // could not find bean in compiled object - return true; - } - - if (compiler.isBeanUsedByValidator(bean)) { - compiler.reportError("the bean '" + bean + "' is already used in another the validator, can not used it in '" + tag + "'"); - return true; - } - - if (beanInitializer != null) { - compiler.reportWarning("tag '" + tag + "' found a 'bean' and a 'beanInitializer' attributes, 'beanInitializer' is skipped"); - } - beanInitializer = bean; - } - - if (beanInitializer != null) { - String code = handler.getSetPropertyCode(getJavaCode(), BEAN_ATTRIBUTE, compiler.checkJavaCode(beanInitializer), compiler); - appendAdditionCode(code); - } - - // add generic type to validator - JAXXBeanInfo beanInfo = getBeanDescriptor(compiler); - setGenericTypes(new String[]{beanInfo.getJAXXBeanDescriptor().getClassDescriptor().getName()}); - - if (getAutoField()) { - registerAutoFieldBean(tag, compiler, beanInfo); - } - - if (getBeanDescriptor(compiler) != null) { - - // add fieldrepresentation invocations - addFieldRepresentations(tag, compiler); - - // register the validator in compiler - compiler.registerValidator(this); - - } - - return false; - } - - protected void addFieldRepresentations(Element tag, JAXXCompiler compiler) { - for (Entry<String, String> entry : fields.entrySet()) { - String propertyName = entry.getKey(); - String component = entry.getValue(); - if (!checkBeanProperty(compiler, 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); - appendAdditionCode(getJavaCode() + ".setFieldRepresentation(" + keyCode + ", " + component + ");"); - - } - } - - protected void registerAutoFieldBean(Element tag, JAXXCompiler compiler, JAXXBeanInfo beanInfo) { - 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 (fields.containsKey(descriptionName)) { - // already defined in field - continue; - } - if (!compiler.checkReference(tag, descriptionName, getStrictMode(), null)) { - // no editor component found - continue; - } - // ok add the field mapping - registerField(descriptionName, descriptionName, compiler); - } - } - - public void registerField(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); - } - } - - protected boolean checkBeanProperty(JAXXCompiler compiler, String propertyName) { - - for (JAXXPropertyDescriptor beanProperty : 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 [" + getBean() + "] "); - return false; - } - return true; - } - } - compiler.reportError("could not find the property '" + propertyName + "' on bean [" + getBean() + "] "); - return false; - } - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java (from rev 1054, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/BeanValidatorHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,626 @@ +/* + * 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.Util; +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidator.Scope; +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 TAG = BeanValidator.class.getSimpleName(); + public static final String BEAN_ATTRIBUTE = "bean"; + public static final String BEAN_CLASS_ATTRIBUTE = "beanClass"; + public static final String BEAN_INITIALIZER_ATTRIBUTE = "beanInitializer"; + + public static final String ERROR_LIST_MODEL_ATTRIBUTE = "errorListModel"; + public static final String ERROR_TABLE_MODEL_ATTRIBUTE = "errorTableModel"; + public static final String ERROR_LIST_ATTRIBUTE = "errorList"; + public static final String ERROR_TABLE_ATTRIBUTE = "errorTable"; + + public static final String ERROR_LIST_MODEL_DEFAULT = "errors"; + public static final String ERROR_TABLE_MODEL_DEFAULT = "errors2"; + + public static final String ERROR_LIST_DEFAULT = "errorList"; + public static final String ERROR_TABLE_DEFAULT = "errorTable"; + + public static final String AUTOFIELD_ATTRIBUTE = "autoField"; + public static final String UI_CLASS_ATTRIBUTE = "uiClass"; + public static final String STRICT_MODE_ATTRIBUTE = "strictMode"; + + public static final String CONTEXT_NAME_ATTRIBUTE = "contextName"; + + public static final String SCOPE_ATTRIBUTE = "scope"; + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static Log log = LogFactory.getLog(BeanValidatorHandler.class); + + 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.TAG)) { + compiler.reportError("tag '" + tag.getParentNode().getLocalName() + "' may only contain " + FieldValidatorHandler.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); + + boolean error = info.addErrorListModel(tag, this, compiler); + + if (!error) { + error = info.addErrorList(tag, compiler); + } + + if (!error) { + error = info.addErrorTableModel(tag, this, compiler); + } + + if (!error) { + error = info.addErrorTable(tag, compiler); + } + + if (!error) { + error = info.addUiClass(this, compiler); + } + + if (!error) { + error = info.addBean(tag, this, compiler); + } + + if (!error) { + error = info.addContextName(this, compiler); + } + + if (!error) { + error = info.addScope(this, compiler); + } + + if (error) { + log.warn("error were detected in second compile pass of CompiledObject [" + 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); + } + // delegate to the compiled object with is statefull (but not the tag handler) + object.addProperty(propertyName, stringValue); + } + + /** + * The compiled objet representing a BeanValidator to be generated in JAXXObject + * + * @author chemit + */ + public static class CompiledBeanValidator extends CompiledObject { + + protected Map<String, String> fields; + protected Map<String, String> excludeFields; + protected String bean; + protected String beanClass; + protected String contextName; + protected String uiClass; + protected String errorListModel; + protected String errorList; + protected Boolean autoField; + protected Boolean strictMode; + protected JAXXBeanInfo beanDescriptor; + protected String errorTableModel; + protected String errorTable; + protected Scope scope; + + public CompiledBeanValidator(String id, ClassDescriptor objectClass, JAXXCompiler compiler) { + super(id, objectClass, compiler); + fields = new TreeMap<String, String>(); + excludeFields = new TreeMap<String, String>(); + } + + public Map<String, String> getFields() { + return fields; + } + + public Map<String, String> getExcludeFields() { + return excludeFields; + } + + public void setFields(Map<String, String> fields) { + this.fields = fields; + } + + public void setExcludeFields(Map<String, String> excludeFields) { + this.excludeFields = excludeFields; + } + + @Override + public void addProperty(String property, String value) { + + if (BEAN_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + bean = value.trim(); + } + return; + } + + if (CONTEXT_NAME_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + contextName = value.trim(); + } + return; + } + + if (BEAN_CLASS_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + beanClass = value.trim(); + } + return; + } + + if (ERROR_LIST_MODEL_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorListModel = value.trim(); + } + return; + } + + if (ERROR_LIST_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorList = value.trim(); + } + return; + } + + if (ERROR_TABLE_MODEL_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorTableModel = value.trim(); + } + return; + } + + if (ERROR_TABLE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + errorTable = value.trim(); + } + return; + } + + if (UI_CLASS_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + uiClass = value.trim(); + } + return; + } + + if (AUTOFIELD_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + autoField = (Boolean) TypeManager.convertFromString(value.trim(), Boolean.class); + } + return; + } + + if (STRICT_MODE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + strictMode = (Boolean) TypeManager.convertFromString(value.trim(), Boolean.class); + } + return; + } + + if (SCOPE_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + scope = (Scope) TypeManager.convertFromString(value.trim(), Scope.class); + } + return; + } + + throw new CompilerException("property " + property + " is not allowed on object " + this); + + //todo should not allowed to find other attributes + //super.addProperty(property, value); + } + + 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 String getBeanClass() { + return beanClass; + } + + public String getContextName() { + return contextName; + } + + public Scope getScope() { + return scope; + } + + public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { + if (beanDescriptor == null && foundBean()) { + + String beanClassName = null; + try { + // get the real bean class name (from bean or beanClass) + if (beanClass != null) { + beanClassName = beanClass; + } else { + 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 = DefaultObjectHandler.getJAXXBeanInfo(beanClassDescriptor); + } catch (ClassNotFoundException e) { + compiler.reportError("could not load class " + beanClassName); + } catch (IntrospectionException e) { + compiler.reportError("could not load class " + beanClassName); + } + } + 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 '" + TAG + " (only field tags)"); + } + + public boolean foundBean() { + return !(bean == null && beanClass == null); + } + + protected boolean addUiClass(BeanValidatorHandler handler, JAXXCompiler compiler) { + boolean withError = false; + if (uiClass != null) { + try { + ClassDescriptor uiClazz = ClassDescriptorLoader.getClassDescriptor(uiClass); + if (!ClassDescriptorLoader.getClassDescriptor(AbstractBeanValidatorUI.class).isAssignableFrom(uiClazz)) { + compiler.reportError("attribute 'ui' :'" + uiClass + "' is not assignable from class " + AbstractBeanValidatorUI.class); + withError = true; + } else { + String code = handler.getSetPropertyCode(getJavaCode(), UI_CLASS_ATTRIBUTE, uiClazz.getName() + ".class", compiler); + appendAdditionCode(code); + } + } catch (ClassNotFoundException e) { + compiler.reportError("class not found '" + uiClass + "'"); + withError = true; + } + } + return withError; + } + + protected boolean addErrorListModel(Element tag, BeanValidatorHandler handler, JAXXCompiler compiler) { + if (errorListModel == null) { + // try with the default "errors" + if (!compiler.checkReference(tag, ERROR_LIST_MODEL_DEFAULT, false, ERROR_LIST_MODEL_ATTRIBUTE)) { + return false; + } + errorListModel = ERROR_LIST_MODEL_DEFAULT; + } else { + if (errorListModel.startsWith("{") && errorListModel.endsWith("}")) { + // this is a script, no check here + errorListModel = errorListModel.substring(1, errorListModel.length() - 1).trim(); + } else if (!compiler.checkReference(tag, errorListModel, true, ERROR_LIST_MODEL_ATTRIBUTE)) { + // errorListModel is not defined + return true; + } + } + + String code = handler.getSetPropertyCode(getJavaCode(), ERROR_LIST_MODEL_ATTRIBUTE, errorListModel, compiler); + appendAdditionCode(code); + + return false; + + } + + protected boolean addErrorTableModel(Element tag, BeanValidatorHandler handler, JAXXCompiler compiler) { + if (errorTableModel == null) { + // try with the default "errors" + if (!compiler.checkReference(tag, ERROR_TABLE_MODEL_DEFAULT, false, ERROR_LIST_MODEL_ATTRIBUTE)) { + return false; + } + errorTableModel = ERROR_TABLE_MODEL_DEFAULT; + } else { + if (errorTableModel.startsWith("{") && errorTableModel.endsWith("}")) { + // this is a script, no check here + errorTableModel = errorTableModel.substring(1, errorTableModel.length() - 1).trim(); + } else if (!compiler.checkReference(tag, errorTableModel, true, ERROR_TABLE_MODEL_ATTRIBUTE)) { + // errorListModel is not defined + return true; + } + } + + String code = handler.getSetPropertyCode(getJavaCode(), ERROR_TABLE_MODEL_ATTRIBUTE, errorTableModel, compiler); + appendAdditionCode(code); + + return false; + + } + + protected boolean addContextName(BeanValidatorHandler handler, JAXXCompiler compiler) { + if (contextName != null) { + String code = handler.getSetPropertyCode(getJavaCode(), CONTEXT_NAME_ATTRIBUTE, TypeManager.getJavaCode(contextName), compiler); + appendAdditionCode(code); + } + return false; + } + + protected boolean addScope(BeanValidatorHandler handler, JAXXCompiler compiler) { + if (scope != null) { + String code = handler.getSetPropertyCode(getJavaCode(), SCOPE_ATTRIBUTE, TypeManager.getJavaCode(scope), compiler); + appendAdditionCode(code); + } + return false; + } + + protected boolean addErrorList(Element tag, JAXXCompiler compiler) { + + if (errorList == null) { + // try with the default "errorList" + if (!compiler.checkReference(tag, ERROR_LIST_DEFAULT, false, ERROR_LIST_ATTRIBUTE)) { + return false; + } + errorList = ERROR_LIST_DEFAULT; + } else { + if (!compiler.checkReference(tag, errorList, true, ERROR_LIST_ATTRIBUTE)) { + return true; + } + } + + String code = Util.class.getName() + ".registerErrorListMouseListener(" + errorList + ");"; + appendAdditionCode(code); + + return false; + + } + + protected boolean addErrorTable(Element tag, JAXXCompiler compiler) { + + if (errorTable == null) { + // try with the default "errorList" + if (!compiler.checkReference(tag, ERROR_TABLE_DEFAULT, false, ERROR_TABLE_ATTRIBUTE)) { + return false; + } + errorTable = ERROR_TABLE_DEFAULT; + } else { + if (!compiler.checkReference(tag, errorTable, true, ERROR_TABLE_ATTRIBUTE)) { + return true; + } + } + + String code = Util.class.getName() + ".registerErrorTableMouseListener(" + errorTable + ");"; + appendAdditionCode(code); + + return false; + + } + + protected boolean addBean(Element tag, BeanValidatorHandler handler, JAXXCompiler compiler) { + + if (!foundBean()) { + compiler.reportError("tag '" + tag + "' requires a 'bean' or a 'beanClass' attribute"); + return true; + } + + String beanInitializer = null; + if (bean != null) { + + if (bean.startsWith("{") && bean.endsWith("}")) { + + // just has an intializer + beanInitializer = bean.substring(1, bean.length() - 1); + // this is not a real bean, so delete it + bean = null; + } else { + + if (!compiler.checkReference(tag, bean, true, BEAN_ATTRIBUTE)) { + // could not find bean in compiled object + return true; + } + + if (compiler.isBeanUsedByValidator(bean)) { + compiler.reportError("the bean '" + bean + "' is already used in another the validator, can not used it in '" + tag + "'"); + return true; + } + + /*if (beanInitializer != null) { + compiler.reportWarning("tag '" + tag + "' found a 'bean' and a 'beanInitializer' attributes, 'beanInitializer' is skipped"); + }*/ + beanInitializer = bean; + } + } + + if (beanInitializer != null) { + String code = handler.getSetPropertyCode(getJavaCode(), BEAN_ATTRIBUTE, compiler.checkJavaCode(beanInitializer), compiler); + appendAdditionCode(code); + } + + // add generic type to validator + JAXXBeanInfo beanInfo = getBeanDescriptor(compiler); + if (beanInfo == null) { + return true; + } + + setGenericTypes(new String[]{beanInfo.getJAXXBeanDescriptor().getClassDescriptor().getName()}); + + if (getAutoField()) { + registerAutoFieldBean(tag, compiler, beanInfo); + } + + if (getBeanDescriptor(compiler) != null) { + + // add fieldrepresentation invocations + addFieldRepresentations(tag, compiler); + + // register the validator in compiler + compiler.registerValidator(this); + + } + + return false; + } + + protected void addFieldRepresentations(Element tag, JAXXCompiler compiler) { + for (Entry<String, String> entry : fields.entrySet()) { + String propertyName = entry.getKey(); + String component = entry.getValue(); + if (!checkBeanProperty(compiler, 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); + appendAdditionCode(getJavaCode() + ".setFieldRepresentation(" + keyCode + ", " + component + ");"); + + } + } + + protected void registerAutoFieldBean(Element tag, JAXXCompiler compiler, JAXXBeanInfo beanInfo) { + 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 (fields.containsKey(descriptionName)) { + // already defined in field + continue; + } + if (excludeFields.containsKey(descriptionName)) { + // exclude field + continue; + } + if (!compiler.checkReference(tag, descriptionName, getStrictMode(), null)) { + // no editor component found + continue; + } + // ok add the field mapping + registerField(descriptionName, descriptionName, compiler); + } + + for (Entry<String, String> entry : excludeFields.entrySet()) { + String key = entry.getKey(); + if (fields.containsKey(key)) { + compiler.reportWarning("field '" + key + "' can not be used and excluded at same time ! (field is skipped) for validator " + this); + fields.remove(key); + } + } + } + + public void registerField(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 void registerExcludeField(String id, String component, JAXXCompiler compiler) { + if (excludeFields.containsKey(id)) { + compiler.reportError("duplicate field '" + id + "' for validator " + this); + } else { + if (compiler.getOptions().isVerbose()) { + log.info("add excludeField <" + id + ":" + component + ">"); + } + excludeFields.put(id, component); + } + } + + protected boolean checkBeanProperty(JAXXCompiler compiler, String propertyName) { + + for (JAXXPropertyDescriptor beanProperty : 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 [" + getBean() + "] "); + return false; + } + return true; + } + } + compiler.reportError("could not find the property '" + propertyName + "' on bean [" + getBean() + "] "); + return false; + } + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/ExcludeFieldValidatorHandler.java (from rev 1054, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/ExcludeFieldValidatorHandler.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/ExcludeFieldValidatorHandler.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/ExcludeFieldValidatorHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,85 @@ +/* + * 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 ExcludeFieldValidatorHandler implements TagHandler { + + public static final String TAG = "excludeField"; + 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(ExcludeFieldValidatorHandler.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.debug(tag); + } + + if (!ClassDescriptorLoader.getClassDescriptor(BeanValidator.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { + compiler.reportError(TAG + " tag may only appear within " + BeanValidatorHandler.TAG + " tag but was " + tag); + return; + } + + CompiledBeanValidator info = (CompiledBeanValidator) compiler.getOpenComponent(); + if (!info.getAutoField()) { + compiler.reportError(TAG + " tag can not be used without an 'autoField' validator : " + tag); + return; + } + String name = tag.getAttribute(NAME_ATTRIBUTE); + String component = tag.getAttribute(COMPONENT_ATTRIBUTE); + if (name == null || name.trim().isEmpty()) { + compiler.reportError(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(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 compiled object + if (info.getFields().containsValue(component)) { + compiler.reportError(TAG + " tag found a attribute " + COMPONENT_ATTRIBUTE + " ["+component+"] already used in this validator"); + return; + } + if (info.getExcludeFields().containsValue(component)) { + compiler.reportError(TAG + " tag found a attribute " + COMPONENT_ATTRIBUTE + " ["+component+"] already used in this validator"); + return; + } + // check component exist (again perharps, but let the error knows exactly which tag failed...) + if (compiler.checkReference(tag, component, true, COMPONENT_ATTRIBUTE)) { + // add a field + info.registerField(name, component, compiler); + } + + + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,78 +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 info = (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 compiled object - if (info.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 let the error knows exactly which tag failed...) - if (compiler.checkReference(tag, component, true, COMPONENT_ATTRIBUTE)) { - // add a field - info.registerField(name, component, compiler); - } - - - } - -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java (from rev 1054, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/tags/validator/FieldValidatorHandler.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -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 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(TAG + " tag may only appear within " + BeanValidatorHandler.TAG + " tag but was " + tag); + return; + } + + CompiledBeanValidator info = (CompiledBeanValidator) compiler.getOpenComponent(); + + String name = tag.getAttribute(NAME_ATTRIBUTE); + String component = tag.getAttribute(COMPONENT_ATTRIBUTE); + if (name == null || name.trim().isEmpty()) { + compiler.reportError(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(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 compiled object + if (info.getFields().containsValue(component)) { + compiler.reportError(TAG + " tag found a attribute " + COMPONENT_ATTRIBUTE + " ["+component+"] already used in this validator"); + return; + } + // check component exist (again perharps, but let the error knows exactly which tag failed...) + if (compiler.checkReference(tag, component, true, COMPONENT_ATTRIBUTE)) { + // add a field + info.registerField(name, component, compiler); + } + + + } + +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java (from rev 1042, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/BeanValidatorScopeConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,29 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.types; + +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidator.Scope; + +public class BeanValidatorScopeConverter implements TypeConverter { + + public String getJavaCode(Object object) { + Scope type = (Scope) object; + return BeanValidator.class.getName() + "." + Scope.class.getSimpleName() + "." + type.name(); + } + + public Object convertFromString(String string, Class type) { + if (type != Scope.class) { + throw new IllegalArgumentException("unsupported type: " + type); + } + try { + return Scope.valueOf(string); + } catch (IllegalArgumentException e) { + // do nothing + } + + throw new IllegalArgumentException("unable to convert string '" + string + "' to " + Scope.class); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/ColorConverter.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/ColorConverter.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/ColorConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,35 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.types; - -import java.awt.Color; -import java.lang.reflect.Field; - -public class ColorConverter implements TypeConverter { - public String getJavaCode(Object object) { - Color color = (Color) object; - return "new Color(" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ")"; - } - - - public Object convertFromString(String string, Class type) { - if (type != Color.class) - throw new IllegalArgumentException("unsupported type: " + type); - if (string.length() == 7 && string.charAt(0) == '#') { - return new Color(Integer.parseInt(string.substring(1), 16)); - } else { - try { - Field color = Color.class.getField(string); - return color.get(null); - } - catch (NoSuchFieldException e) { - throw new IllegalArgumentException("colors must be of the form #xxxxxx ('#' followed by six hexadecimal digits), or the name of a constant field in java.awt.Color (found: '" + string + "')"); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/ColorConverter.java (from rev 1005, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/ColorConverter.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/ColorConverter.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/ColorConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,34 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.types; + +import java.awt.Color; +import java.lang.reflect.Field; + +public class ColorConverter implements TypeConverter { + public String getJavaCode(Object object) { + Color color = (Color) object; + return "new Color(" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ")"; + } + + + public Object convertFromString(String string, Class type) { + if (type != Color.class) { + throw new IllegalArgumentException("unsupported type: " + type); + } + if (string.length() == 7 && string.charAt(0) == '#') { + return new Color(Integer.parseInt(string.substring(1), 16)); + } + try { + Field color = Color.class.getField(string); + return color.get(null); + } + catch (NoSuchFieldException e) { + throw new IllegalArgumentException("colors must be of the form #xxxxxx ('#' followed by six hexadecimal digits), or the name of a constant field in java.awt.Color (found: '" + string + "')"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,33 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.types; - -import java.awt.Insets; -import java.util.StringTokenizer; - -public class InsetsConverter implements TypeConverter { - public String getJavaCode(Object object) { - Insets insets = (Insets) object; - return "new Insets(" + insets.top + ", " + insets.left + ", " + insets.bottom + ", " + insets.right + ")"; - } - - - public Object convertFromString(String string, Class type) { - if (type != Insets.class) - throw new IllegalArgumentException("unsupported type: " + type); - StringTokenizer tokenizer = new StringTokenizer(string, ","); - int count = tokenizer.countTokens(); - if (count == 1) { - int i = Integer.parseInt(tokenizer.nextToken().trim()); - return new Insets(i, i, i, i); - } else if (count == 4) { - int[] insets = new int[count]; - for (int i = 0; tokenizer.hasMoreTokens(); i++) - insets[i] = Integer.parseInt(tokenizer.nextToken().trim()); - return new Insets(insets[0], insets[1], insets[2], insets[3]); - } else - throw new IllegalArgumentException("unable to convert string '" + string + "' to Insets"); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java (from rev 1005, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/InsetsConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,36 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.types; + +import java.awt.Insets; +import java.util.StringTokenizer; + +public class InsetsConverter implements TypeConverter { + public String getJavaCode(Object object) { + Insets insets = (Insets) object; + return "new Insets(" + insets.top + ", " + insets.left + ", " + insets.bottom + ", " + insets.right + ")"; + } + + + public Object convertFromString(String string, Class type) { + if (type != Insets.class) { + throw new IllegalArgumentException("unsupported type: " + type); + } + StringTokenizer tokenizer = new StringTokenizer(string, ","); + int count = tokenizer.countTokens(); + if (count == 1) { + int i = Integer.parseInt(tokenizer.nextToken().trim()); + return new Insets(i, i, i, i); + } + if (count == 4) { + int[] insets = new int[count]; + for (int i = 0; tokenizer.hasMoreTokens(); i++) { + insets[i] = Integer.parseInt(tokenizer.nextToken().trim()); + } + return new Insets(insets[0], insets[1], insets[2], insets[3]); + } + throw new IllegalArgumentException("unable to convert string '" + string + "' to Insets"); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,20 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.types; - -import javax.swing.KeyStroke; - -public class KeyStrokeConverter implements TypeConverter { - public String getJavaCode(Object object) { - return "KeyStroke.getKeyStroke(\"" + object.toString() + "\")"; - } - - - public Object convertFromString(String string, Class type) { - if (type != KeyStroke.class) - throw new IllegalArgumentException("unsupported type: " + type); - return KeyStroke.getKeyStroke(string); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java (from rev 1005, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/KeyStrokeConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,21 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.types; + +import javax.swing.KeyStroke; + +public class KeyStrokeConverter implements TypeConverter { + public String getJavaCode(Object object) { + return "KeyStroke.getKeyStroke(\"" + object.toString() + "\")"; + } + + + public Object convertFromString(String string, Class type) { + if (type != KeyStroke.class) { + throw new IllegalArgumentException("unsupported type: " + type); + } + return KeyStroke.getKeyStroke(string); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeConverter.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/TypeConverter.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,11 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.types; - -public interface TypeConverter { - public String getJavaCode(Object object); - - public Object convertFromString(String string, Class type); -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeConverter.java (from rev 1005, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/TypeConverter.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeConverter.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeConverter.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,11 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.types; + +public interface TypeConverter { + String getJavaCode(Object object); + + Object convertFromString(String string, Class type); +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeManager.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/TypeManager.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeManager.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,44 +0,0 @@ -/* - * Copyright 2006 Ethan Nicholas. All rights reserved. - * Use is subject to license terms. - */ -package jaxx.types; - -import java.util.HashMap; -import java.util.Map; - -public class TypeManager { - private static Map<Class, TypeConverter> converters = new HashMap<Class, TypeConverter>(); - - private TypeManager() { /* not instantiable */ } - - - public static void registerTypeConverter(Class type, TypeConverter converter) { - converters.put(type, converter); - } - - - public static TypeConverter getTypeConverter(Class type) { - return converters.get(type); - } - - - public static String getJavaCode(Object object) { - if (object == null) - return "null"; - else { - TypeConverter converter = getTypeConverter(object.getClass()); - if (converter == null) - throw new IllegalArgumentException("unsupported type: " + object.getClass()); - return converter.getJavaCode(object); - } - } - - - public static Object convertFromString(String string, Class type) { - TypeConverter converter = getTypeConverter(type); - if (converter == null) - throw new IllegalArgumentException("unsupported type: " + type); - return converter.convertFromString(string, type); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeManager.java (from rev 1005, lutinjaxx/trunk/jaxx-core/src/main/java/jaxx/types/TypeManager.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeManager.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/main/java/jaxx/types/TypeManager.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,45 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ +package jaxx.types; + +import java.util.HashMap; +import java.util.Map; + +public class TypeManager { + private static Map<Class, TypeConverter> converters = new HashMap<Class, TypeConverter>(); + + private TypeManager() { /* not instantiable */ } + + + public static void registerTypeConverter(Class type, TypeConverter converter) { + converters.put(type, converter); + } + + + public static TypeConverter getTypeConverter(Class type) { + return converters.get(type); + } + + + public static String getJavaCode(Object object) { + if (object == null) { + return "null"; + } + TypeConverter converter = getTypeConverter(object.getClass()); + if (converter == null) { + throw new IllegalArgumentException("unsupported type: " + object.getClass()); + } + return converter.getJavaCode(object); + } + + + public static Object convertFromString(String string, Class type) { + TypeConverter converter = getTypeConverter(type); + if (converter == null) { + throw new IllegalArgumentException("unsupported type: " + type); + } + return converter.convertFromString(string, type); + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/main/resources/icons (from rev 1042, lutinjaxx/trunk/jaxx-core/src/main/resources/icons) Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/BeanValidator.rst (from rev 1017, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/BeanValidator.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/BeanValidator.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/BeanValidator.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,179 @@ +------------- +BeanValidator +------------- + +.. contents:: + + +Présentation +============ + +Ajout du support de validation dans JAXX. + +La techonologie utilisée est celle de Struts 2 (XWorks 2). + + +Configuration +============= + +La configuration des validateurs se font via des fichier xml (on peut aussi utiliser des annotations,...). + +Ajout d'un validateur +********************* + +Pour enregister un nouveau validateur sur un bean, il suffit de placer dans le même paquetage que le bean un fichier *XXX-validation.xml* où XXX est le nom non qualifié du bean. + +On peut de plus affecter un context de validation, dans ce cas le fichier doit s'appeler *XXX-YYY-validation.xml*, où YYY est le nom du context de validation. + +Ainsi on peut valider de différentes manières un bean (par exemple selon son cycle de vie :création, modification, ...). + +Ajout d'un nouveau type de validateur +************************************* + +Il est aussi possible de définir de nouveau type de validateurs : + + * créer une classe qui étend FieldValidator + * ajouter un fichier validators.xml (ou ajouter dans un tel fichier la définition du nouveau validator) à la racine du class-path. + +I18n +**** + +Afin de rendre le mécanisme multi-langue, on propose dans les fichiers de validations d'utiliser des clef i18n pour les messages. + +Un nouveau parseur dans notre plugin i18n a été ajouté pour détecter ces clefs. (*maven-i18n-plugin:0.7:parserValidation*) + + +Intégration dans JAXX +===================== + +Deux nouveaux tags ont été conçus pour pouvoir décrire un validateur dans les fichiers JAXX. + +Ce développement est dans le paquetage *jaxx.tags.validator*. + +tag BeanValidator +***************** + +Permet de définir un nouveau validateur dans une classe JAXX. + +Les attributs autorisés sont les suivants : + + * *id* : le nom du validateur + + * *bean* : l'id d'un bean connu par la classe JAXX. On ne peut pas utiliser ici une expression car on n'est pas sûr de pouvoir déterminer le type de cette expression pendant le parsing ? (a verifier). + + * *beanClass* : le FQN de classe du bean à valider. Peut-être non présent si l'attribut *bean* est renseigné. + + * *beanInitializer* : une expression pour initialiser le bean à valider. TODO a revoir : on devrait utiliser uniquement un seul attribut *bean*... + + * *contextName* : le nom du contexte de validation. + + * *autoField* : flag pour indiquer l'inscription implicite des validateurs de champs du bean. Pour ce faire on parcourt l'ensemble des champs du bean et on ne considère uniquement ceux dont on connait dans la classe JAXX un composent d'édition du champ (id=nom du champ). Il est possible de surcharger ce configuration implicite en rajoutant explicitement des champs (voir le tag *field*). + + * *errorList* : le composant graphique pour afficher la liste des erreurs, doit étendre *javax.swing.JList*. Si non présent, on essayera le component d'id *errorList*. + + * *errorListModel* : le modèle qui contient la liste des erreurs (et est liée au composant *errorList*), doit étendre *jaxx.runtime.validator.BeanValidatorErrorListModel*. Si non présent on essayera le composent d'id *errorListModel*. + + * *uiClass* : le FQN de la classe utilisé pour le rendu des erreurs sur les wigets d'édition. La classe doit étendre *jaxx.runtime.validator.ui.AbstractBeanValidatorUI*. Si non présent, on utilise par défaut le render *jaxx.runtime.validator.ui.IconValidationUI*. + + +Le tag supporte aussi l'ajout de tag *field* comme fils pour définir explicitement des champs à validater. + +tag field +********* + +Le tag *field* définit une entrée dans le validateur, on définit une correspondance entre le champ à valider et le composant d'édition de ce champ. + +Le tag supporte les attributs suivants : + + * *name* : le nom de la propriété du bean associée. + Cet attribut est obligatoire. + + * *component* : l'id du composant graphique d'édition associé à la propriété du bean. + Cet attribut peut être omis si le nom de la propriété du bean est identique à celui du composent graphique d'édition. + + +Les classes du runtime +====================== + +Ce développement est dans le paquetage *jaxx.runtime.validator* (sauf pour l'interface *jaxx.runtime.JAXXValidator*). + +Il s'agit de l'ensemble des classes ajoutées dans le module *jaxx-core* pour encapsuler la validation dans les fichiers java générés à partir des fichiers JAXX. + + +interface jaxx.runtime.JAXXValidator +************************************ + +Ce contrat a été ajouté à tous les objets JAXX générés (donc l'interface JAXXObject étend JAXXValidator). + +On définit ici uniquement des méthodes d'accès aux validateurs enregistrés dans le JAXXObject. + +TODO on pourrait ajouter des méthodes pour savoir l'état de validation d'un validateur ? + + +classe jaxx.runtime.validator.BeanValidator +******************************************* + +Il s'agit de la classe principale d'encapsulation d'un validateur XWorks 2. + +Le principe est simple : le validateur écoute les modifications sur le bean associé et revalide le bean à chaque modification. La validation met à jour la liste des erreurs asociées. + +On se base sur les PropertyChangeListener pour écouter les modification des beans. Il faut donc que les beans supporte ces listeners. + +Pour les entités de ToPIA, il suffit de positionner un contexte (topia) au bean pour profiter des listeners liés. + +Pour les DTO de ToPIA, les générateurs ont été modifiés pour gérer ce support. + +Les méthodes à retenir sont : + + * *setBean* pour affecter un bean au validateur (pour déasactiver passer null). Lors de la désactivation d'un bean, les erreurs associés sont retirées de la liste des erreurs. + + * *setContextName* pour affecter un nouveau nom de context de validation (par défaut on utilise pas de context de validation). + + * *validate* pour lancer une validation sur le bean liée (ne sera opérant uniquement si un bean est liée et qu'une liste d'erreur est liée). + + * *isValid* pour connaitre l'état du validateur à un moment donné. + +Normalement la méthode *validate* ne devrait pas être appelée directement. : elle est automatiquement invoquée lorsqu'une propriété du bean est modifiée. + +classe jaxx.runtime.validator.BeanValidatorError +************************************************ + +Modélisation d'une erreur renvoyé par le validateur, on conserve ici : + + * le validateur qui a provoqué l'erreur + + * la propriété du bean en faute + + * le composent graphique d'édtion de la propriété + +classe jaxx.runtime.validator.BeanValidatorErrorListModel +********************************************************* + +Le modèle de la liste des erreurs renvoyées par le validateur. Il s'agit d'une extension d'un *javax.swing.DefaultListModel* qui permet de gérer une liste d'erreurs provenant de plusieurs validateurs en même temps. + +classe jaxx.runtime.validator.ErrorListMouseListener +**************************************************** + +Un listener écoutant les double clics sur une liste d'erreurs et qui donne le focus au composent graphique d'édition associée à la propriété dont l'erreur est sélectionné. + + +Les conversions +=============== + +Pour l'édition de proriétés qui ne sont pas des chaines de caractères, des erreurs de conversions peuvent survenir (conversion de la valeur de l'édtieur graphique vers le bean), avant que l'on utilise +réellement la mécanique de la validation. + +Pour palier à ce problème on a intégré la gestion des erreurs de conversion dans le validateur. +Pour ce faire, il suffit de faire appel à la méthode suivante pour injecter dans un bean une propriété : + + :: + + jaxx.runtime.Util.convert(validator,"nomDeLaPropriété",widget.getText(),TypeDeLaProriete.class); + + +On obtiendra si une erreur de conversion intervient, une erreur dont le libellé est de la forme *error.convertor.XXX* +où XXX est nom simple en minuscule du type de la propruité. (par exemple : *error.convertor.integer*). + + + + Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/I18n.rst (from rev 1017, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/I18n.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/I18n.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/I18n.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,56 @@ +---- +I18n +---- + +.. contents:: + + +Présentation +============ + +Ajout du support i18n dans JAXX. + +On utilise la système i18n développé dans la librairie des lutins (*lutinlib*). + +Configuration +============= + +Une option a été ajoutée dans le plugin maven de JAXX : *i18nable* pour permettre ou non l'utilisation de ce système. + +Par défaut, l'option est active (donc aucune configuration supplémentaire n'est nécessaire pour utiliser i18n dans JAXX). + + +Fonctionnement +============== + +Le fonctionnement est simple : lors de la compilation JAXX, lorsque l'on rencontre certains attributs on encapsule la +valeur de l'attribution par un appel à la méthode + +:: + + org.codelutin.i18n.I18n._(String) + + +La liste des attributs en question sont les suivants : + + - title + - text + - toolTipText + + +Ensuite l'utilisation du *parserJava* du plugin i18n permet la détection des clefs i18n. + + +Pourquoi ne plus utiliser l'ancien parserJaxx du plugin i18n +============================================================ + +Un parseur avait été développé initialement pour détecter dans les fichiers JAXX (*parserJaxx*), les appels à la méthode de traduction +i18n dans les attributs. + +Ce parseur n'est plus d'actualité car on ne doit plus avoir d'appel explicite à cette méthode dans les fichiers JAXX. + +De plus, même sans avoir mis en place le mécanisme i18n dans JAXX, ce parseur n'était plus d'actualité : il se base +sur une liste prédéfinie d'attributs xml à scanner pour détecter des appels i18n; ce qui n'était pas acceptable à terme +car si on ajoute un nouveau composent dans JAXX, le plugin i18n n'est pas capable de détecter les nouvelles clefs. + +Donc on préconise l'utilisation du *parserJava* du plugin i18n qui lui est capable de détecter tous les appels i18n. Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Interface.rst (from rev 1017, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/Interface.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Interface.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Interface.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,38 @@ +--------- +Interface +--------- + +.. contents:: + + +Présentation +============ + +Ajout de contrats sur le code généré dans JAXX. + +Mécanisme +========= + +Le compilateur JAXX génère des classes à partir de fichiers JAXX mais n'est pas capable d'ajouter des contrats sur +les objets générés, donc interdit en quelque sorte la programmation par contrat. + +Pour palier à cette limitation, on a ajouté un attribut spécial *implements*. + +Cette attribut ne doit être placé que sur le tag racine d'un fichier JAXX et son contenu est le nom qualifié d'un ou +plusieurs contrats séparaés par des virgules. + +:: + + <JPanel implements='java.lang.Comparable'> + + <script>public int compareTo(JPanel o) { return getName().compareTo(o.getName()); }</script> + + </JPanel> + +La classe générée aura bien le contrat *java.lang.Comparable*. + +TODO +==== + +Il serait intéressant lors de l'injection de contrats sur un objet jaxx de pouvoir vérifier si toutes les méthodes du +contrat sont bien implantées dans la classe, et si ce n'est pas le cas de rendre la classe abstraite. Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JAXXContext.rst (from rev 1017, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/JAXXContext.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JAXXContext.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JAXXContext.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,161 @@ +----------- +JAXXContext +----------- + +.. contents:: + + +Présentation +============ + +Ajout d'un context applicatif dans JAXX. + +Le besoin initial de ce développement est de pouvoir facilement intégrer un context applicatif dans JAXX et de pouvoir +l'utiliser dans les fichiers JAXX pour injecter par exemple des données dans les widgets. + +jaxx.runtime.JAXXContext +======================== + +Il s'agit du contrat de base du context applicatif. + +Les entrées dans le context +*************************** + +Chaque donnée utilisable dans le context est caractérisée par deux propriétés : + + * la type de l'objet + + * un nom (facultatif) associé à la donnée + +Le type de l'objet correspondant en fait à la classe de la donnée. + +Le nom qui est facultatif permet de pouvoir distinguer plusieurs données d'un même type dans le context. Si le nom +n'est pas utilisé pour caractériser une données on fixera alors sa valeur à *null*. + +Afin de pouvoir caractériser les entrées dans le context, une classe a été définie *jaxx.runtime.JAXXContextEntryDef*. + +Les méthodes de lecture +*********************** + +On a définit deux méthodes de lecture de données dans le context : + + * *getContextValue(Class)* récupère la donnée *non nommée* dont le type correspond à celui passé. + + * *getContextValue(Class,String)* récupère la donnée nommé dont le type correspond à celui passé. + +Les méthodes d'écriture +*********************** + +On a définit quatre méthodes d'écriture de données dans le context : + + * *setContextValue(Object)* enregistre dans le context la donnée *non nommée*. + + * *setContextValue(Object,String)* enregistre dans le context la donnée *nommée*. + + * *removeContextValue(Class)* supprime du context, la donnée *non nommée* dont le type est passé. + + * *removeContextValue(Class, String)* supprime du context, la donnée *nommée* dont le type est passé. + +Afin de pouvoir assurer une cohérence dans le context, chaque injection de donnée, sera toujours précédée par une +suppression d'un éventuellement ancienne valeur qui aurait la même définition d'entrée. + +L'héritage +********** + +Il est possible d'avoir une hériarchie de context qui s'enchaînent. Ce mécanisme a été mis en place pour répondre à un +besion précis : chaque fichier JAXX donne lieu à une nouvelle classe qui possède son propre context. + +On peut avoir des fichiers JAXX qui utilisent d'autres fichiers JAXX, il faut donc être capable de lier le context du +composent parent avec ses fils. + +La mise en place de l'héritage est transparente pour l'utilisateur : aucune méthode supplémentaire n'est requise. + +Les implantations de context +============================ + +jaxx.runtime.DefaultJAXXContext +******************************* + +Il s'agit de l'implantation par défaut utilisée par les objects *JAXXObject* (objets générés). + +A noter que pour les opérations d'injection ou de suppression, on effectuera les opérations sur le context qui contient +réellement la donnée, ce qui est important pour conserver la cohérence des contexts dans les contexts chaînés. + +Pour traiter le context parent, aucune méthode publique supplémentaire n'a été rajoutée, il suffit d'injecter un objet +de type *JAXXContext* *non nommé* qui le context courant qui sera détecté comme une entrée de type context. + +Cette entrée spéciale ne sera pas stockée avec les autres entrées afin d'optimiser les algorithmes d'injection et de +restitution. + +jaxx.runtime.JAXXInitialContext +******************************* + +On a implanté un second type de context qui lui peut servir à l'initialisation des JAXXObject. + +Ce second type de context ajoute des méthodes pour préparer le context avant l'instanciation des JAXXObject. + +Ce context admet certaine limitation (pas de suppression dans le context), et apporte trois nouvelles méthodes : + + * add(Object) : injecte dans le context une entrée non nommée et retourne l'instance du context. + + * add(String,Object) : injecte dans le context une entrée nommé et retourne l'instance du context. + + * to(JAXXContext) : injecte dans le context passé toutes les entrée du context. + +Les méthodes *add* peuvent être chaînées comme dans l'exemple suivant : + +:: + + JAXXInitialContext context = new JAXXInitialContext().add("string").add(0).add("currentDate",new Date()); + + +Intégration dans les JAXXObject +=============================== + +Le traitement d'un fichier JAXX donne lieu à une classe qui possède le contrat *jaxx.runtime.JAXXObject*. + +Ce contrat hérite donc du contrat *JAXXContext* (afin de pouvoir l'utiliser de manière transparente dans les fichiers JAXX). + +Afin de simplifier la génération et les évolutions du context indépendemment des évolutions des JAXXObject, on utilise +un pattern de délégation au sein des object générés. + +Paramétrage de l'implantation du context +**************************************** + +Une propriété a été rajoutée sur le plugin JAXX, afin de pouvoir préciser l'implantation de context à utiliser : + +:: + + jaxx.jaxxContextImplementorClass + +Il s'agit du nom qualifié de la classe d'implantation à utiliser. + +Par défaut, si rien n'est renseigné, on utilisera un *jaxx.runtime.DefaultJAXXContext*. + + +Initialisation d'un JAXXObject +****************************** + +Un nouveau constructeur a été ajouté dans les JAXXObjet générés afin de pouvoir facilement initialisé un tel objet à +partir d'un context parent, son unique paramètre est le context parent. Ce constructeur est capable de différencer le +type de context passé : + + * s'il s'agit d'un *JAXXInitialContext*, on recopie alors dans le context réel de l'objet toutes les entrées du context passé. + + * sinon le context passé est simplement injecté dans le context de l'objet (et donc sera utilisé comme le context parent de celui de l'objet). + +Voici un exemple d'initialisation d'un JAXXObject : + +:: + + java.util.Date currentDate = new java.util.Date(); + JAXXInitialContext context = new JAXXInitialContext().add("string").add(0).add("currentDate",currentDate); + JAXXObject ui = new MyUI(context); + + assert "string".equals(myUI.getContextValue(String.class)); + assert 0 == myUI.getContextValue(Integer.class); + assert currentDate.equals(myUI.getContextValue(java.util.Date.class,"currentDate")); + +A noter, que l'initialisation du context d'un *JAXXObject* sera toujours effectuée avant la méthode *$initialize* générée +par le compilateur JAXX, ce qui permet de pouvoir utiliser le context pour l'initialisation des widgets dans les fichiers JAXX. + Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JavaBean.rst (from rev 1017, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/JavaBean.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JavaBean.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/JavaBean.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,50 @@ +-------- +JavaBean +-------- + +.. contents:: + + +Présentation +============ + +Ajout du support complêt des javaBean dans JAXX. + +Mécanisme +========= + +Il est possible dans JAXX de rajouter des objets quelconques via leur nom qualifié de classe : + +:: + + <JPanel> + <java.lang.Boolean id='myState' constructorParams='true'/> + <JLabel text='text' visible='{isMySate()}'/> + </JPanel> + +Avant l'ajout de la fonctionnalité, le code généré possèdait : + + * une propriété en lecture seul nommé *myState*. + +Aucun support javaBean n'était présent et le databinding sur la propriété *visible* du label n'est pas créé. Cela veut +dire que le label sera initialisé avec la valeur initiale du boolean et c'est tout... + +Avec l'ajout du support javaBean, on peut maintenant faire ces bindings, pour ce faire il suffit d'ajouter un attribut +*javaBean* sur l'objet : + +:: + + <JPanel> + <java.lang.Boolean id='myState' constructorParams='true' javaBean='anyValue'/> + <JLabel text='text' visible='{isMySate()}'/> + </JPanel> + +On aura donc en plus : + + * un mutateur sur la propriété *myState* qui déclanchera l'envoie d'un *PropertyChange* sur la propriété lors de modification de valeur. + +Ainsi le compilateur JAXX sera capable d'enregistrer un novueau dataBindig sur la propriété *visible* du label et la +modification de l'état *myState* sera automatiquement répercuté sur la propriété. + + + Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/NavigationTreeModel.rst (from rev 1044, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/NavigationTreeModel.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/NavigationTreeModel.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/NavigationTreeModel.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,168 @@ +------------------- +NavigationTreeModel +------------------- + +.. contents:: + + +Présentation +============ + +Ajout d'un modèle d'arbre de navigation. + +Le but de cette fonctionnalité est de pouvoir créer un arbre de navigation lié au context de JAXX, de définir des UI +rattachés à chaque noeud. + +Le développement est effectué dans le paquetage *jaxx.runtime.swing.navigation*. + +jaxx.runtime.swing.navigation.NavigationTreeModel +================================================= + +Il s'agit du modèle de l'arbre utilisé, c'est une extension d'un *javax.swing.tree.DefaultTreeModel*. + +Les noeuds présents dans ce modèle sont aussi typés en *jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode*. + +L'idée principale est de pouvoir associé à un noeud précis un chemin depuis la racine, ce que l'on appele *chemin de navigation*. + +Pour obtenir le chemin de navigation d'un noeud donné, on récupère l'enmseble des neoud depuis la racine vers ce noeud +et les concatène en suffixant par le caractère séparateur défini. + +Définition d'un noeud +===================== + +Le noeud (*jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode*) est une extension d'un *javax.swing.tree.DefaultMutableTreeNode*. + +Il apporte les nouvelles propriétés suivantes : + + * *navigationPAth* : nom de chemin de navigation de ce noeud. + + * *jaxxClass* : nom qualifié de la classe d'ui associé à ce noeud (doit être obligatoirement un *JAXXObject*) + + * *jaxxActionClass* : nom qualifié de la classe d'handler d'ui associé à ce noeud (doit être obligatoirement un *JAXXAction*). + + * *jaxxContextEntryDef* : définition de l'entrée dans le context JAXX associé à ce noeud. + + * *jaxxContextEntryJXPath* : définition d'une expression JXPath à appliquer sur le bean associé au noeud. + + +Retrouver un noeud à partir du chemin de navigation +*************************************************** + +Il est possible en connaissant le chemin de navigation d'un noued de récupérer le noeud dans l'arbre via la méthode + +:: + + model.findNode("chemin.de.navigation") + +Trouver la valeur associée dans le context JAXX à partir du chemin de navigation +******************************************************************************** + +Il est possible en connaissant le chemin de navigation d'un noued de récupérer la valeur associée dans le context JAXX. + +:: + + model.getJAXXContextValue(myJAXXContext, "chemin.de.navigation")* . + +L'algrotihme est le suivant : + + * récupération du noeud associé au chemin de navigation + + * recherche du premier noeud (dans les noeuds qui remontent vers la racine de l'arbre) dont la propriété *jaxxContextEntry* est non nulle, il s'agit du point d'entré dans le context JAXX. + + * redescendre à partir de ce noeud vers le noeud d'origine (si ce noeud était différent) et en descendant conjointement dans l'objet du context JAXX : + + - on utilise l'expression JXPath pour obtenir l'objet associé au noeud + +Exemple : + +:: + + "$root" + <-- la racine de l'abre + | + + "string" <-- attaché au context JAXX <java.lang.String,"string"> + | + + "liste" + <-- attaché au context JAXX <java.util.List.class,"liste"> + | | + | + "0" <-- le premier élément de la liste + | | + | + "1" <-- le second élément de la liste + | | + | + "2" <-- le troisième élément de la liste + | + + "locale" + <-- attaché au context JAXX <java.util.Locale> + | + + country + | + + language + + // preparation du context + java.util.List myList = java.util.Arrays.asList("one","two","three"); + java.util.Locale myLocale = java.util.Locale.FRENCH; + context.setContextValue(myList, "liste"); + context.setContextValue("stringValue","string"); + context.setContextValue(myLocale); + + + // récupération des valeurs dans le context à partir de chemin de navigation + assert model.getJAXXContextValue(context, "$root") == null; + assert model.getJAXXContextValue(context, "$root.string") == "stringValue"; + assert model.getJAXXContextValue(context, "$root.liste") == myList; + assert model.getJAXXContextValue(context, "$root.liste.0") == "one"; + assert model.getJAXXContextValue(context, "$root.liste.1") == "two"; + assert model.getJAXXContextValue(context, "$root.liste.2") == "three"; + assert model.getJAXXContextValue(context, "$root.locale") == myLocale; + assert model.getJAXXContextValue(context, "$root.locale.country") == myLocale.getCountry(); + assert model.getJAXXContextValue(context, "$root.locale.language") == myLocale.getLanguage(); + +TODO mettre à jour cet exemple suite à l'utilisation de JXPath pour naviguer dans les objets. + +A noter qu'une seconde méthode de récupération de valeur du context JAXX est disponible pour pouvoir récupérer cette +valeur en connaissant le noeud : + +:: + + model.getJAXXContextValue(context, myNode); + +jaxx.runtime.swing.navigation.NavigationTreeSelectionAdapter +============================================================ + +Il s'agit d'un listener sur la sélection d'un noeud dans l'arbre de navigation basé sur notre modèle de navigation. Il +étend *javax.swing.event.TreeSelectionListener*. + +Ce listener contient la gestion de passage d'un noeud à un autre avec interaction avec le context JAXX et affichage automatique de l'ui associé au noeud sélectionné. + +**Attention : la mécanique ne fonctionne que pour un arbre à selection unique.** + +Algorithme +********** + +Voici l'algorithme utilisé lors de la sélection d'un nouveau noeud : + + * *closeUI* : tentative de fermeture de l'ui lié au noeud précédemment selectionné, si cela n'aboutit pas on retourne sur le noeud précédent. + + * *attachBeanFromNodeToContext* : injection dans le context JAXX de la valeur associée au nouveau noeud + + * *createUI* : création de la nouvelle ui (si elle n'existe pas) + + * *openUI* : ouverture de la nouvelle ui + +Si une erreur survient lors de ces opérations, on entre dans la méthode *goBackToPreviousNode* qui est abstraite et permet de notifier les erreur de retourner au noeud précdent. + +jaxx.runtime.swing.navigation.NavigationTreeSelectionAdapterWithCardLayout +************************************************************************** + +Il s'agit d'une implantation du listener précédent qui suppose que les uis associées aux noeuds sont affichées dans un +unique container en utilisant le layout *jaxx.runtime.swing.CardLayout2*. + +La contrainte de chaque ui sera extactement le chemin de navigation du noeud associé. + +Il possède deux méthodes abstraites : + + * *getContentContainer* : qui indique le container d'ui. + + * *getContentLayout* : qui indique le layout utilisé. + +Pour pouvoir utilisé cet *adapter*, il vous suffit de définir la méthode suivante (en plus des deux méthodes abstraites) : + + * *goBackToPreviousNode* : comment gérer les erreurs et retourner au noeud précedent. + Deleted: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Todo.rst =================================================================== --- lutinjaxx/trunk/jaxx-core/src/site/fr/rst/Todo.rst 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Todo.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,4 +0,0 @@ -TODO -==== - -a faire \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Todo.rst (from rev 1017, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/Todo.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Todo.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/Todo.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,15 @@ +==== +TODO +==== + + - réorganiser ce module maven en deux modules : + + * un premier module de runtime + + * un second module contenant uniquement le compilateur et non nécessaire au runtime. + + Le second module pourrait être facultatif et le code pourrait directement être placé dans le module du plugin. + + Cependant cela n'est pas possible actuelement car certains objets du runtime contiennent aussi du code utilisé + par le compilateur JAXX (par exemple StyleSheet). Il faut avant tout cloisonner le code non runtime. + \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/index.rst =================================================================== --- lutinjaxx/trunk/jaxx-core/src/site/fr/rst/index.rst 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/index.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,13 +0,0 @@ -jaxx-core -========= - -.. contents:: - - -Présentation ------------- - -Le compilateur Jaxx TODO - -**Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes -librairies.** Copied: lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/index.rst (from rev 1017, lutinjaxx/trunk/jaxx-core/src/site/fr/rst/index.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/index.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/site/fr/rst/index.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,41 @@ +jaxx-core +========= + +.. contents:: + + +Présentation +------------ + +Le compilateur Jaxx TODO + +**Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes +librairies.** + +Nouvelles fonctionnalités +------------------------- + + * I18n_ + + * JAXXContext_ + + * BeanValidator_ + + * NavigationTreeModel_ + + * JavaBean_ + + * Interface_ + + +.. _I18n: I18n.html + +.. _JAXXContext: JAXXContext.html + +.. _BeanValidator: BeanValidator.html + +.. _NavigationTreeModel: NavigationTreeModel.html + +.. _Javabean: JavaBean.html + +.. _Interface: Interface.html \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java (from rev 1042, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/BeanValidatorScopeConverterTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,46 @@ +package jaxx.junit; + +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidator.Scope; +import jaxx.types.BeanValidatorScopeConverter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class BeanValidatorScopeConverterTest { + + BeanValidatorScopeConverter converter; + Scope value; + String strValue; + + @Before + public void before() { + converter = new BeanValidatorScopeConverter(); + } + + @Test + public void testConvertFromString() { + value = (Scope) converter.convertFromString("ERROR", Scope.class); + Assert.assertEquals(value, Scope.ERROR); + + value = (Scope) converter.convertFromString("WARNING", Scope.class); + Assert.assertEquals(value, Scope.WARNING); + } + + @Test + public void testGetJavaCode() { + value = Scope.ERROR; + strValue = converter.getJavaCode(value); + Assert.assertEquals(BeanValidator.class.getName() + "." + Scope.class.getSimpleName() + "." + value.name(), strValue); + + value = Scope.WARNING; + strValue = converter.getJavaCode(value); + Assert.assertEquals(BeanValidator.class.getName() + "." + Scope.class.getSimpleName() + "." + value.name(), strValue); + } + + @Test(expected = IllegalArgumentException.class) + public void testConvertFromStringError() { + converter.convertFromString("FAKE", Scope.class); + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,50 +0,0 @@ -package jaxx.junit; - -import java.awt.*; -import junit.framework.TestCase; - -import jaxx.reflect.*; - -public class ClassDescriptorTest extends TestCase { - public void testBuiltInClassName() throws ClassNotFoundException, NoSuchMethodException { - ClassDescriptor object = ClassDescriptorLoader.getClassDescriptor("java.lang.Object"); - MethodDescriptor toString = object.getMethodDescriptor("toString", new ClassDescriptor[0]); - assertEquals(toString.getName(), "toString"); - assertEquals(toString.getParameterTypes().length, 0); - - MethodDescriptor equals = object.getMethodDescriptor("equals", new ClassDescriptor[] { object }); - assertEquals(equals.getName(), "equals"); - assertEquals(equals.getParameterTypes().length, 1); - assertEquals(equals.getParameterTypes()[0], object); - } - - - public void testBuiltInClass() throws ClassNotFoundException, NoSuchMethodException { - ClassDescriptor object1 = ClassDescriptorLoader.getClassDescriptor("java.lang.Object"); - ClassDescriptor object2 = ClassDescriptorLoader.getClassDescriptor(Object.class); - assertEquals(object1, object2); - } - - - public void testUserClassName() throws ClassNotFoundException, NoSuchMethodException { - ClassDescriptor me = ClassDescriptorLoader.getClassDescriptor("jaxx.junit.ClassDescriptorTest", getClass().getClassLoader()); - MethodDescriptor testUserClassName = me.getMethodDescriptor("testUserClassName", new ClassDescriptor[0]); - assertEquals(testUserClassName.getName(), "testUserClassName"); - assertEquals(testUserClassName.getParameterTypes().length, 0); - } - - - public void testWrongCase() { - try { - ClassDescriptor object = ClassDescriptorLoader.getClassDescriptor("jaxx.junit.classdescriptortest", getClass().getClassLoader()); - fail("Found descriptor using wrong case: " + object); - } - catch (ClassNotFoundException e) { } - } - - - public void testArrays() throws ClassNotFoundException { - ClassDescriptor intArray = ClassDescriptorLoader.getClassDescriptor(int[].class); - ClassDescriptor objectArray = ClassDescriptorLoader.getClassDescriptor(Object[].class); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java (from rev 1052, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ClassDescriptorTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,65 @@ +package jaxx.junit; + +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.reflect.MethodDescriptor; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import org.junit.Test; + +public class ClassDescriptorTest { + + @Test + public void testGetClassDescriptor() throws Exception { + ClassDescriptor object = ClassDescriptorLoader.getClassDescriptor("jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode"); + + + } + + @Test + public void testBuiltInClassName() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor object = ClassDescriptorLoader.getClassDescriptor("java.lang.Object"); + MethodDescriptor toString = object.getMethodDescriptor("toString", new ClassDescriptor[0]); + assertEquals(toString.getName(), "toString"); + assertEquals(toString.getParameterTypes().length, 0); + + MethodDescriptor equals = object.getMethodDescriptor("equals", new ClassDescriptor[]{object}); + assertEquals(equals.getName(), "equals"); + assertEquals(equals.getParameterTypes().length, 1); + assertEquals(equals.getParameterTypes()[0], object); + } + + @Test + public void testBuiltInClass() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor object1 = ClassDescriptorLoader.getClassDescriptor("java.lang.Object"); + ClassDescriptor object2 = ClassDescriptorLoader.getClassDescriptor(Object.class); + assertEquals(object1, object2); + } + + @Test + public void testUserClassName() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor me = ClassDescriptorLoader.getClassDescriptor("jaxx.junit.ClassDescriptorTest", getClass().getClassLoader()); + MethodDescriptor testUserClassName = me.getMethodDescriptor("testUserClassName", new ClassDescriptor[0]); + assertEquals(testUserClassName.getName(), "testUserClassName"); + assertEquals(testUserClassName.getParameterTypes().length, 0); + } + + @Test(expected = ClassNotFoundException.class) + public void testWrongCase() throws ClassNotFoundException { + //try { + //ClassDescriptor object = + ClassDescriptorLoader.getClassDescriptor("jaxx.junit.classdescriptortest", getClass().getClassLoader()); + // fail("Found descriptor using wrong case: " + object); + //} + //catch (ClassNotFoundException e) { + //} + } + + @Test + public void testArrays() throws ClassNotFoundException { + ClassDescriptor intArray = ClassDescriptorLoader.getClassDescriptor(int[].class); + assertNotNull(intArray); + ClassDescriptor objectArray = ClassDescriptorLoader.getClassDescriptor(Object[].class); + assertNotNull(objectArray); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,59 +0,0 @@ -package jaxx.junit; - -import java.awt.*; -import junit.framework.TestCase; - -import jaxx.types.*; - -public class ColorConverterTest extends TestCase { - private ColorConverter converter; - - public void setUp() { - converter = new ColorConverter(); - } - - - public void testHexValue() { - Color value = (Color) converter.convertFromString("#3000FF", Color.class); - assertEquals(value, new Color(48, 0, 255)); - } - - - public void testUpperCaseConstant() { - Color value = (Color) converter.convertFromString("RED", Color.class); - assertEquals(value, Color.RED); - } - - - public void testLowerCaseConstant() { - Color value = (Color) converter.convertFromString("blue", Color.class); - assertEquals(value, Color.blue); - } - - - public void testMissingHash() { - try { - Color value = (Color) converter.convertFromString("ABCDEF", Color.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } - - - public void testInvalidNumber() { - try { - Color value = (Color) converter.convertFromString("#ABCDEG", Color.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } - - - public void testInvalidConstant() { - try { - Color value = (Color) converter.convertFromString("rEd", Color.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ColorConverterTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,51 @@ +package jaxx.junit; + +import jaxx.types.ColorConverter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.awt.Color; + +public class ColorConverterTest { + + ColorConverter converter; + + @Before + public void setUp() { + converter = new ColorConverter(); + } + + @Test + public void testHexValue() { + Color value = (Color) converter.convertFromString("#3000FF", Color.class); + Assert.assertEquals(value, new Color(48, 0, 255)); + } + + @Test + public void testUpperCaseConstant() { + Color value = (Color) converter.convertFromString("RED", Color.class); + Assert.assertEquals(value, Color.RED); + } + + @Test + public void testLowerCaseConstant() { + Color value = (Color) converter.convertFromString("blue", Color.class); + Assert.assertEquals(value, Color.blue); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingHash() { + converter.convertFromString("ABCDEF", Color.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidNumber() { + converter.convertFromString("#ABCDEG", Color.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidConstant() { + converter.convertFromString("rEd", Color.class); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,62 +0,0 @@ -package jaxx.junit; - -import java.awt.*; -import junit.framework.TestCase; - -import jaxx.types.*; - -public class InsetsConverterTest extends TestCase { - private InsetsConverter converter; - - public void setUp() { - converter = new InsetsConverter(); - } - - - public void testSingleValue() { - Insets value = (Insets) converter.convertFromString("3", Insets.class); - assertEquals(value, new Insets(3, 3, 3, 3)); - } - - - public void testFourValues() { - Insets value = (Insets) converter.convertFromString("3, 0, 12, 1000000", Insets.class); - assertEquals(value, new Insets(3, 0, 12, 1000000)); - } - - - public void testTwoValues() { - try { - Insets value = (Insets) converter.convertFromString("0, 4", Insets.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } - - - public void testThreeValues() { - try { - Insets value = (Insets) converter.convertFromString("0, 4, 9", Insets.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } - - - public void testInvalidNumber() { - try { - Insets value = (Insets) converter.convertFromString("0, 4, 9, A", Insets.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } - - - public void testBadFormatting() { - try { - Insets value = (Insets) converter.convertFromString("0 - 1 - 2 - 3", Insets.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/InsetsConverterTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,50 @@ +package jaxx.junit; + +import jaxx.types.InsetsConverter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.awt.Insets; + +public class InsetsConverterTest { + + InsetsConverter converter; + + @Before + public void setUp() { + converter = new InsetsConverter(); + } + + @Test + public void testSingleValue() { + Insets value = (Insets) converter.convertFromString("3", Insets.class); + Assert.assertEquals(value, new Insets(3, 3, 3, 3)); + } + + @Test + public void testFourValues() { + Insets value = (Insets) converter.convertFromString("3, 0, 12, 1000000", Insets.class); + Assert.assertEquals(value, new Insets(3, 0, 12, 1000000)); + } + + @Test(expected = IllegalArgumentException.class) + public void testTwoValues() { + converter.convertFromString("0, 4", Insets.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testThreeValues() { + converter.convertFromString("0, 4, 9", Insets.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidNumber() { + converter.convertFromString("0, 4, 9, A", Insets.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testBadFormatting() { + converter.convertFromString("0 - 1 - 2 - 3", Insets.class); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,53 +0,0 @@ -package jaxx.junit; - -import jaxx.CompilerException; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.JavaFileParser; -import junit.framework.TestCase; - -import java.io.File; -import java.io.FileReader; -import java.io.Reader; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class JavaFileParserTest extends TestCase { - - - /** log */ - protected static final Log log = LogFactory.getLog(JavaFileParserTest.class); - - protected File getBaseDir() { - // get maven env basedir - String basedir = System.getenv("basedir"); - if (basedir == null) { - basedir = new File("").getAbsolutePath(); - } - return new File(basedir); - } - - public void testParseJavaSourceFile() throws Exception { - - - File testSourceRoot = new File(getBaseDir(), "src" + File.separator + "test" + File.separator + "java"); - assertTrue(testSourceRoot.exists()); - - File src = new File(testSourceRoot, getClass().getName().replaceAll("\\.", File.separator) + ".java"); - assertTrue(src.exists()); - log.info("trying parsing file " + src); - Reader reader = new FileReader(src); - try { - ClassDescriptor result = JavaFileParser.parseJavaFile("TestParserJava", reader, getClass().getClassLoader()); - assertNotNull(result); - - } catch (CompilerException e) { - log.error("could not parse file "+src+" for reason "+e.getMessage(),e); - fail(e.getMessage()); - } - finally { - reader.close(); - } - } - -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/JavaFileParserTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,57 @@ +package jaxx.junit; + +import jaxx.CompilerException; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.JavaFileParser; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.FileReader; +import java.io.Reader; + +public class JavaFileParserTest { + + + /** log */ + protected static final Log log = LogFactory.getLog(JavaFileParserTest.class); + + static File basedir; + + @BeforeClass + public static void initBaseDir() { + // get maven env basedir + String basedir = System.getenv("basedir"); + if (basedir == null) { + basedir = new File("").getAbsolutePath(); + } + JavaFileParserTest.basedir = new File(basedir); + } + + @Test + public void testParseJavaSourceFile() throws Exception { + + File testSourceRoot = new File(basedir, "src" + File.separator + "test" + File.separator + "java"); + Assert.assertTrue(testSourceRoot.exists()); + + File src = new File(testSourceRoot, getClass().getName().replaceAll("\\.", File.separator) + ".java"); + Assert.assertTrue(src.exists()); + log.info("trying parsing file " + src); + Reader reader = new FileReader(src); + try { + ClassDescriptor result = JavaFileParser.parseJavaFile("TestParserJava", reader, getClass().getClassLoader()); + Assert.assertNotNull(result); + + } catch (CompilerException e) { + log.error("could not parse file " + src + " for reason " + e.getMessage(), e); + Assert.fail(e.getMessage()); + } + finally { + reader.close(); + } + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,106 +0,0 @@ -package jaxx.junit; - -import junit.framework.TestCase; - -import jaxx.types.*; - -public class PrimitiveConverterTest extends TestCase { - private PrimitiveConverter converter; - - public void setUp() { - converter = new PrimitiveConverter(); - } - - - public void testBoolean() { - Boolean value = (Boolean) converter.convertFromString("true", Boolean.class); - assertTrue(value.booleanValue()); - - value = (Boolean) converter.convertFromString("false", Boolean.class); - assertFalse(value.booleanValue()); - - try { - value = (Boolean) converter.convertFromString("yes", Boolean.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } - - - public void testByte() { - Byte value = (Byte) converter.convertFromString(String.valueOf(Byte.MAX_VALUE), Byte.class); - assertEquals(value.byteValue(), Byte.MAX_VALUE); - - try { - value = (Byte) converter.convertFromString(String.valueOf(1 + Byte.MAX_VALUE), Byte.class); - fail("Expected NumberFormatException"); - } - catch (NumberFormatException e) { } - } - - - public void testShort() { - Short value = (Short) converter.convertFromString(String.valueOf(Short.MAX_VALUE), Short.class); - assertEquals(value.shortValue(), Short.MAX_VALUE); - - try { - value = (Short) converter.convertFromString(String.valueOf(1 + Short.MAX_VALUE), Short.class); - fail("Expected NumberFormatException"); - } - catch (NumberFormatException e) { } - } - - - public void testInteger() { - Integer value = (Integer) converter.convertFromString(String.valueOf(Integer.MAX_VALUE), Integer.class); - assertEquals(value.intValue(), Integer.MAX_VALUE); - - try { - value = (Integer) converter.convertFromString(String.valueOf(1L + Integer.MAX_VALUE), Integer.class); - fail("Expected NumberFormatException"); - } - catch (NumberFormatException e) { } - } - - - public void testLong() { - Long value = (Long) converter.convertFromString(String.valueOf(Long.MAX_VALUE), Long.class); - assertEquals(value.longValue(), Long.MAX_VALUE); - } - - - public void testFloat() { - Float value = (Float) converter.convertFromString("3.1415", Float.class); - assertTrue(value.floatValue() == 3.1415f); - } - - - public void testDouble() { - Double value = (Double) converter.convertFromString("3.1415", Double.class); - assertTrue(value.doubleValue() == 3.1415); - } - - - public void testCharacter() { - Character value = (Character) converter.convertFromString("A", Character.class); - assertEquals(value.charValue(), 'A'); - - try { - value = (Character) converter.convertFromString("12", Character.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - - try { - value = (Character) converter.convertFromString("", Character.class); - fail("Expected IllegalArgumentException"); - } - catch (IllegalArgumentException e) { } - } - - - public void testString() { - String value = (String) converter.convertFromString("Test", String.class); - assertEquals(value, "Test"); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/PrimitiveConverterTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,113 @@ +package jaxx.junit; + +import jaxx.types.PrimitiveConverter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PrimitiveConverterTest { + + PrimitiveConverter converter; + + + @Before + public void setUp() { + converter = new PrimitiveConverter(); + } + + @Test + public void testBoolean() { + Boolean value = (Boolean) converter.convertFromString("true", Boolean.class); + Assert.assertTrue(value); + + value = (Boolean) converter.convertFromString("false", Boolean.class); + Assert.assertFalse(value); + + } + + @Test(expected = IllegalArgumentException.class) + public void testBoolean2() { + converter.convertFromString("yes", Boolean.class); + } + + @Test + public void testByte() { + Byte value = (Byte) converter.convertFromString(String.valueOf(Byte.MAX_VALUE), Byte.class); + Assert.assertEquals(value.byteValue(), Byte.MAX_VALUE); + + } + + @Test(expected = IllegalArgumentException.class) + public void testByte2() { + + converter.convertFromString(String.valueOf(1 + Byte.MAX_VALUE), Byte.class); + } + + @Test + public void testShort() { + Short value = (Short) converter.convertFromString(String.valueOf(Short.MAX_VALUE), Short.class); + Assert.assertEquals(value.shortValue(), Short.MAX_VALUE); + + + } + + @Test(expected = IllegalArgumentException.class) + public void testShort2() { + + converter.convertFromString(String.valueOf(1 + Short.MAX_VALUE), Short.class); + } + + @Test + public void testInteger() { + Integer value = (Integer) converter.convertFromString(String.valueOf(Integer.MAX_VALUE), Integer.class); + Assert.assertEquals(value.intValue(), Integer.MAX_VALUE); + } + + @Test(expected = IllegalArgumentException.class) + public void testInteger2() { + + converter.convertFromString(String.valueOf(1L + Integer.MAX_VALUE), Integer.class); + } + + @Test + public void testLong() { + Long value = (Long) converter.convertFromString(String.valueOf(Long.MAX_VALUE), Long.class); + Assert.assertEquals(value.longValue(), Long.MAX_VALUE); + } + + @Test + public void testFloat() { + Float value = (Float) converter.convertFromString("3.1415", Float.class); + Assert.assertTrue(value == 3.1415f); + } + + @Test + public void testDouble() { + Double value = (Double) converter.convertFromString("3.1415", Double.class); + Assert.assertTrue(value == 3.1415); + } + + @Test + public void testCharacter() { + Character value = (Character) converter.convertFromString("A", Character.class); + Assert.assertEquals(value.charValue(), 'A'); + } + + @Test(expected = IllegalArgumentException.class) + public void testCharacter2() { + + converter.convertFromString("12", Character.class); + + } + + @Test(expected = IllegalArgumentException.class) + public void testCharacter3() { + converter.convertFromString("", Character.class); + } + + @Test + public void testString() { + String value = (String) converter.convertFromString("Test", String.class); + Assert.assertEquals(value, "Test"); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,132 +0,0 @@ -package jaxx.junit; - -import jaxx.compiler.JAXXCompiler; -import jaxx.reflect.ClassDescriptor; -import jaxx.reflect.ClassDescriptorLoader; -import jaxx.tags.DefaultComponentHandler; -import jaxx.tags.DefaultObjectHandler; -import jaxx.tags.TagHandler; -import jaxx.tags.TagManager; -import junit.framework.TestCase; - -import javax.swing.JPopupMenu; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.IOException; - -public class TagManagerTest extends TestCase { - private JAXXCompiler compiler = JAXXCompiler.createDummyCompiler(); - - protected static boolean init=false; - - public static class TestHandler extends DefaultObjectHandler { - public TestHandler(ClassDescriptor beanClass) { - super(beanClass); - } - } - - - public void setUp() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { - compiler.addImport("javax.swing.*"); - if (!init) { - TagManager.reset(true); - init=true; - } - } - - - public void testRegisterBean() { - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(InputStream.class), TestHandler.class); - - assertTrue(TagManager.getTagHandler(ClassDescriptorLoader.getClassDescriptor(InputStream.class)) instanceof TestHandler); - assertTrue(TagManager.getTagHandler(ClassDescriptorLoader.getClassDescriptor(FileInputStream.class)) instanceof TestHandler); - } - - - public void testRegisterDefaultNamespace() { - TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(OutputStream.class), TestHandler.class); - - TagManager.registerDefaultNamespace("OutputStream", "java.io.*"); - assertTrue("Could not find handler for OutputStream despite default namespace", TagManager.getTagHandler(null, "OutputStream", compiler) instanceof TestHandler); - - PrintStream oldErr = System.err; - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - System.setErr(new PrintStream(buffer)); - TagManager.registerDefaultNamespace("OutputStream", "java.dummy.*"); - assertNull("Found handler for OutputStream despite ambiguous default namespace", TagManager.getTagHandler(null, "OutputStream", compiler)); - System.setErr(oldErr); - assertTrue("No errors were produced with an ambiguous default namespace", buffer.size() > 0); - assertTrue(buffer.size() > 0); - } - - - public void testResolveClassName() { - assertEquals("Could not resolve class name 'Object'", TagManager.resolveClassName("Object", compiler), "java.lang.Object"); - assertEquals("Could not resolve class name 'java.lang.Object'", TagManager.resolveClassName("java.lang.Object", compiler), "java.lang.Object"); - assertNull("Unexpectedly resolved class name 'java.awt.Object'", TagManager.resolveClassName("java.awt.Object", compiler)); - } - - - public void testPackages() { - assertNull("Unexpectedly found handler for java.awt.JButton", TagManager.getTagHandler(null, "java.awt.JButton", compiler)); - assertNotNull("Did not find handler for JButton with default namespace of java.awt.*", TagManager.getTagHandler("java.awt.*", "JButton", compiler)); - assertNull("Unexpectedly found handler for java.awt.*:JButton", TagManager.getTagHandler("java.awt.*", "JButton", true, compiler)); - assertNotNull("Did not find handler for javax.swing.JButton", TagManager.getTagHandler(null, "javax.swing.JButton", compiler)); - assertNotNull("Did not find handler for JButton with default namespace of java.swing.*", TagManager.getTagHandler("java.swing.*", "JButton", compiler)); - assertNotNull("Did not find handler for javax.swing.*:JButton", TagManager.getTagHandler("javax.swing.*", "JButton", true, compiler)); - } - - - public void testImport() throws Exception { - assertNull("Found handler for ActionListener despite no java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); - - compiler.addImport("java.awt.event.*"); - - //fixme makethis test works again - // assertNotNull("Did not find ActionListener with java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); - } - - - public void testAmbiguousImport() throws Exception { - compiler.addImport("java.sql.*"); - assertNotNull("Did not find java.sql.Date with only java.sql.* imported", TagManager.getTagHandler(null, "Date", compiler)); - - PrintStream oldErr = System.err; - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - System.setErr(new PrintStream(buffer)); - compiler.addImport("java.util.*"); - TagManager.reset(true); - assertNull("Still found a handler for Date with an ambiguous import", TagManager.getTagHandler(null, "Date", compiler)); - System.setErr(oldErr); - assertTrue("No errors were produced with an ambiguous import", buffer.size() > 0); - - compiler.addImport("java.util.Date"); - assertNotNull("Did not find java.util.Date with a disambiguating import", TagManager.getTagHandler(null, "Date", compiler)); - } - - - public void testInnerClass() { - TagHandler handler = TagManager.getTagHandler(null, "JPopupMenu.Separator", compiler); - assertTrue("Unable to resolve tag <JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); - assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); - - handler = TagManager.getTagHandler(null, "javax.swing.JPopupMenu.Separator", compiler); - assertTrue("Unable to resolve tag <javax.swing.JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); - assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); - } - - - public void testWrongCase() { - assertNull("Unexpectedly found handler for 'object'", TagManager.getTagHandler(null, "object", compiler)); - assertNull("Unexpectedly found handler for 'tagmanagertest'", TagManager.getTagHandler(null, "tagmanagertest", compiler)); - } - - - public void testAliasing() { - assertEquals("JComboBox is not aliased to jaxx.runtime.swing.JAXXComboBox", "jaxx.runtime.swing.JAXXComboBox", TagManager.resolveClassName("JComboBox", compiler)); - assertEquals("javax.swing.JComboBox is not aliased to jaxx.runtime.swing.JAXXComboBox", "jaxx.runtime.swing.JAXXComboBox", TagManager.resolveClassName("javax.swing.JComboBox", compiler)); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java (from rev 1015, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/TagManagerTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,158 @@ +package jaxx.junit; + +import jaxx.compiler.JAXXCompiler; +import jaxx.reflect.ClassDescriptor; +import jaxx.reflect.ClassDescriptorLoader; +import jaxx.tags.DefaultComponentHandler; +import jaxx.tags.DefaultObjectHandler; +import jaxx.tags.TagHandler; +import jaxx.tags.TagManager; +import jaxx.tags.swing.SwingInitializer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.swing.JPopupMenu; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.beans.Introspector; + +public class TagManagerTest { + + JAXXCompiler compiler = JAXXCompiler.createDummyCompiler(); + + public static class TestHandler extends DefaultObjectHandler { + public TestHandler(ClassDescriptor beanClass) { + super(beanClass); + } + } + + @BeforeClass + public static void initTagManaer() throws Exception { + + TagManager.reset(true); + + } + + @Before + public void setUp() { + compiler.addImport("javax.swing.*"); + + } + + @Test + public void testRegisterBean() { + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(InputStream.class), TestHandler.class); + + Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorLoader.getClassDescriptor(InputStream.class)) instanceof TestHandler); + Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorLoader.getClassDescriptor(FileInputStream.class)) instanceof TestHandler); + } + + @Test + public void testRegisterDefaultNamespace() { + TagManager.registerBean(ClassDescriptorLoader.getClassDescriptor(OutputStream.class), TestHandler.class); + + TagManager.registerDefaultNamespace("OutputStream", "java.io.*"); + Assert.assertTrue("Could not find handler for OutputStream despite default namespace", TagManager.getTagHandler(null, "OutputStream", compiler) instanceof TestHandler); + + PrintStream oldErr = System.err; + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + System.setErr(new PrintStream(buffer)); + TagManager.registerDefaultNamespace("OutputStream", "java.dummy.*"); + Assert.assertNull("Found handler for OutputStream despite ambiguous default namespace", TagManager.getTagHandler(null, "OutputStream", compiler)); + System.setErr(oldErr); + Assert.assertTrue("No errors were produced with an ambiguous default namespace", buffer.size() > 0); + Assert.assertTrue(buffer.size() > 0); + } + + @Test + public void testResolveClassName() { + Assert.assertEquals("Could not resolve class name 'Object'", TagManager.resolveClassName("Object", compiler), "java.lang.Object"); + Assert.assertEquals("Could not resolve class name 'java.lang.Object'", TagManager.resolveClassName("java.lang.Object", compiler), "java.lang.Object"); + Assert.assertNull("Unexpectedly resolved class name 'java.awt.Object'", TagManager.resolveClassName("java.awt.Object", compiler)); + } + + @Test + public void testPackages() { + Assert.assertNull("Unexpectedly found handler for java.awt.JButton", TagManager.getTagHandler(null, "java.awt.JButton", compiler)); + Assert.assertNotNull("Did not find handler for JButton with default namespace of java.awt.*", TagManager.getTagHandler("java.awt.*", "JButton", compiler)); + Assert.assertNull("Unexpectedly found handler for java.awt.*:JButton", TagManager.getTagHandler("java.awt.*", "JButton", true, compiler)); + Assert.assertNotNull("Did not find handler for javax.swing.JButton", TagManager.getTagHandler(null, "javax.swing.JButton", compiler)); + Assert.assertNotNull("Did not find handler for JButton with default namespace of java.swing.*", TagManager.getTagHandler("java.swing.*", "JButton", compiler)); + Assert.assertNotNull("Did not find handler for javax.swing.*:JButton", TagManager.getTagHandler("javax.swing.*", "JButton", true, compiler)); + } + + @Test + public void testImport() throws Exception { + Assert.assertNull("Found handler for ActionListener despite no java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); + + compiler.addImport("java.awt.event.*"); + + Assert.assertNotNull("Did not find ActionListener with java.awt.event.* import", TagManager.getTagHandler(null, "ActionListener", compiler)); + } + + @Test + public void testAmbiguousImport() throws Exception { + compiler.addImport("java.sql.*"); + Assert.assertNotNull("Did not find java.sql.Date with only java.sql.* imported", TagManager.getTagHandler(null, "Date", compiler)); + + PrintStream oldErr = System.err; + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + System.setErr(new PrintStream(buffer)); + compiler.addImport("java.util.*"); + TagManager.reset(true); + Assert.assertNull("Still found a handler for Date with an ambiguous import", TagManager.getTagHandler(null, "Date", compiler)); + System.setErr(oldErr); + Assert.assertTrue("No errors were produced with an ambiguous import", buffer.size() > 0); + + compiler.addImport("java.util.Date"); + Assert.assertNotNull("Did not find java.util.Date with a disambiguating import", TagManager.getTagHandler(null, "Date", compiler)); + } + + @Test + public void testInnerClass() { + TagHandler handler = TagManager.getTagHandler(null, "JPopupMenu.Separator", compiler); + Assert.assertTrue("Unable to resolve tag <JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); + Assert.assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); + + handler = TagManager.getTagHandler(null, "javax.swing.JPopupMenu.Separator", compiler); + Assert.assertTrue("Unable to resolve tag <javax.swing.JPopupMenu.Separator>", handler instanceof DefaultComponentHandler); + Assert.assertTrue(((DefaultComponentHandler) handler).getBeanClass().getName().equals(JPopupMenu.Separator.class.getName())); + } + + @Test + public void testWrongCase() { + Assert.assertNull("Unexpectedly found handler for 'object'", TagManager.getTagHandler(null, "object", compiler)); + Assert.assertNull("Unexpectedly found handler for 'tagmanagertest'", TagManager.getTagHandler(null, "tagmanagertest", compiler)); + } + + @Test + public void testAliasing() { + Assert.assertEquals("JComboBox is not aliased to jaxx.runtime.swing.JAXXComboBox", "jaxx.runtime.swing.JAXXComboBox", TagManager.resolveClassName("JComboBox", compiler)); + Assert.assertEquals("javax.swing.JComboBox is not aliased to jaxx.runtime.swing.JAXXComboBox", "jaxx.runtime.swing.JAXXComboBox", TagManager.resolveClassName("javax.swing.JComboBox", compiler)); + } + + @Test + public void testExtraBeanInfoPath() { + String[] searchPath0 = Introspector.getBeanInfoSearchPath(); + + new SwingInitializer().initialize(); + String[] searchPath = Introspector.getBeanInfoSearchPath(); + Assert.assertEquals(searchPath0.length+1,searchPath.length); + Introspector.setBeanInfoSearchPath(searchPath0); + + String packageName = getClass().getPackage().getName(); + SwingInitializer.setExtraBeanInfoSearchPath(new String[]{packageName}); + + new SwingInitializer().initialize(); + searchPath = Introspector.getBeanInfoSearchPath(); + Assert.assertEquals(searchPath0.length+2,searchPath.length); + Assert.assertEquals(packageName, searchPath[searchPath.length-1]); + + Introspector.setBeanInfoSearchPath(searchPath0); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,79 +0,0 @@ -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.7/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorBean.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,78 @@ +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 Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,167 +0,0 @@ -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.7/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/junit/ValidatorTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,173 @@ +package jaxx.junit; + +import jaxx.runtime.validator.BeanValidator; +import jaxx.runtime.validator.BeanValidatorError; +import jaxx.runtime.validator.BeanValidatorErrorListModel; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.swing.JLabel; +import java.io.File; +import java.util.Enumeration; + +/** @author chemit */ +public class ValidatorTest { + + ValidatorBean bean; + + static protected BeanValidator<ValidatorBean> validator; + static protected BeanValidatorErrorListModel errors; + static protected File basedir; + + @BeforeClass + public static void initValidator() throws Exception { + + 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); + + } + + @Before + public void setUp() throws Exception { + validator.setBean(bean = new ValidatorBean()); + } + + @Test + public void testRequiredFileFieldValidator() throws Exception { + + Assert.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); + + } + + @Test + public void testExistingFileFieldValidator() throws Exception { + + Assert.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); + + } + + @Test + public void testNotExistingFileFieldValidator() throws Exception { + + Assert.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); + + + } + + @Test + public void testExistingDirectoryFieldValidator() throws Exception { + + Assert.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); + + } + + @Test + public void testNotExistingDirectoryFieldValidator() throws Exception { + Assert.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)) { + Assert.assertTrue(required); + return; + } + } + // error was not found + Assert.assertFalse(required); + } +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/DefaultJAXXContextTest.java (from rev 1017, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/DefaultJAXXContextTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/DefaultJAXXContextTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/DefaultJAXXContextTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,308 @@ +package jaxx.runtime; + +import jaxx.runtime.validator.BeanValidator; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.awt.Container; +import java.util.List; +import java.util.Map; + +/** @author chemit */ +public class DefaultJAXXContextTest { + + DefaultJAXXContext ctxt; + + @Before + public void initContext() throws Exception { + + // instanciate a new empty context + ctxt = new DefaultJAXXContext(); + } + + @Test(expected = IllegalStateException.class) + public void testParentContainerFail_IllegalStateException() throws Exception { + ctxt.getParentContainer(Container.class); + } + + @Test(expected = IllegalStateException.class) + public void testParentContainerFail_IllegalStateException2() throws Exception { + ctxt.getParentContainer("null", Container.class); + } + + + @Test(expected = IllegalArgumentException.class) + public void testParentContainerFail_IllegalArgumentException() throws Exception { + + // attach a fake ui (which is NOT a Container) + ctxt.setUi(new MyJAXXObject()); + ctxt.getParentContainer(Container.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testParentContainerFail_IllegalArgumentException2() throws Exception { + + // attach a fake ui (which is NOT a Container) + ctxt.setUi(new MyJAXXObject()); + ctxt.getParentContainer(null, Container.class); + } + + @Test(expected = IllegalArgumentException.class) + public void testParentContainerFail_IllegalArgumentException3() throws Exception { + + // attach a fake ui (which is NOT a Container) + ctxt.setUi(new MyJAXXObject()); + ctxt.getParentContainer("null", Container.class); + } + + @Test + public void testGetParentContext() throws Exception { + JAXXContext expected, result; + expected = null; + result = ctxt.getContextValue(JAXXContext.class); + Assert.assertEquals(expected, result); + + DefaultJAXXContext parentContext = new DefaultJAXXContext(); + + ctxt.setContextValue(parentContext); + + expected = parentContext; + result = ctxt.getContextValue(JAXXContext.class); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValue() throws Exception { + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + + expected = "yo"; + ctxt.setContextValue(expected); + result = ctxt.getContextValue(String.class); + Assert.assertEquals(expected, result); + + expected = "ya"; + ctxt.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + + expected = "yi"; + ctxt.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValueInParentContext() throws Exception { + + // attach parent context + JAXXContext parentContext = new DefaultJAXXContext(); + ctxt.setContextValue(parentContext); + + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + + expected = "yo"; + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + parentContext.setContextValue(expected); + result = ctxt.getContextValue(String.class); + Assert.assertEquals(expected, result); + + expected = "ya"; + result = ctxt.getContextValue(String.class, "second"); + Assert.assertNull(result); + parentContext.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + + expected = "yi"; + result = ctxt.getContextValue(String.class, "second"); + parentContext.setContextValue(expected, "second"); + Assert.assertEquals("ya", result); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValue2() throws Exception { + + // attach parent context + JAXXContext parentContext = new DefaultJAXXContext(); + ctxt.setContextValue(parentContext); + + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + result = ctxt.getContextValue(String.class, "yo"); + Assert.assertNull(result); + + expected = "yo"; + ctxt.setContextValue(expected, "yo"); + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + result = ctxt.getContextValue(String.class, "yo"); + Assert.assertEquals(expected, result); + } + + @Test + public void testSetGetContextValueInParentParentContext() throws Exception { + + // attach parent parent context + JAXXContext parentParentContext = new DefaultJAXXContext(); + JAXXContext parentContext = new DefaultJAXXContext(); + parentContext.setContextValue(parentParentContext); + ctxt.setContextValue(parentContext); + + String expected; + String result; + + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + + expected = "yo"; + result = ctxt.getContextValue(String.class); + Assert.assertNull(result); + parentParentContext.setContextValue(expected); + result = ctxt.getContextValue(String.class); + Assert.assertEquals(expected, result); + + expected = "ya"; + result = ctxt.getContextValue(String.class, "second"); + Assert.assertNull(result); + parentParentContext.setContextValue(expected, "second"); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + + expected = "yi"; + result = ctxt.getContextValue(String.class, "second"); + parentParentContext.setContextValue(expected, "second"); + Assert.assertEquals("ya", result); + result = ctxt.getContextValue(String.class, "second"); + Assert.assertEquals(expected, result); + } + + @Test + public void testEntrySet() throws Exception { + Object o = new Object(); + + ctxt.setContextValue(o); + + Assert.assertEquals(1, ctxt.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object.class, "named")); + + ctxt.setContextValue(o, "named"); + + Assert.assertEquals(2, ctxt.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); + + ctxt.removeContextValue(Object.class); + Assert.assertEquals(1, ctxt.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); + + ctxt.removeContextValue(Object.class); + Assert.assertEquals(1, ctxt.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object.class, "named")); + + ctxt.removeContextValue(Object.class, "named"); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object.class, "named")); + + } + + @Test + public void testEntrySetWithParent() throws Exception { + + DefaultJAXXContext parentContext = new DefaultJAXXContext(); + + ctxt.setContextValue(parentContext); + + class Object2 { + + } + Object o = new Object2(); + + parentContext.setContextValue(o); + + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(1, parentContext.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class, "named")); + + parentContext.setContextValue(o, "named"); + + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(2, parentContext.data.size()); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); + + parentContext.removeContextValue(Object2.class); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(1, parentContext.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); + + parentContext.removeContextValue(Object2.class); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(1, parentContext.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(o, ctxt.getContextValue(Object2.class, "named")); + + ctxt.removeContextValue(Object2.class, "named"); + Assert.assertEquals(0, ctxt.data.size()); + Assert.assertEquals(0, parentContext.data.size()); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class)); + Assert.assertEquals(null, ctxt.getContextValue(Object2.class, "named")); + + } + + private static class MyJAXXObject extends DefaultJAXXContext implements JAXXObject { + + public Object getObjectById(String id) { + return null; + } + + public Map<String, Object> get$objectMap() { + return null; + } + + public void applyDataBinding(String id) { + } + + public void removeDataBinding(String id) { + } + + public JAXXContext getDelegateContext() { + return null; + } + + public void processDataBinding(String dest) { + } + + public void firePropertyChange(String name, Object oldValue, Object newValue) { + } + + public BeanValidator<?> getValidator(String validatorId) { + return null; + } + + public List<String> getValidatorIds() { + return null; + } + } +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/JXPathDecoratorTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,96 @@ +package jaxx.runtime; + +import org.junit.After; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +/** @author chemit */ +public class JXPathDecoratorTest { + + + protected JXPathDecorator<?> decorator; + protected String expected; + protected String result; + + @After + public void after() { + decorator = null; + } + + @Test(expected = NullPointerException.class) + public void testNullInternalClass() throws Exception { + decorator = JXPathDecorator.newDecorator(null, "hello"); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingRightBrace() throws Exception { + decorator = JXPathDecorator.newDecorator(Object.class, "${haha"); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingRightBrace2() throws Exception { + decorator = JXPathDecorator.newDecorator(Object.class, "${haha${hum}"); + } + + @Test + public void testNullBean() throws Exception { + decorator = JXPathDecorator.newDecorator(Object.class, "hello"); + expected = "hello"; + assertEquals(expected, decorator.getExpression()); + assertEquals(0, decorator.nbToken); + assertEquals(0, decorator.getTokens().length); + + result = decorator.toString(null); + assertEquals(null, result); + } + + @Test + public void testNoJXPath() throws Exception { + decorator = JXPathDecorator.newDecorator(Object.class, "hello"); + expected = "hello"; + assertEquals(expected, decorator.getExpression()); + assertEquals(0, decorator.nbToken); + assertEquals(0, decorator.getTokens().length); + + result = decorator.toString(this); + assertEquals(expected, result); + } + + @Test + public void testDecorator() throws Exception { + + decorator = JXPathDecorator.newDecorator(JXPathDecorator.class, "${expression}$s - ${nbToken}$d"); + assertEquals("%1$s - %2$d", decorator.getExpression()); + assertDecoratorInternal(); + + decorator = JXPathDecorator.newDecorator(JXPathDecorator.class, "${expression}${nbToken}"); + assertEquals("%1%2", decorator.getExpression()); + assertDecoratorInternal(); + + decorator = JXPathDecorator.newDecorator(JXPathDecorator.class, "before ${expression}$s - ${nbToken}$d after"); + assertEquals("before %1$s - %2$d after", decorator.getExpression()); + assertDecoratorInternal(); + + decorator = JXPathDecorator.newDecorator(JXPathDecorator.class, "before${expression}$s-${nbToken}$dafter"); + assertEquals("before%1$s-%2$dafter", decorator.getExpression()); + assertDecoratorInternal(); + } + + public void assertDecoratorInternal(String... tokens) { + assertTokens(tokens); + expected = String.format(decorator.getExpression(), decorator.getExpression(), decorator.getNbToken()); + result = decorator.toString(decorator); + assertEquals(expected, result); + } + + private void assertTokens(String... tokens) { + if (tokens.length == 0) { + tokens = new String[]{"expression", "nbToken"}; + } + assertEquals(2, decorator.nbToken); + assertEquals(2, decorator.getTokens().length); + assertEquals(tokens[0], decorator.getTokens()[0]); + assertEquals(tokens[1], decorator.getTokens()[1]); + } + +} Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java (from rev 1060, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/MultiJXPathDecoratorTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,149 @@ +package jaxx.runtime; + +import org.junit.After; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +/** @author chemit */ +public class MultiJXPathDecoratorTest { + + + protected MultiJXPathDecorator<?> decorator; + protected String expected; + protected String result; + + @After + public void after() { + decorator = null; + } + + @Test(expected = NullPointerException.class) + public void testNullInternalClass() throws Exception { + decorator = MultiJXPathDecorator.newDecorator(null, "hello", "#"); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingRightBrace() throws Exception { + decorator = MultiJXPathDecorator.newDecorator(Object.class, "${haha", "#"); + } + + @Test(expected = IllegalArgumentException.class) + public void testMissingRightBrace2() throws Exception { + decorator = MultiJXPathDecorator.newDecorator(Object.class, "${haha${hum}", "#"); + } + + @Test + public void testNullBean() throws Exception { + decorator = MultiJXPathDecorator.newDecorator(Object.class, "hello", ""); + expected = "hello"; + assertEquals(expected, decorator.getExpression()); + assertEquals(0, decorator.nbToken); + assertEquals(0, decorator.getTokens().length); + + result = decorator.toString(null); + assertEquals(null, result); + } + + @Test + public void testMultiDecorator() throws Exception { + + decorator = MultiJXPathDecorator.newDecorator(JXPathDecorator.class, "${expression}$s#${nbToken}$d", "#", " - "); + assertEquals("%1$s - %2$d", decorator.getExpression()); + assertDecoratorInternal(); + assertEquals(2, decorator.contexts.length); + decorator.setContextIndex(1); + assertEquals("%1$d - %2$s", decorator.getExpression()); + assertTokens("nbToken", "expression"); + expected = String.format(decorator.getExpression(), decorator.getNbToken(), decorator.getExpression()); + result = decorator.toString(decorator); + assertEquals(expected, result); + + decorator = MultiJXPathDecorator.newDecorator(JXPathDecorator.class, "${expression}$s ## ${nbToken}$d", " ## ", " - "); + assertEquals("%1$s - %2$d", decorator.getExpression()); + assertDecoratorInternal(); + assertEquals(2, decorator.contexts.length); + decorator.setContextIndex(1); + assertEquals("%1$d - %2$s", decorator.getExpression()); + assertTokens("nbToken", "expression"); + expected = String.format(decorator.getExpression(), decorator.getNbToken(), decorator.getExpression()); + result = decorator.toString(decorator); + assertEquals(expected, result); + } + + @Test + public void testMultiDecorator2() throws Exception { + + decorator = MultiJXPathDecorator.newDecorator(JXPathDecorator.class, "${expression}$s#${nbToken}$d#${separator}$s", "#", " - "); + + assertEquals("%1$s - %2$d - %3$s", decorator.getExpression()); + assertTokens("expression", "nbToken", "separator"); + assertEquals(3, decorator.contexts.length); + + expected = String.format(decorator.getExpression(), decorator.getExpression(), decorator.getNbToken(), decorator.getSeparator()); + result = decorator.toString(decorator); + assertEquals(expected, result); + + decorator.setContextIndex(1); + assertEquals("%1$d - %2$s - %3$s", decorator.getExpression()); + assertTokens("nbToken", "separator", "expression"); + expected = String.format(decorator.getExpression(), decorator.getNbToken(), decorator.getSeparator(), decorator.getExpression()); + result = decorator.toString(decorator); + assertEquals(expected, result); + + decorator.setContextIndex(2); + assertEquals("%1$s - %2$s - %3$d", decorator.getExpression()); + assertTokens("separator", "expression", "nbToken"); + + expected = String.format(decorator.getExpression(), decorator.getSeparator(), decorator.getExpression(), decorator.getNbToken()); + result = decorator.toString(decorator); + assertEquals(expected, result); + } + + @Test + public void testMultiDecoratorWithMultiRef() throws Exception { + + decorator = MultiJXPathDecorator.newDecorator(JXPathDecorator.class, "${expression}$s#${nbToken}$d#${separator}$s %3$s", "#", " - "); + + assertEquals("%1$s - %2$d - %3$s %3$s", decorator.getExpression()); + assertTokens("expression", "nbToken", "separator"); + assertEquals(3, decorator.contexts.length); + + expected = String.format(decorator.getExpression(), decorator.getExpression(), decorator.getNbToken(), decorator.getSeparator()); + result = decorator.toString(decorator); + assertEquals(expected, result); + + decorator.setContextIndex(1); + assertEquals("%1$d - %2$s %3$s - %3$s", decorator.getExpression()); + assertTokens("nbToken", "separator", "expression"); + expected = String.format(decorator.getExpression(), decorator.getNbToken(), decorator.getSeparator(), decorator.getExpression()); + result = decorator.toString(decorator); + assertEquals(expected, result); + + decorator.setContextIndex(2); + assertEquals("%1$s %3$s - %2$s - %3$d", decorator.getExpression()); + assertTokens("separator", "expression", "nbToken"); + + expected = String.format(decorator.getExpression(), decorator.getSeparator(), decorator.getExpression(), decorator.getNbToken()); + result = decorator.toString(decorator); + assertEquals(expected, result); + } + + public void assertDecoratorInternal(String... tokens) { + assertTokens(tokens); + expected = String.format(decorator.getExpression(), decorator.getExpression(), decorator.getNbToken()); + result = decorator.toString(decorator); + assertEquals(expected, result); + } + + private void assertTokens(String... tokens) { + if (tokens.length == 0) { + tokens = new String[]{"expression", "nbToken"}; + } + assertEquals(tokens.length, decorator.nbToken); + assertEquals(tokens.length, decorator.getTokens().length); + for (int i = 0; i < tokens.length; i++) { + assertEquals(tokens[i], decorator.getTokens()[i]); + } + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,25 +0,0 @@ -package jaxx.runtime; - -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -public class UtilTest extends junit.framework.TestCase { - private int count; - - - public void testGetEventListener() { - count = 0; - DocumentListener listener = (DocumentListener) jaxx.runtime.Util.getEventListener(javax.swing.event.DocumentListener.class, this, "incCount"); - listener.insertUpdate(null); - assertEquals(count, 1); - DocumentListener listener2 = (DocumentListener) jaxx.runtime.Util.getEventListener(javax.swing.event.DocumentListener.class, this, "incCount"); - listener2.removeUpdate(null); - assertEquals(count, 2); - //assertTrue("Received two different event listeners despite using identical parameters", listener == listener2); - } - - - public void incCount(DocumentEvent e) { - count++; - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/UtilTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,29 @@ +package jaxx.runtime; + +import org.junit.Assert; +import org.junit.Test; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +public class UtilTest { + + int count; + + @Test + public void testGetEventListener() { + count = 0; + DocumentListener listener = (DocumentListener) jaxx.runtime.Util.getEventListener(javax.swing.event.DocumentListener.class, this, "incCount"); + listener.insertUpdate(null); + Assert.assertEquals(count, 1); + DocumentListener listener2 = (DocumentListener) jaxx.runtime.Util.getEventListener(javax.swing.event.DocumentListener.class, this, "incCount"); + listener2.removeUpdate(null); + Assert.assertEquals(count, 2); + //assertTrue("Received two different event listeners despite using identical parameters", listener == listener2); + } + + + public void incCount(DocumentEvent e) { + count++; + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing (from rev 1017, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/swing) Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/NavigationTreeModelTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/swing/NavigationTreeModelTest.java 2008-11-16 17:44:15 UTC (rev 1017) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/NavigationTreeModelTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,398 +0,0 @@ -package jaxx.runtime.swing; - -import jaxx.runtime.DefaultJAXXContext; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXContextEntryDef; -import jaxx.runtime.swing.NavigationTreeModel.NavigationTreeNode; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - - -/** - * Test du model de navigation. - * - * @author chemit - */ -public class NavigationTreeModelTest { - - - private static final String ROOT_CONTEXT = "$root"; - private static final String FAKE = "-fake"; - private static final String DOT = "."; - - @Test - public void testFindNode() throws Exception { - - NavigationTreeNode rootNode = new NavigationTreeNode(ROOT_CONTEXT, null, null, null); - - for (int i = 0; i < 4; i++) { - NavigationTreeNode sonNode = new NavigationTreeNode(getNodeContext(i), null, null, null); - rootNode.insert(sonNode, i); - for (int j = 0; j < 4; j++) { - NavigationTreeNode sonSonNode = new NavigationTreeNode(getNodeContext(i, j), null, null, null); - sonNode.insert(sonSonNode, j); - for (int k = 0; k < 4; k++) { - sonSonNode.insert(new NavigationTreeNode(getNodeContext(i, j, k), null, null, null), k); - } - } - } - - NavigationTreeModel model = new NavigationTreeModel(rootNode); - - NavigationTreeNode node; - String contextPath; - String currentNode; - - contextPath = ROOT_CONTEXT; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, ROOT_CONTEXT, 0, node, true); - - node = model.findNode(ROOT_CONTEXT + FAKE); - Assert.assertNull(node); - - for (int i = 0; i < 4; i++) { - currentNode = getNodeContext(i); - contextPath = ROOT_CONTEXT + DOT + currentNode; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, currentNode, 1, node, false); - - for (int j = 0; j < 4; j++) { - currentNode = getNodeContext(i, j); - contextPath = ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + currentNode; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, currentNode, 2, node, false); - - for (int k = 0; k < 4; k++) { - currentNode = getNodeContext(i, j, k); - contextPath = ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + getNodeContext(i, j) + DOT + currentNode; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, currentNode, 3, node, false); - } - - node = model.findNode(ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + getNodeContext(i, j) + DOT + currentNode + FAKE); - Assert.assertNull(node); - } - - node = model.findNode(ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + currentNode + FAKE); - Assert.assertNull(node); - - } - - } - - /** - * Test the {@link NavigationTreeModel#getJAXXContextValue(jaxx.runtime.JAXXContext, String)} with an entry point - * as a bean. - * <p/> - * Tree is like this - * <pre> - * $root + - * - name <-- attached to context entry : java.lang.String.class,"name" - * - name2 <-- attached to context entry : java.lang.String.class,"name2" - * - model + <-- attached to context entry : Model.class,null - * - name - * -integerValue - * - sons + - * - 0 + - * - name - * - integerValue - * - sons - * - 1 + - * - name - * - integerValue - * - sons - * - 2 + - * - name - * - integerValue - * - sons - * </pre> - * <p/> - * With this tree, we will have to results : - * <pre> - * $root.name => context.get(String.class,"name") - * $root.name2 => context.get(String.class,"name2") - * $root.model => context.get(Model.class) - * $root.model.name => context.get(Model.class).getName() - * $root.model.integerValue => context.get(Model.class).getIntegerValue() - * $root.model.sons => context.get(Model.class).getSons() - * $root.model.sons.0 => context.get(Model.class).getSons().get(0) - * </pre> - * - * @throws Exception if any pb - */ - @Test - public void testGetJAXXContextValue() throws Exception { - - NavigationTreeNode rootNode = new NavigationTreeNode(ROOT_CONTEXT, null, null, null); - NavigationTreeNode sonNode; - NavigationTreeNode sonSonNode; - NavigationTreeNode sonSonSonNode; - - sonNode = new NavigationTreeNode("name", null, null, JAXXContextEntryDef.newDef("name", String.class)); - - rootNode.insert(sonNode, 0); - - sonNode = new NavigationTreeNode("name2", null, null, JAXXContextEntryDef.newDef("name2", String.class)); - - rootNode.insert(sonNode, 1); - - sonNode = new NavigationTreeNode("model", null, null, JAXXContextEntryDef.newDef(Model.class)); - - rootNode.insert(sonNode, 2); - - sonSonNode = new NavigationTreeNode("name", null, null, null); - sonNode.insert(sonSonNode, 0); - - sonSonNode = new NavigationTreeNode("integerValue", null, null, null); - sonNode.insert(sonSonNode, 1); - - sonSonNode = new NavigationTreeNode("sons", null, null, null); - sonNode.insert(sonSonNode, 2); - - sonSonSonNode = new NavigationTreeNode(0 + "", null, null, null); - sonSonNode.insert(sonSonSonNode, 0); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - sonSonSonNode = new NavigationTreeNode(1 + "", null, null, null); - sonSonNode.insert(sonSonSonNode, 1); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - sonSonSonNode = new NavigationTreeNode(2 + "", null, null, null); - sonSonNode.insert(sonSonSonNode, 2); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - NavigationTreeModel model = new NavigationTreeModel(rootNode); - - JAXXContext context = new DefaultJAXXContext(); - context.setContextValue("the name", "name"); - context.setContextValue("the name2", "name2"); - - - context.setContextValue( - new Model("modelName", 10, - Arrays.asList( - new Model("one", 1, Collections.<Model>emptyList()), - new Model("two", 2, Collections.<Model>emptyList()), - new Model("three", 3, Collections.<Model>emptyList()) - ) - ) - ); - - Assert.assertNull(model.getJAXXContextValue(context, "$root.name" + FAKE)); - - testBinding(model, context, "$root.name", context.getContextValue(String.class, "name")); - testBinding(model, context, "$root.name2", context.getContextValue(String.class, "name2")); - - Model bean = context.getContextValue(Model.class); - - testBinding(model, context, "$root.model", bean); - testBinding(model, context, "$root.model.name", bean.getName()); - testBinding(model, context, "$root.model.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.model.sons", bean.getSons()); - - testBinding(model, context, "$root.model.sons.0.name", bean.getSons().get(0).getName()); - testBinding(model, context, "$root.model.sons.0.integerValue", bean.getSons().get(0).getIntegerValue()); - testBinding(model, context, "$root.model.sons.0.sons", bean.getSons().get(0).getSons()); - - - testBinding(model, context, "$root.model.sons.1.name", bean.getSons().get(1).getName()); - testBinding(model, context, "$root.model.sons.1.integerValue", bean.getSons().get(1).getIntegerValue()); - testBinding(model, context, "$root.model.sons.1.sons", bean.getSons().get(1).getSons()); - - testBinding(model, context, "$root.model.sons.2.name", bean.getSons().get(2).getName()); - testBinding(model, context, "$root.model.sons.2.integerValue", bean.getSons().get(2).getIntegerValue()); - testBinding(model, context, "$root.model.sons.2.sons", bean.getSons().get(2).getSons()); - } - - /** - * Test the {@link NavigationTreeModel#getJAXXContextValue(jaxx.runtime.JAXXContext, String)} with an entry point - * as a list. - * <p/> - * Tree is like this - * <pre> - * $root + - * - models + <-- attached to context entry : java.util.List.class,"models" - * - 0 + - * - name - * -integerValue - * - sons + - * - 0 + - * - name - * - 1 + - * - name - * - integerValue - * - sons - * - 2 + - * - name - * - integerValue - * - sons - * </pre> - * <p/> - * With this tree, we will have to results : - * <pre> - * $root.models => context.get(List.class,"models") - * $root.models.0 => context.get(List.class,"models").get(0) - * $root.models.0.name => context.get(List.class,"models").get(0).getName() - * </pre> - * - * @throws Exception if any pb - */ - @Test - public void testGetJAXXContextValueFromList() throws Exception { - - NavigationTreeNode rootNode = new NavigationTreeNode(ROOT_CONTEXT, null, null, null); - NavigationTreeNode sonNode; - NavigationTreeNode sonSonNode; - NavigationTreeNode sonSonSonNode; - - // first son is a list of models - sonNode = new NavigationTreeNode("models", null, null, JAXXContextEntryDef.newListDef("models")); - rootNode.insert(sonNode, 0); - - // first son son is a model - sonSonNode = new NavigationTreeNode("0", null, null, null); - sonNode.insert(sonSonNode, 0); - - sonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonNode.insert(sonSonSonNode = new NavigationTreeNode("sons", null, null, null), 2); - - sonSonSonNode.insert(sonSonSonNode = new NavigationTreeNode("0", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - - // second son son is a model - sonSonNode = new NavigationTreeNode("1", null, null, null); - sonNode.insert(sonSonNode, 1); - sonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - // third son son is a model - sonSonNode = new NavigationTreeNode("2", null, null, null); - sonNode.insert(sonSonNode, 2); - sonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - NavigationTreeModel model = new NavigationTreeModel(rootNode); - - JAXXContext context = new DefaultJAXXContext(); - List<Model> list = new ArrayList<Model>(); - list.add(new Model("entryOne", 10, - Arrays.asList( - new Model("one", 1, Collections.<Model>emptyList()), - new Model("two", 2, Collections.<Model>emptyList()), - new Model("three", 3, Collections.<Model>emptyList()) - ) - )); - list.add(new Model("entryTwo", 20, - Arrays.asList( - new Model("2one", 1, Collections.<Model>emptyList()), - new Model("2two", 2, Collections.<Model>emptyList()), - new Model("2three", 3, Collections.<Model>emptyList()) - ) - )); - list.add(new Model("entryThree", 30, - Arrays.asList( - new Model("3one", 1, Collections.<Model>emptyList()), - new Model("3two", 2, Collections.<Model>emptyList()), - new Model("3three", 3, Collections.<Model>emptyList()) - ) - )); - context.setContextValue(list, "models"); - - Model bean; - - testBinding(model, context, "$root.models", list); - - bean = list.get(0); - testBinding(model, context, "$root.models.0", bean); - testBinding(model, context, "$root.models.0.name", bean.getName()); - testBinding(model, context, "$root.models.0.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.models.0.sons", bean.getSons()); - testBinding(model, context, "$root.models.0.sons.0", bean.getSons().get(0)); - testBinding(model, context, "$root.models.0.sons.0.name", bean.getSons().get(0).getName()); - - bean = list.get(1); - testBinding(model, context, "$root.models.1", bean); - testBinding(model, context, "$root.models.1.name", bean.getName()); - testBinding(model, context, "$root.models.1.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.models.1.sons", bean.getSons()); - - bean = list.get(2); - testBinding(model, context, "$root.models.2", bean); - testBinding(model, context, "$root.models.2.name", bean.getName()); - testBinding(model, context, "$root.models.2.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.models.2.sons", bean.getSons()); - - } - - protected void testBinding(NavigationTreeModel model, JAXXContext context, String contextPath, Object expected) throws Exception { - - Object value; - value = model.getJAXXContextValue(context, contextPath); - Assert.assertNotNull(value); - Assert.assertEquals(expected, value); - } - - protected static String getNodeContext(int... context) { - String result = ""; - for (int i : context) { - result += i; - } - return result; - } - - protected void assertNodeEquals(String contextPath, String nodeContext, int level, NavigationTreeNode node, boolean root) { - //System.out.println(contextPath + " : " + (node == null ? null : node.getContextPath())); - Assert.assertNotNull(node); - Assert.assertEquals(root, node.isRoot()); - Assert.assertEquals(level, node.getLevel()); - Assert.assertEquals(nodeContext, node.getContext()); - Assert.assertEquals(contextPath, node.getContextPath()); - } - - public static class Model { - - protected String name; - - protected int integerValue; - - protected List<Model> sons; - - public Model(String name, int integerValue, List<Model> sons) { - this.name = name; - this.integerValue = integerValue; - this.sons = sons; - } - - public String getName() { - return name; - } - - public int getIntegerValue() { - return integerValue; - } - - public List<Model> getSons() { - return sons; - } - - @Override - public String toString() { - return super.toString() + "<name:" + name + ",integerValue:" + integerValue + ",sons: " + sons + ">"; - } - } - -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation (from rev 1019, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/swing/navigation) Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java 2008-11-17 11:55:31 UTC (rev 1019) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,398 +0,0 @@ -package jaxx.runtime.swing.navigation; - -import jaxx.runtime.DefaultJAXXContext; -import jaxx.runtime.JAXXContext; -import jaxx.runtime.JAXXContextEntryDef; -import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - - -/** - * Test du model de navigation. - * - * @author chemit - */ -public class NavigationTreeModelTest { - - - private static final String ROOT_CONTEXT = "$root"; - private static final String FAKE = "-fake"; - private static final String DOT = "."; - - @Test - public void testFindNode() throws Exception { - - NavigationTreeNode rootNode = new NavigationTreeNode(ROOT_CONTEXT, null, null, null); - - for (int i = 0; i < 4; i++) { - NavigationTreeNode sonNode = new NavigationTreeNode(getNodeContext(i), null, null, null); - rootNode.insert(sonNode, i); - for (int j = 0; j < 4; j++) { - NavigationTreeNode sonSonNode = new NavigationTreeNode(getNodeContext(i, j), null, null, null); - sonNode.insert(sonSonNode, j); - for (int k = 0; k < 4; k++) { - sonSonNode.insert(new NavigationTreeNode(getNodeContext(i, j, k), null, null, null), k); - } - } - } - - NavigationTreeModel model = new NavigationTreeModel(rootNode); - - NavigationTreeNode node; - String contextPath; - String currentNode; - - contextPath = ROOT_CONTEXT; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, ROOT_CONTEXT, 0, node, true); - - node = model.findNode(ROOT_CONTEXT + FAKE); - Assert.assertNull(node); - - for (int i = 0; i < 4; i++) { - currentNode = getNodeContext(i); - contextPath = ROOT_CONTEXT + DOT + currentNode; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, currentNode, 1, node, false); - - for (int j = 0; j < 4; j++) { - currentNode = getNodeContext(i, j); - contextPath = ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + currentNode; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, currentNode, 2, node, false); - - for (int k = 0; k < 4; k++) { - currentNode = getNodeContext(i, j, k); - contextPath = ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + getNodeContext(i, j) + DOT + currentNode; - node = model.findNode(contextPath); - assertNodeEquals(contextPath, currentNode, 3, node, false); - } - - node = model.findNode(ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + getNodeContext(i, j) + DOT + currentNode + FAKE); - Assert.assertNull(node); - } - - node = model.findNode(ROOT_CONTEXT + DOT + getNodeContext(i) + DOT + currentNode + FAKE); - Assert.assertNull(node); - - } - - } - - /** - * Test the {@link NavigationTreeModel#getJAXXContextValue(jaxx.runtime.JAXXContext, String)} with an entry point - * as a bean. - * <p/> - * Tree is like this - * <pre> - * $root + - * - name <-- attached to context entry : java.lang.String.class,"name" - * - name2 <-- attached to context entry : java.lang.String.class,"name2" - * - model + <-- attached to context entry : Model.class,null - * - name - * -integerValue - * - sons + - * - 0 + - * - name - * - integerValue - * - sons - * - 1 + - * - name - * - integerValue - * - sons - * - 2 + - * - name - * - integerValue - * - sons - * </pre> - * <p/> - * With this tree, we will have to results : - * <pre> - * $root.name => context.get(String.class,"name") - * $root.name2 => context.get(String.class,"name2") - * $root.model => context.get(Model.class) - * $root.model.name => context.get(Model.class).getName() - * $root.model.integerValue => context.get(Model.class).getIntegerValue() - * $root.model.sons => context.get(Model.class).getSons() - * $root.model.sons.0 => context.get(Model.class).getSons().get(0) - * </pre> - * - * @throws Exception if any pb - */ - @Test - public void testGetJAXXContextValue() throws Exception { - - NavigationTreeNode rootNode = new NavigationTreeNode(ROOT_CONTEXT, null, null, null); - NavigationTreeNode sonNode; - NavigationTreeNode sonSonNode; - NavigationTreeNode sonSonSonNode; - - sonNode = new NavigationTreeNode("name", null, null, JAXXContextEntryDef.newDef("name", String.class)); - - rootNode.insert(sonNode, 0); - - sonNode = new NavigationTreeNode("name2", null, null, JAXXContextEntryDef.newDef("name2", String.class)); - - rootNode.insert(sonNode, 1); - - sonNode = new NavigationTreeNode("model", null, null, JAXXContextEntryDef.newDef(Model.class)); - - rootNode.insert(sonNode, 2); - - sonSonNode = new NavigationTreeNode("name", null, null, null); - sonNode.insert(sonSonNode, 0); - - sonSonNode = new NavigationTreeNode("integerValue", null, null, null); - sonNode.insert(sonSonNode, 1); - - sonSonNode = new NavigationTreeNode("sons", null, null, null); - sonNode.insert(sonSonNode, 2); - - sonSonSonNode = new NavigationTreeNode(0 + "", null, null, null); - sonSonNode.insert(sonSonSonNode, 0); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - sonSonSonNode = new NavigationTreeNode(1 + "", null, null, null); - sonSonNode.insert(sonSonSonNode, 1); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - sonSonSonNode = new NavigationTreeNode(2 + "", null, null, null); - sonSonNode.insert(sonSonSonNode, 2); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - NavigationTreeModel model = new NavigationTreeModel(rootNode); - - JAXXContext context = new DefaultJAXXContext(); - context.setContextValue("the name", "name"); - context.setContextValue("the name2", "name2"); - - - context.setContextValue( - new Model("modelName", 10, - Arrays.asList( - new Model("one", 1, Collections.<Model>emptyList()), - new Model("two", 2, Collections.<Model>emptyList()), - new Model("three", 3, Collections.<Model>emptyList()) - ) - ) - ); - - Assert.assertNull(model.getJAXXContextValue(context, "$root.name" + FAKE)); - - testBinding(model, context, "$root.name", context.getContextValue(String.class, "name")); - testBinding(model, context, "$root.name2", context.getContextValue(String.class, "name2")); - - Model bean = context.getContextValue(Model.class); - - testBinding(model, context, "$root.model", bean); - testBinding(model, context, "$root.model.name", bean.getName()); - testBinding(model, context, "$root.model.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.model.sons", bean.getSons()); - - testBinding(model, context, "$root.model.sons.0.name", bean.getSons().get(0).getName()); - testBinding(model, context, "$root.model.sons.0.integerValue", bean.getSons().get(0).getIntegerValue()); - testBinding(model, context, "$root.model.sons.0.sons", bean.getSons().get(0).getSons()); - - - testBinding(model, context, "$root.model.sons.1.name", bean.getSons().get(1).getName()); - testBinding(model, context, "$root.model.sons.1.integerValue", bean.getSons().get(1).getIntegerValue()); - testBinding(model, context, "$root.model.sons.1.sons", bean.getSons().get(1).getSons()); - - testBinding(model, context, "$root.model.sons.2.name", bean.getSons().get(2).getName()); - testBinding(model, context, "$root.model.sons.2.integerValue", bean.getSons().get(2).getIntegerValue()); - testBinding(model, context, "$root.model.sons.2.sons", bean.getSons().get(2).getSons()); - } - - /** - * Test the {@link NavigationTreeModel#getJAXXContextValue(jaxx.runtime.JAXXContext, String)} with an entry point - * as a list. - * <p/> - * Tree is like this - * <pre> - * $root + - * - models + <-- attached to context entry : java.util.List.class,"models" - * - 0 + - * - name - * -integerValue - * - sons + - * - 0 + - * - name - * - 1 + - * - name - * - integerValue - * - sons - * - 2 + - * - name - * - integerValue - * - sons - * </pre> - * <p/> - * With this tree, we will have to results : - * <pre> - * $root.models => context.get(List.class,"models") - * $root.models.0 => context.get(List.class,"models").get(0) - * $root.models.0.name => context.get(List.class,"models").get(0).getName() - * </pre> - * - * @throws Exception if any pb - */ - @Test - public void testGetJAXXContextValueFromList() throws Exception { - - NavigationTreeNode rootNode = new NavigationTreeNode(ROOT_CONTEXT, null, null, null); - NavigationTreeNode sonNode; - NavigationTreeNode sonSonNode; - NavigationTreeNode sonSonSonNode; - - // first son is a list of models - sonNode = new NavigationTreeNode("models", null, null, JAXXContextEntryDef.newListDef("models")); - rootNode.insert(sonNode, 0); - - // first son son is a model - sonSonNode = new NavigationTreeNode("0", null, null, null); - sonNode.insert(sonSonNode, 0); - - sonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonNode.insert(sonSonSonNode = new NavigationTreeNode("sons", null, null, null), 2); - - sonSonSonNode.insert(sonSonSonNode = new NavigationTreeNode("0", null, null, null), 0); - sonSonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - - // second son son is a model - sonSonNode = new NavigationTreeNode("1", null, null, null); - sonNode.insert(sonSonNode, 1); - sonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - // third son son is a model - sonSonNode = new NavigationTreeNode("2", null, null, null); - sonNode.insert(sonSonNode, 2); - sonSonNode.insert(new NavigationTreeNode("name", null, null, null), 0); - sonSonNode.insert(new NavigationTreeNode("integerValue", null, null, null), 1); - sonSonNode.insert(new NavigationTreeNode("sons", null, null, null), 2); - - NavigationTreeModel model = new NavigationTreeModel(rootNode); - - JAXXContext context = new DefaultJAXXContext(); - List<Model> list = new ArrayList<Model>(); - list.add(new Model("entryOne", 10, - Arrays.asList( - new Model("one", 1, Collections.<Model>emptyList()), - new Model("two", 2, Collections.<Model>emptyList()), - new Model("three", 3, Collections.<Model>emptyList()) - ) - )); - list.add(new Model("entryTwo", 20, - Arrays.asList( - new Model("2one", 1, Collections.<Model>emptyList()), - new Model("2two", 2, Collections.<Model>emptyList()), - new Model("2three", 3, Collections.<Model>emptyList()) - ) - )); - list.add(new Model("entryThree", 30, - Arrays.asList( - new Model("3one", 1, Collections.<Model>emptyList()), - new Model("3two", 2, Collections.<Model>emptyList()), - new Model("3three", 3, Collections.<Model>emptyList()) - ) - )); - context.setContextValue(list, "models"); - - Model bean; - - testBinding(model, context, "$root.models", list); - - bean = list.get(0); - testBinding(model, context, "$root.models.0", bean); - testBinding(model, context, "$root.models.0.name", bean.getName()); - testBinding(model, context, "$root.models.0.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.models.0.sons", bean.getSons()); - testBinding(model, context, "$root.models.0.sons.0", bean.getSons().get(0)); - testBinding(model, context, "$root.models.0.sons.0.name", bean.getSons().get(0).getName()); - - bean = list.get(1); - testBinding(model, context, "$root.models.1", bean); - testBinding(model, context, "$root.models.1.name", bean.getName()); - testBinding(model, context, "$root.models.1.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.models.1.sons", bean.getSons()); - - bean = list.get(2); - testBinding(model, context, "$root.models.2", bean); - testBinding(model, context, "$root.models.2.name", bean.getName()); - testBinding(model, context, "$root.models.2.integerValue", bean.getIntegerValue()); - testBinding(model, context, "$root.models.2.sons", bean.getSons()); - - } - - protected void testBinding(NavigationTreeModel model, JAXXContext context, String contextPath, Object expected) throws Exception { - - Object value; - value = model.getJAXXContextValue(context, contextPath); - Assert.assertNotNull(value); - Assert.assertEquals(expected, value); - } - - protected static String getNodeContext(int... context) { - String result = ""; - for (int i : context) { - result += i; - } - return result; - } - - protected void assertNodeEquals(String contextPath, String nodeContext, int level, NavigationTreeNode node, boolean root) { - //System.out.println(contextPath + " : " + (node == null ? null : node.getContextPath())); - Assert.assertNotNull(node); - Assert.assertEquals(root, node.isRoot()); - Assert.assertEquals(level, node.getLevel()); - Assert.assertEquals(nodeContext, node.getContext()); - Assert.assertEquals(contextPath, node.getContextPath()); - } - - public static class Model { - - protected String name; - - protected int integerValue; - - protected List<Model> sons; - - public Model(String name, int integerValue, List<Model> sons) { - this.name = name; - this.integerValue = integerValue; - this.sons = sons; - } - - public String getName() { - return name; - } - - public int getIntegerValue() { - return integerValue; - } - - public List<Model> getSons() { - return sons; - } - - @Override - public String toString() { - return super.toString() + "<name:" + name + ",integerValue:" + integerValue + ",sons: " + sons + ">"; - } - } - -} Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java (from rev 1035, lutinjaxx/trunk/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/java/jaxx/runtime/swing/navigation/NavigationTreeModelTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,393 @@ +package jaxx.runtime.swing.navigation; + +import jaxx.runtime.DefaultJAXXContext; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXContextEntryDef; +import jaxx.runtime.swing.navigation.NavigationTreeModel.NavigationTreeNode; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +/** + * Test du model de navigation. + * + * @author chemit + */ +public class NavigationTreeModelTest { + + private static final String ROOT_CONTEXT = "$root"; + private static final String FAKE = "-fake"; + + private static final String separator = "/"; + + @Test + public void testFindNode() throws Exception { + + NavigationTreeModelBuilder builder = new NavigationTreeModelBuilder(separator); + + NavigationTreeNode rootNode = builder.build(null, (String) null, (String) null, ROOT_CONTEXT, null, null); + + for (int i = 0; i < 4; i++) { + NavigationTreeNode sonNode = builder.build(rootNode, (String) null, (String) null, getNodeContext(i), null, null); + for (int j = 0; j < 4; j++) { + NavigationTreeNode sonSonNode = builder.build(sonNode, (String) null, (String) null, getNodeContext(i, j), null, null); + for (int k = 0; k < 4; k++) { + builder.build(sonSonNode, (String) null, (String) null, getNodeContext(i, j, k), null, null); + } + } + } + + NavigationTreeModel model = builder.getModel(); + + NavigationTreeNode node; + String contextPath; + String currentNode; + + contextPath = ROOT_CONTEXT; + node = model.findNode(contextPath); + assertNodeEquals(contextPath, ROOT_CONTEXT, 0, node, true); + + node = model.findNode(ROOT_CONTEXT + FAKE); + Assert.assertNull(node); + + for (int i = 0; i < 4; i++) { + currentNode = getNodeContext(i); + contextPath = ROOT_CONTEXT + separator + currentNode; + node = model.findNode(contextPath); + assertNodeEquals(contextPath, currentNode, 1, node, false); + + for (int j = 0; j < 4; j++) { + currentNode = getNodeContext(i, j); + contextPath = ROOT_CONTEXT + separator + getNodeContext(i) + separator + currentNode; + node = model.findNode(contextPath); + assertNodeEquals(contextPath, currentNode, 2, node, false); + + for (int k = 0; k < 4; k++) { + currentNode = getNodeContext(i, j, k); + contextPath = ROOT_CONTEXT + separator + getNodeContext(i) + separator + getNodeContext(i, j) + separator + currentNode; + node = model.findNode(contextPath); + assertNodeEquals(contextPath, currentNode, 3, node, false); + } + + node = model.findNode(ROOT_CONTEXT + separator + getNodeContext(i) + separator + getNodeContext(i, j) + separator + currentNode + FAKE); + Assert.assertNull(node); + } + + node = model.findNode(ROOT_CONTEXT + separator + getNodeContext(i) + separator + currentNode + FAKE); + Assert.assertNull(node); + + } + + } + + /** + * Test the {@link NavigationTreeModel#getJAXXContextValue(jaxx.runtime.JAXXContext, String)} with an entry point + * as a bean. + * <p/> + * Tree is like this + * <pre> + * $root + + * - name <-- attached to context entry : java.lang.String.class,"name" + * - name2 <-- attached to context entry : java.lang.String.class,"name2" + * - model + <-- attached to context entry : Model.class,null + * - name + * -integerValue + * - sons + + * - 0 + + * - name + * - integerValue + * - sons + * - 1 + + * - name + * - integerValue + * - sons + * - 2 + + * - name + * - integerValue + * - sons + * </pre> + * <p/> + * With this tree, we will have to results : + * <pre> + * $root.name => context.get(String.class,"name") + * $root.name2 => context.get(String.class,"name2") + * $root.model => context.get(Model.class) + * $root.model.name => context.get(Model.class).getName() + * $root.model.integerValue => context.get(Model.class).getIntegerValue() + * $root.model.sons => context.get(Model.class).getSons() + * $root.model.sons.0 => context.get(Model.class).getSons().get(0) + * </pre> + * + * @throws Exception if any pb + */ + @Test + public void testGetJAXXContextValue() throws Exception { + + NavigationTreeModelBuilder builder = new NavigationTreeModelBuilder(separator); + + NavigationTreeNode rootNode = builder.build(null, (String) null, (String) null, ROOT_CONTEXT, null, null); + + NavigationTreeNode sonNode; + NavigationTreeNode sonSonNode; + NavigationTreeNode sonSonSonNode; + + builder.build(rootNode, (String) null, JAXXContextEntryDef.newDef("name", String.class), "name", null, null); + builder.build(rootNode, (String) null, JAXXContextEntryDef.newDef("name2", String.class), "name2", null, null); + + sonNode = builder.build(rootNode, (String) null, JAXXContextEntryDef.newDef(Model.class), "model", null, null); + + builder.build(sonNode, (String) null, "../name", "name", null, null); + builder.build(sonNode, (String) null, "../integerValue", "integerValue", null, null); + + sonSonNode = builder.build(sonNode, (String) null, "../sons", "sons", null, null); + + sonSonSonNode = builder.build(sonSonNode, (String) null, "..[1]", 0 + "", null, null); + + builder.build(sonSonSonNode, (String) null, "../name", "name", null, null); + builder.build(sonSonSonNode, (String) null, "../integerValue", "integerValue", null, null); + builder.build(sonSonSonNode, (String) null, "../sons", "sons", null, null); + + sonSonSonNode = builder.build(sonSonNode, (String) null, "..[2]", 1 + "", null, null); + + builder.build(sonSonSonNode, (String) null, "../name", "name", null, null); + builder.build(sonSonSonNode, (String) null, "../integerValue", "integerValue", null, null); + builder.build(sonSonSonNode, (String) null, "../sons", "sons", null, null); + + sonSonSonNode = builder.build(sonSonNode, (String) null, (String) null, 2 + "", null, null); + //sonSonSonNode = model.new NavigationTreeNode(null, "..[3]", 2 + "", null, null); + sonSonNode.insert(sonSonSonNode, 2); + builder.build(sonSonSonNode, (String) null, "../..[3]/name", "name", null, null); + builder.build(sonSonSonNode, (String) null, "../..[3]/integerValue", "integerValue", null, null); + builder.build(sonSonSonNode, (String) null, "../..[3]/sons", "sons", null, null); + + NavigationTreeModel model = builder.getModel(); + + JAXXContext context = new DefaultJAXXContext(); + context.setContextValue("the name", "name"); + context.setContextValue("the name2", "name2"); + + + context.setContextValue( + new Model("modelName", 10, + Arrays.asList( + new Model("one", 1, Collections.<Model>emptyList()), + new Model("two", 2, Collections.<Model>emptyList()), + new Model("three", 3, Collections.<Model>emptyList()) + ) + ) + ); + + Assert.assertNull(model.getJAXXContextValue(context, "$root.name" + FAKE)); + + testBinding(model, context, "$root/name", context.getContextValue(String.class, "name")); + testBinding(model, context, "$root/name2", context.getContextValue(String.class, "name2")); + + Model bean = context.getContextValue(Model.class); + + testBinding(model, context, "$root/model", bean); + testBinding(model, context, "$root/model/name", bean.getName()); + testBinding(model, context, "$root/model/integerValue", bean.getIntegerValue()); + testBinding(model, context, "$root/model/sons", bean.getSons()); + + testBinding(model, context, "$root/model/sons/0/name", bean.getSons().get(0).getName()); + testBinding(model, context, "$root/model/sons/0/integerValue", bean.getSons().get(0).getIntegerValue()); + testBinding(model, context, "$root/model/sons/0/sons", bean.getSons().get(0).getSons()); + + + testBinding(model, context, "$root/model/sons/1/name", bean.getSons().get(1).getName()); + testBinding(model, context, "$root/model/sons/1/integerValue", bean.getSons().get(1).getIntegerValue()); + testBinding(model, context, "$root/model/sons/1/sons", bean.getSons().get(1).getSons()); + + testBinding(model, context, "$root/model/sons/2/name", bean.getSons().get(2).getName()); + testBinding(model, context, "$root/model/sons/2/integerValue", bean.getSons().get(2).getIntegerValue()); + testBinding(model, context, "$root/model/sons/2/sons", bean.getSons().get(2).getSons()); + } + + /** + * Test the {@link NavigationTreeModel#getJAXXContextValue(jaxx.runtime.JAXXContext, String)} with an entry point + * as a list. + * <p/> + * Tree is like this + * <pre> + * $root + + * - models + <-- attached to context entry : java.util.List.class,"models" + * - 0 + + * - name + * -integerValue + * - sons + + * - 0 + + * - name + * - 1 + + * - name + * - integerValue + * - sons + * - 2 + + * - name + * - integerValue + * - sons + * </pre> + * <p/> + * With this tree, we will have to results : + * <pre> + * $root.models => context.get(List.class,"models") + * $root.models.0 => context.get(List.class,"models").get(0) + * $root.models.0.name => context.get(List.class,"models").get(0).getName() + * </pre> + * + * @throws Exception if any pb + */ + @Test + public void testGetJAXXContextValueFromList() throws Exception { + + NavigationTreeModelBuilder builder = new NavigationTreeModelBuilder(separator); + + NavigationTreeNode rootNode = builder.build(null, (String) null, (String) null, ROOT_CONTEXT, null, null); + + NavigationTreeNode sonNode; + NavigationTreeNode sonSonNode; + NavigationTreeNode sonSonSonNode; + + // first son is a list of models + sonNode = builder.build(rootNode, (String) null, JAXXContextEntryDef.newListDef("models"), "models", null, null); + + // first son son is a model + sonSonNode = builder.build(sonNode, (String) null, "..[1]", "0", null, null); + + builder.build(sonSonNode, (String) null, "../name", "name", null, null); + builder.build(sonSonNode, (String) null, "../integerValue", "integerValue", null, null); + sonSonNode = builder.build(sonSonNode, (String) null, "../sons", "sons", null, null); + + sonSonSonNode = builder.build(sonSonNode, (String) null, "..[1]", "0", null, null); + builder.build(sonSonSonNode, (String) null, "../name", "name", null, null); + + // second son son is a model + sonSonNode = builder.build(sonNode, (String) null, "..[2]", "1", null, null); + + builder.build(sonSonNode, (String) null, "../name", "name", null, null); + builder.build(sonSonNode, (String) null, "../integerValue", "integerValue", null, null); + builder.build(sonSonNode, (String) null, "../sons", "sons", null, null); + + // third son son is a model + sonSonNode = builder.build(sonNode, (String) null, "..[3]", "2", null, null); + + builder.build(sonSonNode, (String) null, "../name", "name", null, null); + builder.build(sonSonNode, (String) null, "../integerValue", "integerValue", null, null); + builder.build(sonSonNode, (String) null, "../sons", "sons", null, null); + + NavigationTreeModel model = builder.getModel(); + + + List<Model> list = Arrays.asList( + new Model("entryOne", 10, + Arrays.asList( + new Model("one", 1, Collections.<Model>emptyList()), + new Model("two", 2, Collections.<Model>emptyList()), + new Model("three", 3, Collections.<Model>emptyList()) + ) + ), + new Model("entryTwo", 20, + Arrays.asList( + new Model("2one", 1, Collections.<Model>emptyList()), + new Model("2two", 2, Collections.<Model>emptyList()), + new Model("2three", 3, Collections.<Model>emptyList()) + ) + ), + new Model("entryThree", 30, + Arrays.asList( + new Model("3one", 1, Collections.<Model>emptyList()), + new Model("3two", 2, Collections.<Model>emptyList()), + new Model("3three", 3, Collections.<Model>emptyList()) + ) + ) + ); + JAXXContext context = new DefaultJAXXContext(); + context.setContextValue(list, "models"); + + Model bean; + + testBinding(model, context, "$root/models", list); + + bean = list.get(0); + testBinding(model, context, "$root/models/0", bean); + testBinding(model, context, "$root/models/0/name", bean.getName()); + testBinding(model, context, "$root/models/0/integerValue", bean.getIntegerValue()); + testBinding(model, context, "$root/models/0/sons", bean.getSons()); + testBinding(model, context, "$root/models/0/sons/0", bean.getSons().get(0)); + testBinding(model, context, "$root/models/0/sons/0/name", bean.getSons().get(0).getName()); + + bean = list.get(1); + testBinding(model, context, "$root/models/1", bean); + testBinding(model, context, "$root/models/1/name", bean.getName()); + testBinding(model, context, "$root/models/1/integerValue", bean.getIntegerValue()); + testBinding(model, context, "$root/models/1/sons", bean.getSons()); + + bean = list.get(2); + testBinding(model, context, "$root/models/2", bean); + testBinding(model, context, "$root/models/2/name", bean.getName()); + testBinding(model, context, "$root/models/2/integerValue", bean.getIntegerValue()); + testBinding(model, context, "$root/models/2/sons", bean.getSons()); + + } + + protected void testBinding(NavigationTreeModel model, JAXXContext context, String contextPath, Object expected) throws Exception { + + Object value; + value = model.getJAXXContextValue(context, contextPath); + Assert.assertNotNull(value); + Assert.assertEquals(expected, value); + } + + protected String getNodeContext(int... context) { + String result = ""; + for (int i : context) { + result += i; + } + return result; + } + + protected void assertNodeEquals(String contextPath, String nodeContext, int level, NavigationTreeNode node, boolean root) { + //System.out.println(contextPath + " : " + (node == null ? null : node.getContextPath())); + Assert.assertNotNull(node); + Assert.assertEquals(root, node.isRoot()); + Assert.assertEquals(level, node.getLevel()); + Assert.assertEquals(nodeContext, node.getNavigationPath()); + Assert.assertEquals(contextPath, node.getContextPath()); + } + + public static class Model { + + protected String name; + + protected int integerValue; + + protected List<Model> sons; + + public Model(String name, int integerValue, List<Model> sons) { + this.name = name; + this.integerValue = integerValue; + this.sons = sons; + } + + public String getName() { + return name; + } + + public int getIntegerValue() { + return integerValue; + } + + public List<Model> getSons() { + return sons; + } + + @Override + public String toString() { + return super.toString() + "<name:" + name + ",integerValue:" + integerValue + ",sons: " + sons + ">"; + } + } + +} Deleted: lutinjaxx/tags/0.7/jaxx-core/src/test/resources/log4j.properties =================================================================== --- lutinjaxx/trunk/jaxx-core/src/test/resources/log4j.properties 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/resources/log4j.properties 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,9 +0,0 @@ -# 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 Copied: lutinjaxx/tags/0.7/jaxx-core/src/test/resources/log4j.properties (from rev 1011, lutinjaxx/trunk/jaxx-core/src/test/resources/log4j.properties) =================================================================== --- lutinjaxx/tags/0.7/jaxx-core/src/test/resources/log4j.properties (rev 0) +++ lutinjaxx/tags/0.7/jaxx-core/src/test/resources/log4j.properties 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,8 @@ +# 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.jaxx=DEBUG Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding (from rev 1016, lutinjaxx/trunk/jaxx-example/BeanDataBinding) Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/BeanDataBinding/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/changelog.txt (from rev 1059, lutinjaxx/trunk/jaxx-example/BeanDataBinding/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,3 @@ +0.7 chemit 200812?? + * 20081208 [chemit] javaBean attribute use to initialize bean + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/BeanDataBinding/pom.xml 2008-11-16 17:42:00 UTC (rev 1016) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,46 +0,0 @@ -<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.6-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.jaxx-example</groupId> - <artifactId>BeanDataBinding</artifactId> - - <dependencies> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>maven-jaxx-plugin</artifactId> - <version>0.6-SNAPSHOT</version> - </dependency> - </dependencies> - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>Bean DataBinding example</name> - <description>Jaxx Bean DataBinding extension 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 Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-example/BeanDataBinding/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -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.7</version> + </parent> + + <groupId>org.codelutin.jaxx-example</groupId> + <artifactId>BeanDataBinding</artifactId> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>Bean DataBinding example</name> + <description>Jaxx Bean DataBinding extension example</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding?root=buix</url> + </scm> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx =================================================================== --- lutinjaxx/trunk/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx 2008-11-16 17:42:00 UTC (rev 1016) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,20 +0,0 @@ -<Application title='{getContentMessage()}'> - <!-- a full java bean property of the class --> - <Boolean id='editing' constructorParams='false' javaBean='anyvalue'/> - - <!-- not full java bean property (must add script...) --> - <Boolean id='editing2' constructorParams='false'/> - - <String id='contentMessage' constructorParams='"message..."' javaBean='anyvalue'/> - - <script> - public Boolean isEditing2() { return editing2; } - - public void setEditing2(Boolean newValue) { - Boolean oldValue = this.editing2; - this.editing2 = newValue; - firePropertyChange("editing2", oldValue, newValue) ; - } - </script> - -</Application> Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx (from rev 1059, lutinjaxx/trunk/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BaseBeanDataBinding.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,20 @@ +<Application title='{getContentMessage()}'> + <!-- a full java bean property of the class --> + <Boolean id='editing' javaBean='false'/> + + <!-- not full java bean property (must add script...) --> + <Boolean id='editing2' constructorParams='false'/> + + <String id='contentMessage' javaBean='"message..."'/> + + <script> + public Boolean isEditing2() { return editing2; } + + public void setEditing2(Boolean newValue) { + Boolean oldValue = this.editing2; + this.editing2 = newValue; + firePropertyChange("editing2", oldValue, newValue) ; + } + </script> + +</Application> Deleted: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx =================================================================== --- lutinjaxx/trunk/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx 2008-11-16 17:42:00 UTC (rev 1016) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,41 +0,0 @@ -<BaseBeanDataBinding layout='{new GridLayout()}'> -<!--BaseBeanDataBinding title="BeanDataBinding.jaxx" layout='{new GridLayout()}'--> - - <Boolean id='editing3' constructorParams='true' javaBean='anyvalue'/> - - <Table> - <row> - <cell> - <JPanel> - <JButton visible='{!isEditing()}' text='edit' onActionPerformed='setEditing(true);'/> - <JButton visible='{isEditing()}' text='close' onActionPerformed='setEditing(false);'/> - </JPanel> - </cell> - <cell weightx='1' fill='both'> - <JTextField enabled='{isEditing()}' text='to edit'/> - </cell> - </row> - <row> - <cell> - <JPanel> - <JButton visible='{!isEditing2()}' text='edit2' onActionPerformed='setEditing2(true);'/> - <JButton visible='{isEditing2()}' text='close2' onActionPerformed='setEditing2(false);'/> - </JPanel> - </cell> - <cell weightx='1' fill='both'> - <JTextField enabled='{isEditing2()}' text="to edit 2"/> - </cell> - </row> - <row> - <cell> - <JPanel> - <JButton visible='{!isEditing3()}' text='edit3' onActionPerformed='setEditing3(true);'/> - <JButton visible='{isEditing3()}' text='close3' onActionPerformed='setEditing3(false);'/> - </JPanel> - </cell> - <cell weightx='1' fill='both'> - <JTextField id='edit3' enabled='{isEditing3()}' text="{getContentMessage()}" onKeyReleased='setContentMessage(edit3.getText())'/> - </cell> - </row> - </Table> -</BaseBeanDataBinding> Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx (from rev 1059, lutinjaxx/trunk/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/main/java/examples/BeanDataBinding/BeanDataBinding.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,40 @@ +<BaseBeanDataBinding layout='{new GridLayout()}'> + + <Boolean id='editing3' javaBean='true'/> + + <Table> + <row> + <cell> + <JPanel> + <JButton visible='{!isEditing()}' text='edit' onActionPerformed='setEditing(true);'/> + <JButton visible='{isEditing()}' text='close' onActionPerformed='setEditing(false);'/> + </JPanel> + </cell> + <cell weightx='1' fill='both'> + <JTextField enabled='{isEditing()}' text='to edit'/> + </cell> + </row> + <row> + <cell> + <JPanel> + <JButton visible='{!isEditing2()}' text='edit2' onActionPerformed='setEditing2(true);'/> + <JButton visible='{isEditing2()}' text='close2' onActionPerformed='setEditing2(false);'/> + </JPanel> + </cell> + <cell weightx='1' fill='both'> + <JTextField enabled='{isEditing2()}' text="to edit 2"/> + </cell> + </row> + <row> + <cell> + <JPanel> + <JButton visible='{!isEditing3()}' text='edit3' onActionPerformed='setEditing3(true);'/> + <JButton visible='{isEditing3()}' text='close3' onActionPerformed='setEditing3(false);'/> + </JPanel> + </cell> + <cell weightx='1' fill='both'> + <JTextField id='edit3' enabled='{isEditing3()}' text="{getContentMessage()}" onKeyReleased='setContentMessage(edit3.getText())'/> + </cell> + </row> + </Table> +</BaseBeanDataBinding> Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/images/BeanDataBinding-screenshot.png (from rev 1050, lutinjaxx/trunk/jaxx-example/BeanDataBinding/src/site/fr/rst/images/BeanDataBinding-screenshot.png) =================================================================== (Binary files differ) Deleted: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/images/Validation-screenshot.png =================================================================== (Binary files differ) Deleted: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst =================================================================== --- lutinjaxx/trunk/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst 2008-11-16 17:42:00 UTC (rev 1016) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,28 +0,0 @@ -=================== -Examples/Validation -=================== - -This example program creates a number of components which are used to control the appearance of a JLabel. -Everything is performed through data binding; there are no script tags or explicit event handlers anywhere. - -Screen shot ------------ - -.. image:: images/Validation-screenshot.png - -Set it in action ----------------- - -|webstart| - -To run this example in `Java Web Start`_, click the `following link`_. - - -Source code ------------ - -.. _Java Web Start: http://java.sun.com/products/javawebstart/ - -.. |webstart| image:: images/webstart.gif - -.. _following link: ./launch-Validation.jnlp Copied: lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst (from rev 1050, lutinjaxx/trunk/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/BeanDataBinding/src/site/fr/rst/index.rst 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,27 @@ +======================== +Examples/BeanDataBinding +======================== + +This example program tests the bean data binding with the full java bean support. + +Screen shot +----------- + +.. image:: images/BeanDataBinding-screenshot.png + +Set it in action +---------------- + +|webstart| + +To run this example in `Java Web Start`_, click the `following link`_. + + +Source code +----------- + +.. _Java Web Start: http://java.sun.com/products/javawebstart/ + +.. |webstart| image:: images/webstart.gif + +.. _following link: ./launch-BeanDataBinding.jnlp Copied: lutinjaxx/tags/0.7/jaxx-example/Calculator/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Calculator/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Calculator/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Calculator/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-example/Calculator/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Calculator/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Calculator/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Calculator/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/Calculator/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Calculator/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-example/Calculator/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,40 +0,0 @@ -<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.6-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 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.7/jaxx-example/Calculator/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-example/Calculator/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Calculator/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Calculator/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -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.7</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.7/jaxx-example/Calculator</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/Calculator</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-example/Calculator?root=buix</url> + </scm> + +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-example/Components (from rev 1004, lutinjaxx/trunk/jaxx-example/Components) Copied: lutinjaxx/tags/0.7/jaxx-example/Components/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Components/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Components/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Components/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-example/Components/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Components/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Components/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Components/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/Components/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Components/pom.xml 2008-10-27 17:04:20 UTC (rev 1004) +++ lutinjaxx/tags/0.7/jaxx-example/Components/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,41 +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.6-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 Copied: lutinjaxx/tags/0.7/jaxx-example/Components/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-example/Components/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Components/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Components/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,48 @@ +<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.7</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> + <resources> + <resource> + <directory>src/main/java</directory> + <includes> + <include>**/*.jaxx</include> + </includes> + </resource> + </resources> + </build> + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/Components</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/Components</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-example/Components?root=buix</url> + </scm> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx =================================================================== --- lutinjaxx/trunk/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx 2008-10-27 17:04:20 UTC (rev 1004) +++ lutinjaxx/tags/0.7/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,78 +0,0 @@ -<DemoPanel> - <script> - String username; - String password; - - private class OKAction extends javax.swing.AbstractAction { - public OKAction() { - putValue(NAME, "OK"); - } - - - public void actionPerformed(ActionEvent e) { - username = usernameField.getText(); - password = new String(passwordField.getPassword()); - dialog.dispose(); - } - } - - - private class CancelAction extends javax.swing.AbstractAction { - public CancelAction() { - putValue(NAME, "Cancel"); - } - - - public void actionPerformed(ActionEvent e) { - dialog.dispose(); - } - } - - JRootPane rootPane = dialog.getRootPane(); - rootPane.setDefaultButton(ok); - rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "cancel"); - rootPane.getActionMap().put("cancel", new CancelAction()); - </script> - - <JDialog title='Sign on' id='dialog' modal='true' onWindowOpened='dialog.setLocationRelativeTo(demoPanel); - passwordField.setText("");'> - <Table> - <row> - <cell> - <JLabel text='Username:' displayedMnemonic='U' labelFor='{usernameField}'/> - </cell> - - <cell> - <JTextField id='usernameField'/> - </cell> - </row> - - <row> - <cell> - <JLabel text='Password:' displayedMnemonic='P' labelFor='{passwordField}'/> - </cell> - - <cell> - <JPasswordField id='passwordField'/> - </cell> - </row> - - <row> - <cell columns='2'> - <JPanel layout='{new GridLayout(1, 0, 6, 6)}'> - <JButton id='ok' text='OK' action='{new OKAction()}'/> - <JButton text='Cancel' action='{new CancelAction()}'/> - </JPanel> - </cell> - </row> - </Table> - </JDialog> - - <VBox id='demoPanel' horizontalAlignment='center' verticalAlignment='middle'> - <JButton text='Show password dialog' onActionPerformed='dialog.setVisible(true)'/> - <VBox> - <JLabel text='{username != null ? "Username: " + username : ""}'/> - <JLabel text='{password != null ? "Password: " + password : ""}'/> - </VBox> - </VBox> -</DemoPanel> \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx (from rev 1016, lutinjaxx/trunk/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Components/src/main/java/examples/Components/JDialogDemo.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,79 @@ +<DemoPanel> + <script> + String username; + String password; + + private class OKAction extends javax.swing.AbstractAction { + public OKAction() { + putValue(NAME, "OK"); + } + + + public void actionPerformed(ActionEvent e) { + username = usernameField.getText(); + password = new String(passwordField.getPassword()); + dialog.dispose(); + } + } + + + private class CancelAction extends javax.swing.AbstractAction { + public CancelAction() { + putValue(NAME, "Cancel"); + } + + + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + } + } + { + JRootPane rootPane = dialog.getRootPane(); + rootPane.setDefaultButton(ok); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "cancel"); + rootPane.getActionMap().put("cancel", new CancelAction()); + } + </script> + + <JDialog title='Sign on' id='dialog' modal='true' onWindowOpened='dialog.setLocationRelativeTo(demoPanel); + passwordField.setText("");'> + <Table> + <row> + <cell> + <JLabel text='Username:' displayedMnemonic='U' labelFor='{usernameField}'/> + </cell> + + <cell> + <JTextField id='usernameField'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Password:' displayedMnemonic='P' labelFor='{passwordField}'/> + </cell> + + <cell> + <JPasswordField id='passwordField'/> + </cell> + </row> + + <row> + <cell columns='2'> + <JPanel layout='{new GridLayout(1, 0, 6, 6)}'> + <JButton id='ok' text='OK' action='{new OKAction()}'/> + <JButton text='Cancel' action='{new CancelAction()}'/> + </JPanel> + </cell> + </row> + </Table> + </JDialog> + + <VBox id='demoPanel' horizontalAlignment='center' verticalAlignment='middle'> + <JButton text='Show password dialog' onActionPerformed='dialog.setVisible(true)'/> + <VBox> + <JLabel text='{username != null ? "Username: " + username : ""}'/> + <JLabel text='{password != null ? "Password: " + password : ""}'/> + </VBox> + </VBox> +</DemoPanel> \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-example/Counter/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Counter/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Counter/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Counter/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-example/Counter/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Counter/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Counter/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Counter/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/Counter/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Counter/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-example/Counter/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,39 +0,0 @@ -<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.6-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 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.7/jaxx-example/Counter/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-example/Counter/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Counter/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Counter/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -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.7</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.7/jaxx-example/Counter</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/Counter</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-example/Counter?root=buix</url> + </scm> +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-example/LabelStyle/README.txt (from rev 1058, lutinjaxx/trunk/jaxx-example/LabelStyle/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/LabelStyle/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/LabelStyle/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-example/LabelStyle/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/LabelStyle/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/LabelStyle/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/LabelStyle/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/LabelStyle/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/LabelStyle/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-example/LabelStyle/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,39 +0,0 @@ -<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.6-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 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.7/jaxx-example/LabelStyle/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-example/LabelStyle/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/LabelStyle/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/LabelStyle/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -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.7</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.7/jaxx-example/LabelStyle</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/LabelStyle</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-example/LabelStyle?root=buix</url> + </scm> +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-example/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-example/Validation/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Validation/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Validation/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Validation/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-example/Validation/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/Validation/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Validation/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Validation/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/Validation/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/Validation/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-example/Validation/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,39 +0,0 @@ -<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.6-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 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.7/jaxx-example/Validation/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-example/Validation/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/Validation/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/Validation/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -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.7</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.7/jaxx-example/Validation</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example/Validation</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-example/Validation?root=buix</url> + </scm> +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-example/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-example/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-example/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-example/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-example/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,262 +0,0 @@ -<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.6-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.6-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_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 Copied: lutinjaxx/tags/0.7/jaxx-example/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-example/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-example/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-example/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,256 @@ +<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.7</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> + <module>BeanDataBinding</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> + + </properties> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-example</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-example?root=buix</url> + </scm> + + <build> + <pluginManagement> + <plugins> + + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-jaxx-plugin</artifactId> + <version>${project.version}</version> + <configuration> + <src>${basedir}/src/main/java</src> + <force>true</force> + </configuration> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <configuration> + <outputDirectory>${project.build.directory}/lib</outputDirectory> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <classpathPrefix>./lib/</classpathPrefix> + </manifest> + </archive> + </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> + + <profiles> + <!-- by default example are included, use -Ddoexample=false to disable examples --> + <profile> + <id>dojnlp</id> + <activation> + <property> + <name>dojnlp</name> + <value>!false</value> + </property> + </activation> + <build> + <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.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> + </build> + </profile> + </profiles> + +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-swing-action/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-swing-action/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-swing-action/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-swing-action/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Deleted: lutinjaxx/tags/0.7/jaxx-swing-action/changelog =================================================================== --- lutinjaxx/trunk/jaxx-swing-action/changelog 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-swing-action/changelog 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,10 +0,0 @@ -ver-0-5 chemit 20081002 - * 20081002 [chemit] Using lutinproject 3.0, changing groupId to org.codelutin - -jaxx-swing-action (0.4) stable; urgency=high - - * bug correction when have to compile actions but not the baseAction, providerConfig was null - * bug correction when action herites from another not base action, the action has te be treated after the mother action - * usemaven-i18n-plugin v0.4 - - -- Tony Chemit <chemit@codelutin.com> Fri, 05 Aug 2008 02:02:02 +0200 Copied: lutinjaxx/tags/0.7/jaxx-swing-action/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-swing-action/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-swing-action/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-swing-action/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-swing-action/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-swing-action/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-swing-action/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,74 +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.6-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.7/jaxx-swing-action/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-swing-action/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-swing-action/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-swing-action/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,78 @@ +<?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.7</version> + </parent> + + <artifactId>jaxx-swing-action</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-util</artifactId> + </dependency> + + <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> + <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.7/jaxx-swing-action</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-swing-action</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-swing-action?root=buix</url> + </scm> + +</project> Deleted: lutinjaxx/tags/0.7/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java =================================================================== --- lutinjaxx/trunk/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,405 +0,0 @@ -/* -* ##% Copyright (C) 2007, 2008 Code Lutin, Tony Chemit -* -* 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.action; - -import jaxx.runtime.JAXXObject; -import jaxx.runtime.swing.JAXXToggleButton; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.swing.AbstractButton; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import java.awt.event.ActionEvent; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.ServiceLoader; -import java.util.Set; -import java.util.TreeMap; - -/** - * A simple implementation of {@link ActionFactory} using some {@link ActionProvider} to seek actions. - * <p/> - * <p/> - * An entry is in that form : <code>action.actionName=fqn</code> where - * <p/> - * <code>actionName</code> is the key of action used in factory, and - * <code>fqn</code> is the fully qualified name of the implemented action class. - * <p/> - * A special clase is to have for a given entry a key like this : <code>action.:fqn'=fqn</code>, in that case, - * le fqn' is a classe of type {@link org.codelutin.jaxx.action.ActionNameProvider} which gives us at - * runtime the names of each entry to put in cache for the givne action fqn. - * - * @author chemit - */ -public class ActionFactoryFromProvider<A extends MyAbstractAction> implements ActionFactory<A> { - - protected static Log log = LogFactory.getLog(ActionFactoryFromProvider.class); - - public static <A extends MyAbstractAction> ActionFactory<A> newInstance(Class<A> klazz) { - return new ActionFactoryFromProvider<A>(klazz); - } - - /** class of encapsuling action */ - protected Class<A> baseImpl; - - /** dictionary of known actions implementations */ - private Map<String, Class<? extends MyAbstractAction>> impls; - - /** dictionary of instanciated actions */ - private Map<String, A> cache; - - protected final ActionConfigConfigurationResolver actionConfigInitializer; - protected final ToggleActionConfigConfigurationResolver toggleActionConfigInitializer; - protected final SelectActionConfigConfigurationResolver selectActionConfigInitializer; - - protected List<AbstractActionConfigurationResolver> configurationResolvers; - - protected ActionFactoryFromProvider(Class<A> baseImpl) { - this.baseImpl = baseImpl; - this.impls = init(); - this.cache = new TreeMap<String, A>(); - this.configurationResolvers = new java.util.ArrayList<AbstractActionConfigurationResolver>(); - - this.toggleActionConfigInitializer = registerInitializer(ToggleActionConfigConfigurationResolver.class); - this.actionConfigInitializer = registerInitializer(ActionConfigConfigurationResolver.class); - this.selectActionConfigInitializer = registerInitializer(SelectActionConfigConfigurationResolver.class); - } - - public Class<A> getBaseClass() { - return baseImpl; - } - - public void resetCache() { - cache.clear(); - } - - /*public A get(String actionKey) { - return cache.get(actionKey); - }*/ - - public void loadActions(JAXXObject ui) { - if (log.isDebugEnabled()) { - log.debug("for ui " + ui.getClass()); - } - for (Map.Entry<String, Class<? extends MyAbstractAction>> entry : implsEntrySet()) { - String actionKey = entry.getKey(); - Object comp = ui.getObjectById(actionKey); - if (comp == null || !(comp instanceof AbstractButton || comp instanceof JComboBox)) { - // nothing to do - continue; - } - if (log.isTraceEnabled()) { - log.trace("detect action " + actionKey); - } - if (comp instanceof AbstractButton) { - AbstractButton component = (AbstractButton) comp; - A action = newAction(actionKey, component); - - component.setAction(action); - - if (component instanceof JAXXToggleButton) { - JAXXToggleButton glueComponent = (JAXXToggleButton) component; - glueComponent.setIcon((Icon) action.getValue(Action.SMALL_ICON)); - Integer integer = (Integer) action.getValue(Action.MNEMONIC_KEY); - if (integer != null) { - glueComponent.setNormalMnemonic(integer); - } - glueComponent.setSelectedIcon((Icon) action.getValue(Action.SMALL_ICON + 2)); - integer = (Integer) action.getValue(Action.MNEMONIC_KEY + 2); - if (integer != null) { - glueComponent.setGlueMnemonic(integer); - } - glueComponent.setGlueText((String) action.getValue(Action.NAME + 2)); - glueComponent.setGlueTooltipText((String) action.getValue(Action.SHORT_DESCRIPTION + 2)); - - glueComponent.setNormalText((String) action.getValue(Action.NAME)); - glueComponent.setNormalTooltipText((String) action.getValue(Action.SHORT_DESCRIPTION)); - } - - Boolean value = (Boolean) action.getValue("hideActionText"); - component.setHideActionText(value != null && value); - action.setEnabled(true); - continue; - } - // is JComboBox - JComboBox component = (JComboBox) comp; - A action = newAction(actionKey, component); - - component.setAction(action); - Integer val = (Integer) action.getValue("selectedIndex"); - if (val != null && val != -1 && val < component.getItemCount() && val != component.getSelectedIndex()) { - component.setSelectedIndex(val); - } - } - } - - /** - * @param actionKey le nom de l'action tel que définie dans le fichier - * de mapping (sans le prefix action.) - * @param component le button où rattacher l'action - * @return une nouvelle instance de l'action associée à sa clef. - */ - public A newAction(String actionKey, JComponent component) { - // try first in cache - A result = getActionFromCache(actionKey); - if (result != null) { - return result; - } - - try { - result = newActionInstance(actionKey); - } catch (Exception e) { - throw new RuntimeException(e); - } - - if (log.isDebugEnabled()) { - log.debug("create <" + actionKey + " : " + result + ">"); - } - - // recherche de l'annotation de configuration - ActionConfigurationResolver<?, ?> configurationResolver = resolveActionConfiguration(result); - - if (configurationResolver != null) { - configurationResolver.applyConfiguration(component, result); - } - - try { - - if (configurationResolver != null) { - if (AbstractButton.class.isAssignableFrom(configurationResolver.getComponentImpl())) { - finalizeNewAction((AbstractButton) component, result, configurationResolver); - } - - if (JComboBox.class.isAssignableFrom(configurationResolver.getComponentImpl())) { - finalizeNewAction((JComboBox) component, result, configurationResolver); - } - - return result; - } - - if (component == null || component instanceof AbstractButton) { - finalizeNewAction((AbstractButton) component, result, configurationResolver); - return result; - } - - if (component instanceof JComboBox) { - finalizeNewAction((JComboBox) component, result, configurationResolver); - } - } finally { - // save result in cache - cache.put(actionKey, result); - } - - return result; - } - - public A newAction(String actionKey) { - return newAction(actionKey, null); - } - - public String[] getActionNames() { - return impls.keySet().toArray(new String[impls.size()]); - } - - public Set<Entry<String, Class<? extends MyAbstractAction>>> implsEntrySet() { - return impls.entrySet(); - } - - public Set<Entry<String, A>> cacheEntrySet() { - return cache.entrySet(); - } - - public void fireAction(String actionKey, Object source, JComponent component) { - A action = newAction(actionKey, component); - fireAction0(actionKey, source, action); - } - - public void fireAction(String actionKey, Object source) { - fireAction(actionKey, source, null); - } - - /** - * @param actionKey la clef de l'action - * @return l'action deja stockee dans le cache d'action, ou <code>null</code> si non trouvée. - */ - public A getActionFromCache(String actionKey) { - // on vérifie que l'action existe bien - checkRegistredAction(actionKey); - - A action = null; - // try in cache - if (cache.containsKey(actionKey)) { - // use cached action - action = cache.get(actionKey); - if (log.isDebugEnabled()) { - log.debug("use cache action " + action); - } - } - return action; - } - - public void dispose() { - if (log.isInfoEnabled()) { - log.info(this); - } - for (String actionKey : getActionNames()) { - MyAbstractAction action = getActionFromCache(actionKey); - if (action != null) { - action.disposeUI(); - } - } - resetCache(); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - resetCache(); - impls.clear(); - } - - /** - * @param component le button où rattacher l'action - * @param action action - * @param configurationResolver initializer - */ - protected void finalizeNewAction(AbstractButton component, MyAbstractAction action, ActionConfigurationResolver<?, ?> configurationResolver) { - - if (configurationResolver == null) { - // no configurationResolver matching, - if (component != null) { - action.putValue(Action.ACTION_COMMAND_KEY, component.getName()); - action.putValue(Action.SHORT_DESCRIPTION, component.getToolTipText()); - action.putValue(Action.SMALL_ICON, component.getIcon()); - action.putValue(Action.NAME, component.getText()); - action.putValue(Action.MNEMONIC_KEY, component.getMnemonic()); - action.putValue("hideActionText", component.getHideActionText()); - if (component instanceof JAXXToggleButton) { - JAXXToggleButton glueComponent = (JAXXToggleButton) component; - action.putValue(Action.SHORT_DESCRIPTION, glueComponent.getNormalTooltipText()); - action.putValue(Action.NAME, glueComponent.getNormalText()); - action.putValue(Action.SMALL_ICON, glueComponent.getIcon()); - action.putValue(Action.MNEMONIC_KEY, glueComponent.getNormalMnemonic()); - action.putValue(Action.SHORT_DESCRIPTION + 2, glueComponent.getGlueTooltipText()); - action.putValue(Action.NAME + 2, glueComponent.getGlueText()); - action.putValue(Action.SMALL_ICON + 2, glueComponent.getSelectedIcon()); - action.putValue(Action.MNEMONIC_KEY + 2, glueComponent.getGlueMnemonic()); - } - } - - } - - String text = (String) action.getValue(Action.NAME); - Integer mnemo = (Integer) action.getValue(Action.MNEMONIC_KEY); - if (mnemo != null && mnemo != '\0') { - int pos = text.indexOf((char) mnemo.intValue()); - if (pos == -1) { - pos = text.indexOf(Character.toLowerCase((char) mnemo.intValue())); - } - action.putValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY, pos); - } - - } - - /** - * @param component le select box où rattacher l'action - * @param action action - * @param configurationResolver initializer - */ - protected void finalizeNewAction(JComboBox component, MyAbstractAction action, ActionConfigurationResolver<?, ?> configurationResolver) { - - if (configurationResolver == null) { - action.putValue(Action.ACTION_COMMAND_KEY, component.getName()); - action.putValue(Action.SHORT_DESCRIPTION, component.getToolTipText()); - //result.putValue("selectedIndex", component.getSelectedIndex()); - } - - } - - protected ActionConfigurationResolver resolveActionConfiguration(MyAbstractAction action) { - for (ActionConfigurationResolver resolver : configurationResolvers) { - if (resolver.resolveConfiguration(action) != null) { - return resolver; - } - } - return null; - } - - protected <I extends AbstractActionConfigurationResolver> I registerInitializer(Class<I> initizalizer) { - try { - I instance = initizalizer.newInstance(); - configurationResolvers.add(instance); - return instance; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public void fireAction0(String actionKey, Object source, A action) { - if (action == null) { - log.warn("could not find action " + actionKey); - return; - } - ActionEvent event = new ActionEvent(source, ActionEvent.ACTION_FIRST, actionKey); - action.actionPerformed(event); - } - - protected void checkRegistredAction(String actionKey) { - if (!impls.containsKey(actionKey)) { - throw new IllegalStateException("can not find a registered action for key " + actionKey); - } - } - - - @SuppressWarnings({"unchecked"}) - protected A newActionInstance(String actionKey) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { - Class<? extends MyAbstractAction> klazz = impls.get(actionKey); - MyAbstractAction result; - result = klazz.getConstructor(String.class).newInstance(actionKey); - result.putValue(Action.ACTION_COMMAND_KEY, actionKey); - if (!getBaseClass().isAssignableFrom(klazz)) { - // the instanciated action must be boxed in the base Action of the factory - result = getBaseClass().getConstructor(MyAbstractAction.class).newInstance(result); - } - return (A) result; - } - - - public Map<String, Class<? extends MyAbstractAction>> init() { - if (log.isDebugEnabled()) { - log.debug("start loading " + this); - } - // obtain a ServiceLoader on ActionProvider - ServiceLoader<ActionProvider> loader = ServiceLoader.load(ActionProvider.class); - Map<String, Class<? extends MyAbstractAction>> cache = new TreeMap<String, Class<? extends MyAbstractAction>>(); - - for (ActionProvider<?> actionProvider : loader) { - if (log.isDebugEnabled()) { - log.debug("found " + actionProvider); - } - cache.putAll(actionProvider.getClasses()); - } - return cache; - } - -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java (from rev 1037, lutinjaxx/trunk/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java) =================================================================== --- lutinjaxx/tags/0.7/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java (rev 0) +++ lutinjaxx/tags/0.7/jaxx-swing-action/src/main/java/org/codelutin/jaxx/action/ActionFactoryFromProvider.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,457 @@ +/* +* ##% Copyright (C) 2007, 2008 Code Lutin, Tony Chemit +* +* 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.action; + +import jaxx.runtime.JAXXObject; +import jaxx.runtime.swing.JAXXToggleButton; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.util.Resource; + +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import java.awt.event.ActionEvent; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.TreeMap; + +/** + * A simple implementation of {@link ActionFactory} using some {@link ActionProvider} to seek actions. + * <p/> + * <p/> + * An entry is in that form : <code>action.actionName=fqn</code> where + * <p/> + * <code>actionName</code> is the key of action used in factory, and + * <code>fqn</code> is the fully qualified name of the implemented action class. + * <p/> + * A special clase is to have for a given entry a key like this : <code>action.:fqn'=fqn</code>, in that case, + * le fqn' is a classe of type {@link org.codelutin.jaxx.action.ActionNameProvider} which gives us at + * runtime the names of each entry to put in cache for the givne action fqn. + * + * @author chemit + */ +public class ActionFactoryFromProvider<A extends MyAbstractAction> implements ActionFactory<A> { + + protected static Log log = LogFactory.getLog(ActionFactoryFromProvider.class); + + public static <A extends MyAbstractAction> ActionFactory<A> newInstance(Class<A> klazz) { + return new ActionFactoryFromProvider<A>(klazz); + } + + /** class of encapsuling action */ + protected Class<A> baseImpl; + + /** dictionary of known actions implementations */ + private Map<String, Class<? extends MyAbstractAction>> impls; + + /** dictionary of instanciated actions */ + private Map<String, A> cache; + + protected final ActionConfigConfigurationResolver actionConfigInitializer; + protected final ToggleActionConfigConfigurationResolver toggleActionConfigInitializer; + protected final SelectActionConfigConfigurationResolver selectActionConfigInitializer; + + protected List<AbstractActionConfigurationResolver> configurationResolvers; + + protected ActionFactoryFromProvider(Class<A> baseImpl) { + this.baseImpl = baseImpl; + this.impls = init(); + this.cache = new TreeMap<String, A>(); + this.configurationResolvers = new java.util.ArrayList<AbstractActionConfigurationResolver>(); + + this.toggleActionConfigInitializer = registerInitializer(ToggleActionConfigConfigurationResolver.class); + this.actionConfigInitializer = registerInitializer(ActionConfigConfigurationResolver.class); + this.selectActionConfigInitializer = registerInitializer(SelectActionConfigConfigurationResolver.class); + } + + public Class<A> getBaseClass() { + return baseImpl; + } + + public void resetCache() { + cache.clear(); + } + + /*public A get(String actionKey) { + return cache.get(actionKey); + }*/ + + public void loadActions(JAXXObject ui) { + if (log.isDebugEnabled()) { + log.debug("for ui " + ui.getClass()); + } + for (Map.Entry<String, Class<? extends MyAbstractAction>> entry : implsEntrySet()) { + String actionKey = entry.getKey(); + Object comp = ui.getObjectById(actionKey); + if (comp == null || !(comp instanceof AbstractButton || comp instanceof JComboBox)) { + // nothing to do + continue; + } + if (log.isTraceEnabled()) { + log.trace("detect action " + actionKey); + } + if (comp instanceof AbstractButton) { + AbstractButton component = (AbstractButton) comp; + A action = newAction(actionKey, component); + + component.setAction(action); + + if (component instanceof JAXXToggleButton) { + JAXXToggleButton glueComponent = (JAXXToggleButton) component; + glueComponent.setIcon((Icon) action.getValue(Action.SMALL_ICON)); + Integer integer = (Integer) action.getValue(Action.MNEMONIC_KEY); + if (integer != null) { + glueComponent.setNormalMnemonic(integer); + } + glueComponent.setSelectedIcon((Icon) action.getValue(Action.SMALL_ICON + 2)); + integer = (Integer) action.getValue(Action.MNEMONIC_KEY + 2); + if (integer != null) { + glueComponent.setGlueMnemonic(integer); + } + glueComponent.setGlueText((String) action.getValue(Action.NAME + 2)); + glueComponent.setGlueTooltipText((String) action.getValue(Action.SHORT_DESCRIPTION + 2)); + + glueComponent.setNormalText((String) action.getValue(Action.NAME)); + glueComponent.setNormalTooltipText((String) action.getValue(Action.SHORT_DESCRIPTION)); + } + + Boolean value = (Boolean) action.getValue("hideActionText"); + component.setHideActionText(value != null && value); + action.setEnabled(true); + continue; + } + // is JComboBox + JComboBox component = (JComboBox) comp; + A action = newAction(actionKey, component); + + component.setAction(action); + Integer val = (Integer) action.getValue("selectedIndex"); + if (val != null && val != -1 && val < component.getItemCount() && val != component.getSelectedIndex()) { + component.setSelectedIndex(val); + } + } + } + + /** + * @param actionKey le nom de l'action tel que définie dans le fichier + * de mapping (sans le prefix action.) + * @param component le button où rattacher l'action + * @return une nouvelle instance de l'action associée à sa clef. + */ + public A newAction(String actionKey, JComponent component) { + // try first in cache + A result = getActionFromCache(actionKey); + if (result != null) { + return result; + } + + try { + result = newActionInstance(actionKey); + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (log.isDebugEnabled()) { + log.debug("create <" + actionKey + " : " + result + ">"); + } + + // recherche de l'annotation de configuration + ActionConfigurationResolver<?, ?> configurationResolver = resolveActionConfiguration(result); + + if (configurationResolver != null) { + configurationResolver.applyConfiguration(component, result); + } + + try { + + if (configurationResolver != null) { + if (AbstractButton.class.isAssignableFrom(configurationResolver.getComponentImpl())) { + finalizeNewAction((AbstractButton) component, result, configurationResolver); + } + + if (JComboBox.class.isAssignableFrom(configurationResolver.getComponentImpl())) { + finalizeNewAction((JComboBox) component, result, configurationResolver); + } + + return result; + } + + if (component == null || component instanceof AbstractButton) { + finalizeNewAction((AbstractButton) component, result, configurationResolver); + return result; + } + + if (component instanceof JComboBox) { + finalizeNewAction((JComboBox) component, result, configurationResolver); + } + } finally { + // save result in cache + cache.put(actionKey, result); + } + + return result; + } + + public A newAction(String actionKey) { + return newAction(actionKey, null); + } + + public String[] getActionNames() { + return impls.keySet().toArray(new String[impls.size()]); + } + + public Set<Entry<String, Class<? extends MyAbstractAction>>> implsEntrySet() { + return impls.entrySet(); + } + + public Set<Entry<String, A>> cacheEntrySet() { + return cache.entrySet(); + } + + public void fireAction(String actionKey, Object source, JComponent component) { + A action = newAction(actionKey, component); + fireAction0(actionKey, source, action); + } + + public void fireAction(String actionKey, Object source) { + fireAction(actionKey, source, null); + } + + /** + * @param actionKey la clef de l'action + * @return l'action deja stockee dans le cache d'action, ou <code>null</code> si non trouvée. + */ + public A getActionFromCache(String actionKey) { + // on vérifie que l'action existe bien + checkRegistredAction(actionKey); + + A action = null; + // try in cache + if (cache.containsKey(actionKey)) { + // use cached action + action = cache.get(actionKey); + if (log.isDebugEnabled()) { + log.debug("use cache action " + action); + } + } + return action; + } + + public void dispose() { + if (log.isInfoEnabled()) { + log.info(this); + } + for (String actionKey : getActionNames()) { + MyAbstractAction action = getActionFromCache(actionKey); + if (action != null) { + action.disposeUI(); + } + } + resetCache(); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + resetCache(); + impls.clear(); + } + + /** + * @param component le button où rattacher l'action + * @param action action + * @param configurationResolver initializer + */ + protected void finalizeNewAction(AbstractButton component, MyAbstractAction action, ActionConfigurationResolver<?, ?> configurationResolver) { + + if (configurationResolver == null) { + // no configurationResolver matching, + if (component != null) { + action.putValue(Action.ACTION_COMMAND_KEY, component.getName()); + action.putValue(Action.SHORT_DESCRIPTION, component.getToolTipText()); + action.putValue(Action.SMALL_ICON, component.getIcon()); + action.putValue(Action.NAME, component.getText()); + action.putValue(Action.MNEMONIC_KEY, component.getMnemonic()); + action.putValue("hideActionText", component.getHideActionText()); + if (component instanceof JAXXToggleButton) { + JAXXToggleButton glueComponent = (JAXXToggleButton) component; + action.putValue(Action.SHORT_DESCRIPTION, glueComponent.getNormalTooltipText()); + action.putValue(Action.NAME, glueComponent.getNormalText()); + action.putValue(Action.SMALL_ICON, glueComponent.getIcon()); + action.putValue(Action.MNEMONIC_KEY, glueComponent.getNormalMnemonic()); + action.putValue(Action.SHORT_DESCRIPTION + 2, glueComponent.getGlueTooltipText()); + action.putValue(Action.NAME + 2, glueComponent.getGlueText()); + action.putValue(Action.SMALL_ICON + 2, glueComponent.getSelectedIcon()); + action.putValue(Action.MNEMONIC_KEY + 2, glueComponent.getGlueMnemonic()); + } + } + + } + + String text = (String) action.getValue(Action.NAME); + Integer mnemo = (Integer) action.getValue(Action.MNEMONIC_KEY); + if (mnemo != null && mnemo != '\0') { + int pos = text.indexOf((char) mnemo.intValue()); + if (pos == -1) { + pos = text.indexOf(Character.toLowerCase((char) mnemo.intValue())); + } + action.putValue(Action.DISPLAYED_MNEMONIC_INDEX_KEY, pos); + } + + } + + /** + * @param component le select box où rattacher l'action + * @param action action + * @param configurationResolver initializer + */ + protected void finalizeNewAction(JComboBox component, MyAbstractAction action, ActionConfigurationResolver<?, ?> configurationResolver) { + + if (configurationResolver == null) { + action.putValue(Action.ACTION_COMMAND_KEY, component.getName()); + action.putValue(Action.SHORT_DESCRIPTION, component.getToolTipText()); + //result.putValue("selectedIndex", component.getSelectedIndex()); + } + + } + + protected ActionConfigurationResolver resolveActionConfiguration(MyAbstractAction action) { + for (ActionConfigurationResolver resolver : configurationResolvers) { + if (resolver.resolveConfiguration(action) != null) { + return resolver; + } + } + return null; + } + + protected <I extends AbstractActionConfigurationResolver> I registerInitializer(Class<I> initizalizer) { + try { + I instance = initizalizer.newInstance(); + configurationResolvers.add(instance); + return instance; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void fireAction0(String actionKey, Object source, A action) { + if (action == null) { + log.warn("could not find action " + actionKey); + return; + } + ActionEvent event = new ActionEvent(source, ActionEvent.ACTION_FIRST, actionKey); + action.actionPerformed(event); + } + + protected void checkRegistredAction(String actionKey) { + if (!impls.containsKey(actionKey)) { + throw new IllegalStateException("can not find a registered action for key " + actionKey); + } + } + + + @SuppressWarnings({"unchecked"}) + protected A newActionInstance(String actionKey) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + Class<? extends MyAbstractAction> klazz = impls.get(actionKey); + MyAbstractAction result; + result = klazz.getConstructor(String.class).newInstance(actionKey); + result.putValue(Action.ACTION_COMMAND_KEY, actionKey); + if (!getBaseClass().isAssignableFrom(klazz)) { + // the instanciated action must be boxed in the base Action of the factory + result = getBaseClass().getConstructor(MyAbstractAction.class).newInstance(result); + } + return (A) result; + } + + + public Map<String, Class<? extends MyAbstractAction>> init() { + if (log.isDebugEnabled()) { + log.debug("start loading " + this); + } + URLClassLoader newCL = fixClassLoader(getClass()); + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (newCL != null) { + // replace current cl by our fiexed cl + Thread.currentThread().setContextClassLoader(newCL); + } + // obtain a ServiceLoader on ActionProvider + ServiceLoader<ActionProvider> loader = ServiceLoader.load(ActionProvider.class); + Map<String, Class<? extends MyAbstractAction>> cache = new TreeMap<String, Class<? extends MyAbstractAction>>(); + + for (ActionProvider<?> actionProvider : loader) { + if (log.isDebugEnabled()) { + log.debug("found " + actionProvider); + } + cache.putAll(actionProvider.getClasses()); + } + if (newCL != null) { + // to avoid side effects, push back old cl + Thread.currentThread().setContextClassLoader(cl); + } + return cache; + } + + /** + * Fix the class loader when application is launched from a java -jar + * The ServiceLoader seems not to find services from jar manifest... + * <p/> + * Our solution is to get all jar from the jar manifest and create a URLClassLoader, this is not perfect but works. + * <p/> + * TODO Put this nice code in a ServiceLoaderUtil in lutinutil... + * + * @param klass class to use to obtain classloader + * @return the fixed classloader + */ + public static URLClassLoader fixClassLoader(Class klass) { + ClassLoader l = klass.getClassLoader(); + URLClassLoader cl; + if (!(l instanceof URLClassLoader)) { + log.warn("using cl is not a URL classloader " + l); + cl = new URLClassLoader(new URL[0], l); + } else { + cl = (URLClassLoader) l; + } + if (cl.getURLs().length == 1) { + // come from a java -jar, must expand all jar to make possible ServiceLoader to work + try { + //todo put this in lutinutil ServiceLoaderUtil + URL[] urls = Resource.getClassPathURLsFromJarManifest(cl.getURLs()[0]); + URLClassLoader newCL = new URLClassLoader(urls); + if (log.isTraceEnabled()) { + for (URL url : newCL.getURLs()) { + log.trace(url); + } + } + return newCL; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return null; + } + +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/jaxx-util/README.txt (from rev 1057, lutinjaxx/trunk/jaxx-util/README.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-util/README.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-util/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Copied: lutinjaxx/tags/0.7/jaxx-util/changelog.txt (from rev 1057, lutinjaxx/trunk/jaxx-util/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/jaxx-util/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/jaxx-util/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file Deleted: lutinjaxx/tags/0.7/jaxx-util/pom.xml =================================================================== --- lutinjaxx/trunk/jaxx-util/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/jaxx-util/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -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.6-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.7/jaxx-util/pom.xml (from rev 1062, lutinjaxx/trunk/jaxx-util/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/jaxx-util/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/jaxx-util/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,46 @@ +<?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.7</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.7/jaxx-util</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/jaxx-util</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/jaxx-util?root=buix</url> + </scm> + +</project> Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/README.txt (from rev 1057, lutinjaxx/trunk/maven-jaxx-plugin/README.txt) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/README.txt (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/README.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/changelog =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/changelog 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/changelog 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,6 +0,0 @@ -ver-0-5 chemit 20081002 - * 20081013 [chemit] can generate logger on jaxx files - * 20081011 [chemit] improve site - * 20081011 [chemit] refactor tests of the plugin using maven-plugin-testing-harness plugin - * 20081002 [chemit] Using lutinpluginproject 3.0, changing groupId to org.codelutin - * 20081002 [chemit] Make nearly all tests works again... Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/changelog.txt (from rev 1060, lutinjaxx/trunk/maven-jaxx-plugin/changelog.txt) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/changelog.txt (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/changelog.txt 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,14 @@ +0.7 chemit 200812?? +* 20081208 [chemit] - javabBean attribute use to initialize bean +* 20081207 [chemit] use lutinproject 3.1 + +0.6 chemit 200811?? + * 20081108 [chemit] can add extra imports in JaxxGeneratorMojo (will be added to all generated java files). + * 20081104 [chemit] can add extra beanInfoSearchPath in JaxxGeneratorMojo + +ver-0-5 chemit 20081002 + * 20081013 [chemit] can generate logger on jaxx files + * 20081011 [chemit] improve site + * 20081011 [chemit] refactor tests of the plugin using maven-plugin-testing-harness plugin + * 20081002 [chemit] Using lutinpluginproject 3.0, changing groupId to org.codelutin + * 20081002 [chemit] Make nearly all tests works again... Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/pom.xml =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,127 +0,0 @@ -<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.6-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> \ No newline at end of file Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/pom.xml (from rev 1062, lutinjaxx/trunk/maven-jaxx-plugin/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,132 @@ +<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.7</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> + + <!-- pour acceder aux BeansInfos swing via Introspector --> + <dependency> + <groupId>com.sun</groupId> + <artifactId>dt</artifactId> + <!--scope>system</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> + <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> + <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.7/maven-jaxx-plugin</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7/maven-jaxx-plugin</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7/maven-jaxx-plugin?root=buix</url> + </scm> + +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.7/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-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,464 +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; - - /** - * 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 Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java (from rev 1060, lutinjaxx/trunk/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/main/java/org/codelutin/jaxx/JaxxGeneratorMojo.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,550 @@ +/* *##% + * 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.runtime.JAXXContext; +import jaxx.tags.TagManager; +import jaxx.tags.swing.SwingInitializer; +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.lang.reflect.Modifier; +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; + /** + * flag to keep compilers after the generate operation (usefull for tests. + * <p/> + * By default, always reset. + * + * @parameter expression="${jaxx.resetAfterCompile}" default-value="true" + */ + protected boolean resetAfterCompile; + + /** + * the name of implementation of {@link jaxx.runtime.JAXXContext} + * to be used on {@link jaxx.runtime.JAXXObject}. + * <p/> + * Must not be abstract. + * + * @parameter expression="${jaxx.jaxxContextImplementorClass}" default-value="jaxx.runtime.DefaultJAXXContext" + * @required + */ + protected String jaxxContextImplementorClass; + + /** + * extra path to be added in {@link java.beans.Introspector#setBeanInfoSearchPath(String[])}. + * <p/> + * add beanInfoSearchPath to be registred by {@link SwingInitializer#setExtraBeanInfoSearchPath(String[])} + * <p/> + * and then will be use by {@link jaxx.tags.swing.SwingInitializer#initialize()}. + * <p/> + * <p/> + * This permit to use real beanInfo of imported graphic libraries. + * + * @parameter expression="${jaxx.beanInfoSearchPath}" + */ + protected String[] beanInfoSearchPath; + + /** + * list of fqn of class toimport for all generated jaxx files + * + * @parameter expression="${jaxx.extraImports}" + */ + protected String[] extraImports; + + 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; + + checkJaxxContextImplementorClass(); + + if (beanInfoSearchPath != null && beanInfoSearchPath.length > 0) { + // regisre extra path + SwingInitializer.setExtraBeanInfoSearchPath(beanInfoSearchPath); + } + 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); + result.setResetAfterCompile(resetAfterCompile); + result.setJaxxContextImplementorClass(jaxxContextImplementorClass); + result.setExtraImports(extraImports); + 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)); + } + } + } + + protected void checkJaxxContextImplementorClass() { + if (jaxxContextImplementorClass == null) { + throw new IllegalArgumentException("jaxxContextImplementor can not be null"); + } + try { + Class jaxxContextImplementor = Class.forName(jaxxContextImplementorClass); + if (!JAXXContext.class.isAssignableFrom(jaxxContextImplementor)) { + throw new IllegalArgumentException("jaxxContextImplementor '" + jaxxContextImplementor + "' does not implements " + JAXXContext.class); + } + if (Modifier.isAbstract(jaxxContextImplementor.getModifiers())) { + throw new IllegalArgumentException("jaxxContextImplementor '" + jaxxContextImplementor + "' can not be abstract."); + + } + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("could not find jaxxContextImplementor class : " + jaxxContextImplementorClass); + } + } + + 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; + } + + public String getJaxxContextImplementorClass() { + return jaxxContextImplementorClass; + } + + public void setJaxxContextImplementorClass(String jaxxContextImplementorClass) { + this.jaxxContextImplementorClass = jaxxContextImplementorClass; + } + + public String[] getBeanInfoSearchPath() { + return beanInfoSearchPath; + } + + public void setBeanInfoSearchPath(String[] beanInfoSearchPath) { + this.beanInfoSearchPath = beanInfoSearchPath; + } +} \ No newline at end of file Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/Bug1750Test.java (from rev 1060, lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/Bug1750Test.java) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/Bug1750Test.java (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/Bug1750Test.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,44 @@ +package org.codelutin.jaxx; + +import jaxx.Base64Coder; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerHelper; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.runtime.Util; + +/** @author chemit */ +public class Bug1750Test extends JaxxBaseTest { + + public void testBug_1750() throws Exception { + mojo.execute(); + assertEquals(1, mojo.getFiles().length); + + JAXXCompiler compiler = JAXXCompilerHelper.getJAXXCompiler("testcases.bug_1750.ComboBox"); + assertNotNull(compiler); + + JAXXObjectDescriptor descriptor = compiler.getJAXXObjectDescriptor(); + assertNotNull(descriptor); + + String data = Base64Coder.serialize(descriptor, false); + + JAXXObjectDescriptor descriptor2 = (JAXXObjectDescriptor) Base64Coder.deserialize(data, false); + assertNotNull(descriptor2); + assertEquals(descriptor.toString(), descriptor2.toString()); + + descriptor2 = Util.decodeJAXXObjectDescriptor(data); + assertNotNull(descriptor2); + assertEquals(descriptor.toString(), descriptor2.toString()); + + data = Base64Coder.serialize(descriptor, true); + + descriptor2 = (JAXXObjectDescriptor) Base64Coder.deserialize(data, true); + assertNotNull(descriptor2); + assertEquals(descriptor.toString(), descriptor2.toString()); + + descriptor2 = Util.decodeCompressedJAXXObjectDescriptor(data); + assertNotNull(descriptor2); + assertEquals(descriptor.toString(), descriptor2.toString()); + + } + +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/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-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/BuildExamples.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,106 +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.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.7/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-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,232 +0,0 @@ -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 { - - 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(2, mojo.getFiles().length); - - } - - public void testValidatorErrors() throws Exception { - // init mojo to get alls files to treate - mojo.init(); - String[] files = mojo.getFiles(); - assertEquals(17, 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 Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java (from rev 1048, lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/CompilerTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,266 @@ +package org.codelutin.jaxx; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerHelper; +import jaxx.runtime.DefaultJAXXContext; +import jaxx.runtime.JAXXContext; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.junit.Assert; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.Map; + +public class CompilerTest extends JaxxBaseTest { + + 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 testErrorJaxxContextImplementorClass() throws Exception { + mojo.setJaxxContextImplementorClass(null); + try { + mojo.init(); + fail(); + } catch (IllegalArgumentException e) { + Assert.assertTrue(true); + } + + mojo.setJaxxContextImplementorClass(String.class.getName()); + try { + mojo.init(); + fail(); + } catch (IllegalArgumentException e) { + Assert.assertTrue(true); + } + + mojo.setJaxxContextImplementorClass(JAXXContext.class.getName()); + try { + mojo.init(); + fail(); + } catch (IllegalArgumentException e) { + Assert.assertTrue(true); + } + + mojo.setJaxxContextImplementorClass(DefaultJAXXContext.class.getName()); + mojo.init(); + Assert.assertTrue(true); + + } + + 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(2, mojo.getFiles().length); + + } + + public void testValidatorErrors() throws Exception { + // init mojo to get alls files to treate + mojo.init(); + String[] files = mojo.getFiles(); + assertEquals(15, 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("for file " + file); + } 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.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,73 +0,0 @@ -package org.codelutin.jaxx; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.maven.plugin.testing.AbstractMojoTestCase; -import org.codelutin.util.FileUtil; - -import java.io.File; -import java.io.IOException; - -/** @author chemit */ -public abstract class JaxxBaseTest extends AbstractMojoTestCase { - - protected static final String DEFALUT_PREFIX = "src" + File.separator + "test" + File.separator + "resources" + File.separator + "testcases" + File.separator; - - /** log */ - protected Log log; - - protected JaxxGeneratorMojo mojo; - - protected File pomFile; - - public String getPrefix() { - return DEFALUT_PREFIX; - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - getLog().info(getName()); - pomFile = getPomFile(); - mojo = (JaxxGeneratorMojo) lookupMojo("generate", pomFile); - assertNotNull(mojo); - } - - protected File getPomFile() { - return new File(getBasedir(), getPrefix() + getName().substring(4) + ".xml"); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - if (mojo != null) { - mojo = null; - } - if (pomFile != null) { - pomFile = null; - } - } - - protected void checkPattern(JaxxGeneratorMojo mojo, String pattern, boolean required, String... files) throws IOException { - for (String file : files) { - // check we have a the required/forbidden pattern - File f = new File(mojo.getOutJava(), file.substring(0, file.length() - 4) + "java"); - if (mojo.isVerbose()) { - getLog().info("check generated file " + f); - } - - assertTrue("generated file " + f + " was not found...", f.exists()); - String content = FileUtil.readAsString(f); - - String errorMessage = required ? "could not find the pattern : " : "should not have found pattern :"; - assertEquals(errorMessage + pattern + " in file " + f, required, content.contains(pattern)); - } - } - - protected Log getLog() { - if (log == null) { - log = LogFactory.getLog(getClass()); - } - return log; - } -} Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java (from rev 1015, lutinjaxx/trunk/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/java/org/codelutin/jaxx/JaxxBaseTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,76 @@ +package org.codelutin.jaxx; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.maven.plugin.testing.AbstractMojoTestCase; +import org.codelutin.util.FileUtil; + +import java.io.File; +import java.io.IOException; + +import jaxx.runtime.DefaultJAXXContext; + +/** @author chemit */ +public abstract class JaxxBaseTest extends AbstractMojoTestCase { + + protected static final String DEFALUT_PREFIX = "src" + File.separator + "test" + File.separator + "resources" + File.separator + "testcases" + File.separator; + + /** log */ + protected Log log; + + protected JaxxGeneratorMojo mojo; + + protected File pomFile; + + public String getPrefix() { + return DEFALUT_PREFIX; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + getLog().info(getName()); + pomFile = getPomFile(); + mojo = (JaxxGeneratorMojo) lookupMojo("generate", pomFile); + mojo.setJaxxContextImplementorClass(DefaultJAXXContext.class.getName()); + assertNotNull(mojo); + } + + protected File getPomFile() { + return new File(getBasedir(), getPrefix() + getName().substring(4) + ".xml"); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + if (mojo != null) { + mojo = null; + } + if (pomFile != null) { + pomFile = null; + } + } + + protected void checkPattern(JaxxGeneratorMojo mojo, String pattern, boolean required, String... files) throws IOException { + for (String file : files) { + // check we have a the required/forbidden pattern + File f = new File(mojo.getOutJava(), file.substring(0, file.length() - 4) + "java"); + if (mojo.isVerbose()) { + getLog().info("check generated file " + f); + } + + assertTrue("generated file " + f + " was not found...", f.exists()); + String content = FileUtil.readAsString(f); + + String errorMessage = required ? "could not find the pattern : " : "should not have found pattern :"; + assertEquals(errorMessage + pattern + " in file " + f, required, content.contains(pattern)); + } + } + + protected Log getLog() { + if (log == null) { + log = LogFactory.getLog(getClass()); + } + return log; + } +} Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/Bug_1750.xml (from rev 1060, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/Bug_1750.xml) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/Bug_1750.xml (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/Bug_1750.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,24 @@ +<?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> + <verbose>true</verbose> + <resetAfterCompile>false</resetAfterCompile> + <includes> + <value>**/bug_1750/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,18 +0,0 @@ -<Application> - <script> - Object ref1 = new ConstructorReferenceTest(); - box.add(new JLabel(ref1.toString())); - - TypeReference ref2; // this line only compiles if TypeReference.jaxx gets compiled due to this reference - box.add(new JLabel("Type reference worked")); - - box.add(new JLabel(StaticMethodTest.getText())); - </script> - - <VBox id='box'> - <!-- TODO Ce cas ne fonctionne plus (il faut posséder cette classe compilée ? --> - <!--ClassTest customProperty='Compiled class file worked'/--> - <JAXXTest customProperty='Uncompiled JAXX file worked'/> - <JavaTest customProperty='Uncompiled Java file worked'/> - </VBox> -</Application> \ No newline at end of file Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx (from rev 1039, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/ClassReferences.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,18 @@ +<Application> + <script> + Object ref1 = new ConstructorReferenceTest(); + box.add(new JLabel(ref1.toString())); + + TypeReference ref2; // this line only compiles if TypeReference.jaxx gets compiled due to this reference + box.add(new JLabel("Type reference worked")); + + box.add(new JLabel(StaticMethodTest.getText())); + </script> + + <VBox id='box'> + <!-- TODO Ce cas ne fonctionne plus (il faut posséder cette classe compilée ? --> + <!--ClassTest customProperty='Compiled class file worked'/--> + <JAXXTest customProperty='Uncompiled JAXX file worked'/> + <JavaTaist customProperty='Uncompiled Java file worked'/> + </VBox> +</Application> \ No newline at end of file Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTaist.java (from rev 1039, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTaist.java) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTaist.java (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTaist.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,9 @@ +package testcases.ClassReferences; + +import javax.swing.*; + +public class JavaTaist extends JLabel { + public void setCustomProperty(String label) { + setText(label); + } +} \ No newline at end of file Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTest.java =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTest.java 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ClassReferences/JavaTest.java 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,9 +0,0 @@ -package testcases.ClassReferences; - -import javax.swing.*; - -public class JavaTest extends JLabel { - public void setCustomProperty(String label) { - setText(label); - } -} \ No newline at end of file Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ErrorJaxxContextImplementorClass.xml (from rev 1015, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/ErrorJaxxContextImplementorClass.xml) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ErrorJaxxContextImplementorClass.xml (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/ErrorJaxxContextImplementorClass.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,20 @@ +<?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> + <jaxxContextImplementorClass>java.lang.String</jaxxContextImplementorClass> + <force>true</force> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/bug_1750 (from rev 1060, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/bug_1750) Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/DuplicatedFieldInOtherValidator.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/DuplicatedFieldInOtherValidator.jaxx 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/DuplicatedFieldInOtherValidator.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,266 +0,0 @@ -<Application title="Validation.jaxx"> - - <!-- models --> - <Model id='model'/> - <Model id='model2'/> - - <!-- 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> - - <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='140'> - <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> - </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> Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/FieldComponentDuplicated2.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/FieldComponentDuplicated2.jaxx 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/errors/FieldComponentDuplicated2.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,266 +0,0 @@ -<Application title="Validation.jaxx"> - - <!-- models --> - <Model id='model'/> - <Model id='model2'/> - - <!-- errors model --> - <jaxx.runtime.validator.BeanValidatorErrorListModel id='errors' onContentsChanged='ok.setEnabled(errors.size()==0)'/> - - <!-- validators --> - <BeanValidator id='validator' errorListModel='errors' bean="model"> - <field name="text" component="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> - - <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='140'> - <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> - </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> Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,270 +0,0 @@ -<Application title="Validation.jaxx"> - - <!-- 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='140'> - <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> - </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.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx (from rev 1042, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/Validation.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,275 @@ +<Application title="Validation.jaxx"> + + <!-- 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' scope='ERROR'> + <field name="text"/> + <field name="text2"/> + <field name="ratio"/> + </BeanValidator> + <BeanValidator id='validator2' bean='model2' errorListModel='errors' + uiClass="jaxx.runtime.validator.ui.IconValidationUI" scope="WARNING"> + <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" + scope='ERROR'> + <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='140'> + <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> + </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> Deleted: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx =================================================================== --- lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,111 +0,0 @@ -<Application title="Validation.jaxx"> - - <!-- models --> - <Identity id='identity'/> - - <!-- errors model --> - <jaxx.runtime.validator.BeanValidatorErrorListModel id='errors'/> - - <!-- validators --> - <BeanValidator id='validator3' autoField='true' beanClass='testcases.validator.ok.Identity' errorListModel='errors'> - <field name="email" component="email2"/> - </BeanValidator> - - <Table fill='both'> - <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'> - <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> - </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> - </Table> -</Application> Copied: lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx (from rev 1042, lutinjaxx/trunk/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx) =================================================================== --- lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx (rev 0) +++ lutinjaxx/tags/0.7/maven-jaxx-plugin/src/test/resources/testcases/validator/ok/ValidationBeanClass.jaxx 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,112 @@ +<Application title="Validation.jaxx"> + + <!-- models --> + <Identity id='identity'/> + + <!-- errors model --> + <jaxx.runtime.validator.BeanValidatorErrorListModel id='errors'/> + + <!-- validators --> + <BeanValidator id='validator3' autoField='true' beanClass='testcases.validator.ok.Identity' errorListModel='errors' + scope='ERROR'> + <field name="email" component="email2"/> + </BeanValidator> + + <Table fill='both'> + <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'> + <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> + </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> + </Table> +</Application> Deleted: lutinjaxx/tags/0.7/pom.xml =================================================================== --- lutinjaxx/trunk/pom.xml 2008-10-27 17:01:12 UTC (rev 1003) +++ lutinjaxx/tags/0.7/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -1,217 +0,0 @@ -<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.6-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>0.6-SNAPSHOT</version> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-core</artifactId> - <version>0.6-SNAPSHOT</version> - </dependency> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-swing-action</artifactId> - <version>0.6-SNAPSHOT</version> - </dependency> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>jaxx-example</artifactId> - <version>0.6-SNAPSHOT</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> - <!-- 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 Copied: lutinjaxx/tags/0.7/pom.xml (from rev 1062, lutinjaxx/trunk/pom.xml) =================================================================== --- lutinjaxx/tags/0.7/pom.xml (rev 0) +++ lutinjaxx/tags/0.7/pom.xml 2008-12-10 12:03:56 UTC (rev 1063) @@ -0,0 +1,215 @@ +<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.2</version> + </parent> + + <artifactId>lutinjaxx</artifactId> + + <modules> + <module>jaxx-util</module> + <module>jaxx-core</module> + <module>jaxx-swing-action</module> + <module>maven-jaxx-plugin</module> + </modules> + + <dependencies> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + </dependency> + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>lutinjaxx</name> + <version>0.7</version> + <description>Jaxx lutin library main pom</description> + <inceptionYear>2008</inceptionYear> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>pom</packaging> + + <properties> + + <!-- id du projet du labs --> + <labs.id>38</labs.id> + + <labs.project>buix</labs.project> + + <!-- lutinutil version --> + <lutinutil.version>1.0</lutinutil.version> + + <!-- multi-module level two son pom scm properties --> + <maven.scm.url.child.child> + http://${labs.host}/plugins/scmsvn/viewcvs.php/lutinjaxx/trunk/${project.parent.artifactId}/${project.artifactId}?root=${labs.project} + </maven.scm.url.child.child> + + <maven.scm.developerConnection.child.child> + scm:svn:svn+ssh://${username}@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/${project.parent.artifactId}/${project.artifactId} + </maven.scm.developerConnection.child.child> + + <maven.scm.connection.child.child> + scm:svn:svn://anonymous@${labs.host}/svnroot/${labs.project}/lutinjaxx/trunk/${project.parent.artifactId}/${project.artifactId} + </maven.scm.connection.child.child> + </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> + <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>${lutinutil.version}</version> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-util</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-swing-action</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>jaxx-example</artifactId> + <version>${project.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> + + <dependency> + <groupId>commons-jxpath</groupId> + <artifactId>commons-jxpath</artifactId> + <version>1.3</version> + </dependency> + + </dependencies> + </dependencyManagement> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/buix/lutinjaxx/tags/0.7</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/lutinjaxx/tags/0.7?root=buix</url> + </scm> + + <profiles> + <!-- by default example are included, use -Ddoexample=false to disable examples --> + <profile> + <id>doexample</id> + <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