This is an automated email from the git hooks/post-receive script. New commit to annotated tag v2.5.2 in repository jaxx. See https://gitlab.nuiton.org/nuiton/jaxx.git commit 183c193f5049daa68975a1cab26acac919c5530e Author: Maven Release Manager <???> Date: Tue Jul 17 17:31:29 2012 +0000 [maven-release-plugin] copy for tag jaxx-2.5.2 --- trunk/LICENSE.txt | 166 + trunk/README.txt | 2 + trunk/changelog.txt | 41 + trunk/jaxx-compiler/LICENSE.txt | 166 + trunk/jaxx-compiler/README.txt | 2 + trunk/jaxx-compiler/changelog.txt | 120 + trunk/jaxx-compiler/pom.xml | 174 + .../src/license/THIRD-PARTY.properties | 22 + .../src/main/java/jaxx/compiler/ClassMap.java | 117 + .../main/java/jaxx/compiler/CompiledObject.java | 794 ++ .../jaxx/compiler/CompiledObjectDecorator.java | 108 + .../java/jaxx/compiler/CompilerConfiguration.java | 140 + .../main/java/jaxx/compiler/CompilerException.java | 71 + .../compiler/DefaultCompilerConfiguration.java | 315 + .../src/main/java/jaxx/compiler/EventHandler.java | 89 + .../src/main/java/jaxx/compiler/I18nHelper.java | 97 + .../src/main/java/jaxx/compiler/IDHelper.java | 120 + .../src/main/java/jaxx/compiler/JAXXCompiler.java | 2002 ++++ .../main/java/jaxx/compiler/JAXXCompilerFile.java | 207 + .../src/main/java/jaxx/compiler/JAXXEngine.java | 482 + .../src/main/java/jaxx/compiler/JAXXFactory.java | 160 + .../src/main/java/jaxx/compiler/JAXXProfile.java | 389 + .../src/main/java/jaxx/compiler/SymbolTable.java | 92 + .../compiler/UnsupportedAttributeException.java | 68 + .../jaxx/compiler/UnsupportedTagException.java | 66 + .../java/jaxx/compiler/beans/BeanInfoUtil.java | 61 + .../jaxx/compiler/beans/JAXXBeanDescriptor.java | 40 + .../java/jaxx/compiler/beans/JAXXBeanInfo.java | 60 + .../compiler/beans/JAXXEventSetDescriptor.java | 61 + .../jaxx/compiler/beans/JAXXFeatureDescriptor.java | 77 + .../java/jaxx/compiler/beans/JAXXIntrospector.java | 191 + .../compiler/beans/JAXXPropertyDescriptor.java | 112 + .../java/jaxx/compiler/binding/DataBinding.java | 312 + .../jaxx/compiler/binding/DataBindingHelper.java | 263 + .../java/jaxx/compiler/binding/DataListener.java | 93 + .../java/jaxx/compiler/binding/DataSource.java | 885 ++ .../java/jaxx/compiler/binding/JavaParserUtil.java | 383 + .../compiler/binding/PseudoClassDataBinding.java | 134 + .../binding/writers/AbstractJAXXBindingWriter.java | 97 + .../binding/writers/DefaultJAXXBindingWriter.java | 137 + .../binding/writers/JAXXBindingWriter.java | 87 + .../writers/SimpleJAXXObjectBindingWriter.java | 111 + .../java/jaxx/compiler/css/StylesheetHelper.java | 703 ++ .../src/main/java/jaxx/compiler/css/parser/CSS.jj | 587 ++ .../src/main/java/jaxx/compiler/css/parser/CSS.jjt | 256 + .../java/jaxx/compiler/css/parser/CSSParser.java | 824 ++ .../compiler/css/parser/CSSParserConstants.java | 97 + .../compiler/css/parser/CSSParserTokenManager.java | 1177 +++ .../css/parser/CSSParserTreeConstants.java | 65 + .../compiler/css/parser/JJTCSSParserState.java | 148 + .../main/java/jaxx/compiler/css/parser/Node.java | 76 + .../jaxx/compiler/css/parser/ParseException.java | 45 + .../jaxx/compiler/css/parser/SimpleCharStream.java | 423 + .../java/jaxx/compiler/css/parser/SimpleNode.java | 147 + .../main/java/jaxx/compiler/css/parser/Token.java | 101 + .../jaxx/compiler/css/parser/TokenMgrError.java | 151 + .../decorators/BoxedCompiledObjectDecorator.java | 80 + .../decorators/DefaultCompiledObjectDecorator.java | 364 + .../HelpRootCompiledObjectDecorator.java | 226 + .../compiler/finalizers/AbstractFinalizer.java | 90 + .../jaxx/compiler/finalizers/DefaultFinalizer.java | 1301 +++ .../compiler/finalizers/JAXXCompilerFinalizer.java | 90 + .../jaxx/compiler/finalizers/SwingFinalizer.java | 93 + .../compiler/finalizers/ValidatorFinalizer.java | 266 + .../main/java/jaxx/compiler/java/JavaArgument.java | 86 + .../java/jaxx/compiler/java/JavaConstructor.java | 98 + .../main/java/jaxx/compiler/java/JavaElement.java | 133 + .../jaxx/compiler/java/JavaElementFactory.java | 186 + .../main/java/jaxx/compiler/java/JavaField.java | 299 + .../src/main/java/jaxx/compiler/java/JavaFile.java | 498 + .../java/jaxx/compiler/java/JavaFileGenerator.java | 456 + .../main/java/jaxx/compiler/java/JavaMethod.java | 354 + .../compiler/java/parser/JJTJavaParserState.java | 148 + .../main/java/jaxx/compiler/java/parser/Java1.5.jj | 5125 ++++++++++ .../java/jaxx/compiler/java/parser/Java1.5.jjt | 2150 ++++ .../jaxx/compiler/java/parser/JavaCharStream.java | 555 + .../java/jaxx/compiler/java/parser/JavaParser.java | 10073 +++++++++++++++++++ .../compiler/java/parser/JavaParserConstants.java | 285 + .../java/parser/JavaParserTokenManager.java | 2100 ++++ .../java/parser/JavaParserTreeConstants.java | 255 + .../main/java/jaxx/compiler/java/parser/Node.java | 76 + .../jaxx/compiler/java/parser/ParseException.java | 239 + .../java/jaxx/compiler/java/parser/SimpleNode.java | 160 + .../main/java/jaxx/compiler/java/parser/Token.java | 104 + .../jaxx/compiler/java/parser/TokenMgrError.java | 151 + .../jaxx/compiler/reflect/ClassDescriptor.java | 299 + .../compiler/reflect/ClassDescriptorHelper.java | 538 + .../compiler/reflect/ClassDescriptorResolver.java | 70 + .../jaxx/compiler/reflect/FieldDescriptor.java | 57 + .../jaxx/compiler/reflect/MemberDescriptor.java | 62 + .../jaxx/compiler/reflect/MethodDescriptor.java | 77 + .../ClassDescriptorResolverFromJavaClass.java | 203 + .../ClassDescriptorResolverFromJavaFile.java | 745 ++ .../ClassDescriptorResolverFromJaxxFile.java | 202 + .../jaxx/compiler/script/ScriptInitializer.java | 45 + .../java/jaxx/compiler/script/ScriptManager.java | 485 + .../java/jaxx/compiler/spi/DefaultInitializer.java | 237 + .../main/java/jaxx/compiler/spi/Initializer.java | 44 + .../compiler/tags/DefaultComponentHandler.java | 458 + .../jaxx/compiler/tags/DefaultObjectHandler.java | 1240 +++ .../java/jaxx/compiler/tags/ImportHandler.java | 104 + .../java/jaxx/compiler/tags/ScriptHandler.java | 118 + .../main/java/jaxx/compiler/tags/StyleHandler.java | 120 + .../main/java/jaxx/compiler/tags/TagHandler.java | 71 + .../main/java/jaxx/compiler/tags/TagManager.java | 650 ++ .../compiler/tags/swing/ApplicationHandler.java | 85 + .../java/jaxx/compiler/tags/swing/CellHandler.java | 224 + .../compiler/tags/swing/CompiledItemContainer.java | 71 + .../java/jaxx/compiler/tags/swing/ItemHandler.java | 177 + .../compiler/tags/swing/JAXXComboBoxHandler.java | 83 + .../jaxx/compiler/tags/swing/JAXXListHandler.java | 86 + .../jaxx/compiler/tags/swing/JAXXTabHandler.java | 36 + .../jaxx/compiler/tags/swing/JAXXTreeHandler.java | 91 + .../jaxx/compiler/tags/swing/JCheckBoxHandler.java | 47 + .../jaxx/compiler/tags/swing/JComboBoxHandler.java | 65 + .../compiler/tags/swing/JInternalFrameHandler.java | 75 + .../jaxx/compiler/tags/swing/JListHandler.java | 67 + .../jaxx/compiler/tags/swing/JMenuHandler.java | 47 + .../compiler/tags/swing/JPasswordFieldHandler.java | 46 + .../compiler/tags/swing/JPopupMenuHandler.java | 53 + .../compiler/tags/swing/JProgressBarHandler.java | 47 + .../compiler/tags/swing/JRadioButtonHandler.java | 109 + .../compiler/tags/swing/JScrollPaneHandler.java | 104 + .../jaxx/compiler/tags/swing/JSliderHandler.java | 70 + .../jaxx/compiler/tags/swing/JSpinnerHandler.java | 124 + .../compiler/tags/swing/JSplitPaneHandler.java | 102 + .../compiler/tags/swing/JTabbedPaneHandler.java | 171 + .../compiler/tags/swing/JTextComponentHandler.java | 115 + .../jaxx/compiler/tags/swing/JToolBarHandler.java | 81 + .../jaxx/compiler/tags/swing/JTreeHandler.java | 68 + .../jaxx/compiler/tags/swing/JWindowHandler.java | 83 + .../jaxx/compiler/tags/swing/JXLayerHandler.java | 111 + .../java/jaxx/compiler/tags/swing/RowHandler.java | 111 + .../java/jaxx/compiler/tags/swing/TabHandler.java | 221 + .../jaxx/compiler/tags/swing/TableHandler.java | 178 + .../tags/validator/BeanValidatorHandler.java | 1002 ++ .../validator/ExcludeFieldValidatorHandler.java | 125 + .../tags/validator/FieldValidatorHandler.java | 155 + .../jaxx/compiler/tasks/CompileFirstPassTask.java | 126 + .../jaxx/compiler/tasks/CompileSecondPassTask.java | 95 + .../java/jaxx/compiler/tasks/FinalizeTask.java | 78 + .../compiler/tasks/GenerateConstructorsTask.java | 511 + .../java/jaxx/compiler/tasks/GenerateTask.java | 208 + .../main/java/jaxx/compiler/tasks/InitTask.java | 86 + .../java/jaxx/compiler/tasks/JAXXEngineTask.java | 86 + .../main/java/jaxx/compiler/tasks/ProfileTask.java | 56 + .../java/jaxx/compiler/tasks/StyleSheetTask.java | 80 + .../java/jaxx/compiler/tools/PrintTagInfo.java | 145 + .../tools/jaxxcapture/AbstractContextNode.java | 44 + .../compiler/tools/jaxxcapture/CapturedObject.java | 171 + .../compiler/tools/jaxxcapture/ContextNode.java | 33 + .../compiler/tools/jaxxcapture/JAXXCapture.java | 404 + .../compiler/tools/jaxxcapture/LiteralNode.java | 45 + .../compiler/tools/jaxxcapture/MethodNode.java | 44 + .../compiler/tools/jaxxcapture/PropertyNode.java | 44 + .../jaxx/compiler/tools/jaxxcapture/ValueNode.java | 39 + .../jaxxcapture/handlers/JTabbedPaneHandler.java | 51 + .../tools/jaxxcapture/handlers/ObjectHandler.java | 351 + .../tools/jaxxcapture/handlers/TableHandler.java | 39 + .../java/jaxx/compiler/types/ColorConverter.java | 63 + .../types/GridBagConstraintsConverter.java | 51 + .../java/jaxx/compiler/types/InsetsConverter.java | 64 + .../jaxx/compiler/types/KeyStrokeConverter.java | 49 + .../jaxx/compiler/types/PrimitiveConverter.java | 125 + .../java/jaxx/compiler/types/TypeConverter.java | 35 + .../main/java/jaxx/compiler/types/TypeManager.java | 129 + .../services/jaxx.compiler.CompiledObjectDecorator | 3 + .../services/jaxx.compiler.JAXXCompilerFinalizer | 3 + .../services/jaxx.compiler.spi.Initializer | 1 + .../services/jaxx.compiler.types.TypeConverter | 5 + trunk/jaxx-compiler/src/site/rst/index.rst | 40 + trunk/jaxx-compiler/src/site/site_fr.xml | 67 + .../java/jaxx/compiler/beans/BeanIntoUtilTest.java | 59 + .../jaxx/compiler/binding/JavaParserUtilTest.java | 327 + .../java/jaxx/compiler/java/JavaFieldTest.java | 127 + .../java/jaxx/compiler/java/JavaMethodTest.java | 91 + .../jaxx/compiler/reflect/ClassDescriptorTest.java | 148 + .../jaxx/compiler/reflect/MyAbstractClass.java | 38 + .../java/jaxx/compiler/reflect/MyChildClass.java | 48 + .../java/jaxx/compiler/reflect/MyChildClass2.java | 40 + .../test/java/jaxx/compiler/reflect/MyClass.java | 68 + .../test/java/jaxx/compiler/reflect/MyEnum.java | 45 + .../java/jaxx/compiler/reflect/MyInterface.java | 38 + .../java/jaxx/compiler/reflect/MyInterface2.java | 40 + .../java/jaxx/compiler/reflect/MyInterface3.java | 40 + .../ClassDescriptorResolverFromJavaFileTest.java | 397 + .../java/jaxx/compiler/tags/TagManagerTest.java | 171 + .../jaxx/compiler/types/ColorConverterTest.java | 75 + .../jaxx/compiler/types/InsetsConverterTest.java | 74 + .../compiler/types/PrimitiveConverterTest.java | 137 + .../java/jaxx/compiler/types/TypeManagerTest.java | 80 + .../src/test/resources/log4j.properties | 32 + trunk/jaxx-demo/LICENSE.txt | 166 + trunk/jaxx-demo/README.txt | 2 + trunk/jaxx-demo/changelog.txt | 2 + trunk/jaxx-demo/pom.xml | 465 + trunk/jaxx-demo/src/license/THIRD-PARTY.properties | 19 + .../src/main/filters/jaxx-demo.properties | 34 + .../src/main/java/jaxx/demo/DemoConfig.java | 368 + .../src/main/java/jaxx/demo/DemoPanel.jaxx | 59 + .../src/main/java/jaxx/demo/DemoSources.jaxx | 108 + .../main/java/jaxx/demo/DemoSourcesHandler.java | 129 + .../jaxx-demo/src/main/java/jaxx/demo/DemoTab.jaxx | 62 + trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUI.css | 190 + .../jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx | 114 + .../src/main/java/jaxx/demo/DemoUIHandler.java | 578 ++ .../jaxx-demo/src/main/java/jaxx/demo/RunDemo.java | 202 + .../demo/component/jaxx/BoxedDecoratorDemo.css | 63 + .../demo/component/jaxx/BoxedDecoratorDemo.jaxx | 131 + .../component/jaxx/StatusMessagePanelDemo.jaxx | 35 + .../component/jaxx/editor/ComboEditorDemo.jaxx | 69 + .../demo/component/jaxx/editor/DatePickerDemo.jaxx | 98 + .../demo/component/jaxx/editor/FileEditorDemo.jaxx | 111 + .../demo/component/jaxx/editor/I18nEditorDemo.jaxx | 95 + .../component/jaxx/editor/ListSelectorDemo.jaxx | 103 + .../component/jaxx/editor/NumberEditorDemo.jaxx | 120 + .../jaxx/editor/NumberEditorDemoModel.java | 86 + .../demo/component/jaxx/editor/TimeEditorDemo.css | 50 + .../demo/component/jaxx/editor/TimeEditorDemo.jaxx | 114 + .../component/jaxx/editor/TimeEditorDemoModel.java | 79 + .../jaxx/demo/component/swing/HidorButtonDemo.jaxx | 45 + .../jaxx/demo/component/swing/JButtonDemo.jaxx | 62 + .../jaxx/demo/component/swing/JCheckBoxDemo.jaxx | 65 + .../component/swing/JCheckBoxMenuItemDemo.jaxx | 85 + .../jaxx/demo/component/swing/JComboBoxDemo.jaxx | 73 + .../jaxx/demo/component/swing/JDialogDemo.jaxx | 113 + .../java/jaxx/demo/component/swing/JListDemo.jaxx | 84 + .../jaxx/demo/component/swing/JMenuItemDemo.jaxx | 52 + .../demo/component/swing/JPasswordFieldDemo.jaxx | 35 + .../demo/component/swing/JProgressBarDemo.jaxx | 123 + .../demo/component/swing/JRadioButtonDemo.jaxx | 44 + .../component/swing/JRadioButtonMenuItemDemo.jaxx | 57 + .../jaxx/demo/component/swing/JSliderDemo.jaxx | 42 + .../jaxx/demo/component/swing/JSpinnerDemo.jaxx | 37 + .../jaxx/demo/component/swing/JSplitPaneDemo.jaxx | 41 + .../jaxx/demo/component/swing/JTextAreaDemo.jaxx | 54 + .../jaxx/demo/component/swing/JTextFieldDemo.jaxx | 48 + .../demo/component/swing/JToggleButtonDemo.jaxx | 35 + .../java/jaxx/demo/entities/AbstractDemoBean.java | 108 + .../java/jaxx/demo/entities/DemoDataProvider.java | 112 + .../jaxx/demo/entities/DemoDecoratorProvider.java | 51 + .../src/main/java/jaxx/demo/entities/Identity.java | 128 + .../src/main/java/jaxx/demo/entities/Model.java | 92 + .../src/main/java/jaxx/demo/entities/Movie.java | 141 + .../src/main/java/jaxx/demo/entities/People.java | 137 + .../feature/databinding/BaseBeanDataBinding.jaxx | 51 + .../feature/databinding/BeanDataBindingDemo.jaxx | 85 + .../feature/databinding/BindingExtremeDemo.jaxx | 292 + .../feature/databinding/DefaultDemoUIModel.java | 170 + .../jaxx/demo/feature/databinding/DemoUIModel.java | 99 + .../main/java/jaxx/demo/feature/nav/NavDemo.jaxx | 107 + .../java/jaxx/demo/feature/nav/NavDemoHandler.java | 300 + .../feature/nav/content/AbstractContentUI.jaxx | 50 + .../demo/feature/nav/content/ActorContentUI.jaxx | 62 + .../demo/feature/nav/content/ActorsContentUI.jaxx | 83 + .../demo/feature/nav/content/MovieContentUI.jaxx | 62 + .../demo/feature/nav/content/MoviesContentUI.jaxx | 82 + .../feature/nav/tree/ActorsTreeNodeLoador.java | 81 + .../feature/nav/tree/MoviesTreeNodeLoador.java | 96 + .../feature/nav/tree/NavDemoTreeCellRenderer.java | 116 + .../demo/feature/nav/tree/NavDemoTreeHelper.java | 88 + .../demo/feature/nav/tree/NavDemoTreeNode.java | 49 + .../nav/treetable/ActorsTreeTableNodeLoador.java | 82 + .../nav/treetable/MoviesTreeTableNodeLoador.java | 97 + .../nav/treetable/NavDemoTreeTableHelper.java | 88 + .../nav/treetable/NavDemoTreeTableModel.java | 119 + .../nav/treetable/NavDemoTreeTableNode.java | 47 + .../jaxx/demo/feature/validation/Validation.css | 29 + .../feature/validation/ValidationListDemo.jaxx | 372 + .../feature/validation/ValidationTableDemo.jaxx | 377 + .../src/main/java/jaxx/demo/fun/CalculatorDemo.css | 76 + .../main/java/jaxx/demo/fun/CalculatorDemo.jaxx | 146 + .../main/java/jaxx/demo/fun/CalculatorEngine.java | 211 + .../src/main/java/jaxx/demo/fun/CounterDemo.jaxx | 34 + .../src/main/java/jaxx/demo/fun/LabelStyleDemo.css | 58 + .../main/java/jaxx/demo/fun/LabelStyleDemo.jaxx | 133 + .../main/java/jaxx/demo/tree/DemoCellRenderer.java | 107 + .../main/java/jaxx/demo/tree/DemoDataProvider.java | 208 + .../src/main/java/jaxx/demo/tree/DemoNode.java | 69 + .../main/java/jaxx/demo/tree/DemoNodeLoador.java | 87 + .../main/java/jaxx/demo/tree/DemoTreeHelper.java | 61 + .../main/resources/i18n/jaxx-demo_en_GB.properties | 270 + .../main/resources/i18n/jaxx-demo_es_ES.properties | 270 + .../main/resources/i18n/jaxx-demo_fr_FR.properties | 270 + .../src/main/resources/icons/action-about.png | Bin 0 -> 936 bytes .../src/main/resources/icons/action-accept.png | Bin 0 -> 781 bytes .../src/main/resources/icons/action-block.png | Bin 0 -> 576 bytes .../src/main/resources/icons/action-close.png | Bin 0 -> 688 bytes .../src/main/resources/icons/action-config.png | Bin 0 -> 611 bytes .../src/main/resources/icons/action-exit.png | Bin 0 -> 830 bytes .../src/main/resources/icons/action-fullscreen.png | Bin 0 -> 687 bytes .../src/main/resources/icons/action-help.png | Bin 0 -> 746 bytes .../src/main/resources/icons/action-i18n-fr.png | Bin 0 -> 545 bytes .../src/main/resources/icons/action-i18n-uk.png | Bin 0 -> 599 bytes .../resources/icons/action-leave-fullscreen.png | Bin 0 -> 727 bytes .../resources/icons/action-reload-application.png | Bin 0 -> 463 bytes .../src/main/resources/icons/action-reload-log.png | Bin 0 -> 858 bytes .../src/main/resources/icons/action-reload-ui.png | Bin 0 -> 795 bytes .../src/main/resources/icons/action-show-help.png | Bin 0 -> 744 bytes .../src/main/resources/icons/action-site.png | Bin 0 -> 928 bytes .../src/main/resources/icons/action-translate.png | Bin 0 -> 790 bytes trunk/jaxx-demo/src/main/resources/icons/jaxx.png | Bin 0 -> 9503 bytes .../demo/entities/Identity-error-validation.xml | 73 + .../demo/entities/Identity-info-validation.xml | 73 + .../demo/entities/Identity-warning-validation.xml | 73 + .../jaxx/demo/entities/Model-error-validation.xml | 59 + .../jaxx/demo/entities/Model-info-validation.xml | 37 + .../demo/entities/Model-warning-validation.xml | 42 + .../main/resources/jaxx/demo/images/Amethyst.jpg | Bin 0 -> 24619 bytes .../src/main/resources/jaxx/demo/images/Lynx.jpg | Bin 0 -> 40463 bytes .../src/main/resources/jaxx/demo/images/Tomato.jpg | Bin 0 -> 22862 bytes .../src/main/resources/jaxx/demo/images/ana.jpg | Bin 0 -> 101898 bytes .../src/main/resources/jaxx/demo/images/hector.jpg | Bin 0 -> 40284 bytes .../src/main/resources/jaxx/demo/images/jack.jpg | Bin 0 -> 42155 bytes .../src/main/resources/jaxx/demo/images/joe.jpg | Bin 0 -> 10837 bytes .../src/main/resources/jaxx/demo/images/nacho.jpg | Bin 0 -> 46253 bytes .../src/main/resources/jaxx/demo/images/nacho2.png | Bin 0 -> 388751 bytes .../resources/jaxx/demo/images/pencil_black.gif | Bin 0 -> 190 bytes .../jaxx-demo/src/main/resources/log4j.properties | 40 + trunk/jaxx-demo/src/main/resources/validators.xml | 58 + .../src/site/rst/images/Components-screenshot.gif | Bin 0 -> 46663 bytes trunk/jaxx-demo/src/site/rst/index.rst | 71 + trunk/jaxx-demo/src/site/site_fr.xml | 76 + .../java/jaxx/demo/BeanValidatorDetectorTest.java | 82 + trunk/jaxx-maven-plugin/LICENSE.txt | 166 + trunk/jaxx-maven-plugin/README.txt | 2 + trunk/jaxx-maven-plugin/changelog.txt | 37 + trunk/jaxx-maven-plugin/pom.xml | 260 + .../src/license/THIRD-PARTY.properties | 29 + .../jaxx/plugin/AbstractGenerateHelpMojo.java | 278 + .../org/nuiton/jaxx/plugin/AbstractJaxxMojo.java | 187 + .../nuiton/jaxx/plugin/GenerateHelpFilesMojo.java | 521 + .../nuiton/jaxx/plugin/GenerateHelpIdsMojo.java | 142 + .../org/nuiton/jaxx/plugin/GenerateHelpMojo.java | 77 + .../nuiton/jaxx/plugin/GenerateHelpSearchMojo.java | 237 + .../java/org/nuiton/jaxx/plugin/GenerateMojo.java | 683 ++ .../main/java/org/nuiton/jaxx/plugin/NodeItem.java | 167 + .../java/org/nuiton/jaxx/plugin/XmlHelper.java | 234 + .../src/main/resources/defaultContent.html.vm | 14 + .../src/main/resources/defaultHelpSet.hs.vm | 44 + .../src/main/resources/defaultI18n.java.vm | 16 + .../src/main/resources/defaultIndex.xml.vm | 21 + .../src/main/resources/defaultMap.jhm.vm | 16 + .../src/main/resources/defaultToc.xml.vm | 20 + .../src/main/resources/log4j.properties | 35 + trunk/jaxx-maven-plugin/src/site/rst/Todo.rst | 30 + trunk/jaxx-maven-plugin/src/site/rst/index.rst | 55 + trunk/jaxx-maven-plugin/src/site/site_fr.xml | 81 + .../java/org/nuiton/jaxx/plugin/Bug1124Test.java | 99 + .../java/org/nuiton/jaxx/plugin/Bug1404Test.java | 47 + .../java/org/nuiton/jaxx/plugin/Bug1722Test.java | 40 + .../java/org/nuiton/jaxx/plugin/Bug1750Test.java | 71 + .../java/org/nuiton/jaxx/plugin/Bug1751Test.java | 43 + .../java/org/nuiton/jaxx/plugin/Bug184Test.java | 47 + .../java/org/nuiton/jaxx/plugin/CompilerTest.java | 325 + .../nuiton/jaxx/plugin/CompilerValidatorTest.java | 91 + .../org/nuiton/jaxx/plugin/DataBinding/Bean.java | 40 + .../nuiton/jaxx/plugin/DataBinding/BeanImpl.java | 62 + .../org/nuiton/jaxx/plugin/DataBindingTest.java | 59 + .../java/org/nuiton/jaxx/plugin/DecoratorTest.java | 40 + .../org/nuiton/jaxx/plugin/Evolution74Test.java | 106 + .../test/java/org/nuiton/jaxx/plugin/I18nTest.java | 70 + .../java/org/nuiton/jaxx/plugin/JaxxBaseTest.java | 111 + .../java/org/nuiton/jaxx/plugin/NodeItemTest.java | 79 + .../compilerTest/classReferences/JavaTaist.java | 33 + .../validator/ok/Identity.java | 103 + .../compilerValidatorTest/validator/ok/Model.java | 90 + .../src/test/resources/log4j.properties | 35 + .../nuiton/jaxx/plugin/bug1404Test/Bug_1404.xml | 53 + .../org/nuiton/jaxx/plugin/bug1404Test/Test1.jaxx | 27 + .../org/nuiton/jaxx/plugin/bug1404Test/Test2.jaxx | 27 + .../nuiton/jaxx/plugin/bug1404Test/TestParent.jaxx | 25 + .../nuiton/jaxx/plugin/bug1722Test/Bug_1722.xml | 52 + .../nuiton/jaxx/plugin/bug1722Test/DemoPanel.jaxx | 31 + .../jaxx/plugin/bug1722Test/JButtonDemo.jaxx | 29 + .../nuiton/jaxx/plugin/bug1750Test/Bug_1750.xml | 53 + .../nuiton/jaxx/plugin/bug1750Test/ComboBox.jaxx | 42 + .../nuiton/jaxx/plugin/bug1751Test/Bug_1751.xml | 54 + .../org/nuiton/jaxx/plugin/bug1751Test/Test1.jaxx | 25 + .../org/nuiton/jaxx/plugin/bug1751Test/Test2.jaxx | 25 + .../org/nuiton/jaxx/plugin/bug1751Test/Test3.jaxx | 25 + .../org/nuiton/jaxx/plugin/bug184Test/Bug_184.xml | 51 + .../org/nuiton/jaxx/plugin/bug184Test/MyPanel.jaxx | 37 + .../nuiton/jaxx/plugin/compilerTest/CSSTests.xml | 53 + .../jaxx/plugin/compilerTest/ClassReferences.xml | 51 + .../jaxx/plugin/compilerTest/ClientProperty.xml | 52 + .../ErrorJaxxContextImplementorClass.xml | 52 + .../org/nuiton/jaxx/plugin/compilerTest/Errors.xml | 55 + .../nuiton/jaxx/plugin/compilerTest/ErrorsCss.xml | 51 + .../org/nuiton/jaxx/plugin/compilerTest/Force.xml | 51 + .../org/nuiton/jaxx/plugin/compilerTest/Icon.xml | 54 + .../nuiton/jaxx/plugin/compilerTest/ImportTag.xml | 50 + .../jaxx/plugin/compilerTest/Initializers.xml | 51 + .../jaxx/plugin/compilerTest/InnerClasses.xml | 51 + .../org/nuiton/jaxx/plugin/compilerTest/NoLog.xml | 52 + .../plugin/compilerTest/OverridingDataBindings.xml | 51 + .../org/nuiton/jaxx/plugin/compilerTest/Script.xml | 51 + .../plugin/compilerTest/SpecialSubclassing.xml | 51 + .../nuiton/jaxx/plugin/compilerTest/WithLog.xml | 52 + .../plugin/compilerTest/cSSTests/CSSTests.jaxx | 48 + .../jaxx/plugin/compilerTest/cSSTests/Child.jaxx | 25 + .../jaxx/plugin/compilerTest/cSSTests/Child2.jaxx | 25 + .../plugin/compilerTest/cSSTests/GrandChild.jaxx | 55 + .../compilerTest/cSSTests/GrandChildButton.jaxx | 25 + .../compilerTest/cSSTests/Pseudoclasses.jaxx | 123 + .../plugin/compilerTest/cSSTests/SimpleCSS.jaxx | 56 + .../classReferences/ClassReferences.jaxx | 42 + .../classReferences/ConstructorReferenceTest.jaxx | 31 + .../classReferences/JAXXReferenceTest.jaxx | 31 + .../compilerTest/classReferences/JAXXTest.jaxx | 31 + .../classReferences/StaticMethodTest.jaxx | 31 + .../classReferences/TypeReference.jaxx | 25 + .../compilerTest/clientProperty/TestOne.jaxx | 27 + .../plugin/compilerTest/errors/AmbiguousName.jaxx | 34 + .../compilerTest/errors/BadTypeConversions.jaxx | 28 + .../compilerTest/errors/CellOutsideOfRow.jaxx | 29 + .../errors/ChildrenInNonContainer.jaxx | 28 + .../plugin/compilerTest/errors/ClassNotFound.jaxx | 27 + .../compilerTest/errors/ConflictingPackages.jaxx | 25 + .../compilerTest/errors/ConstraintsParseError.jaxx | 29 + .../compilerTest/errors/DataBindingParseError.jaxx | 30 + .../plugin/compilerTest/errors/DuplicateIDs.jaxx | 28 + .../errors/EventHandlerParseError.jaxx | 28 + .../jaxx/plugin/compilerTest/errors/InvalidID.jaxx | 27 + .../plugin/compilerTest/errors/InvalidRootTag.jaxx | 25 + .../plugin/compilerTest/errors/InvalidXML.jaxx | 28 + .../compilerTest/errors/ItemDuplicateValues.jaxx | 32 + .../plugin/compilerTest/errors/ItemNoValue.jaxx | 28 + .../plugin/compilerTest/errors/MixedContent.jaxx | 43 + .../compilerTest/errors/RowOutsideOfTable.jaxx | 33 + .../plugin/compilerTest/errors/RowWrongChild.jaxx | 33 + .../plugin/compilerTest/errors/ScriptNotFound.jaxx | 25 + .../compilerTest/errors/ScriptParseError.jaxx | 30 + .../compilerTest/errors/ScriptSourceAndInline.jaxx | 27 + .../plugin/compilerTest/errors/StyleNotFound.jaxx | 25 + .../compilerTest/errors/StyleParseError.jaxx | 33 + .../compilerTest/errors/StyleSourceAndInline.jaxx | 27 + .../errors/TabOutsideOfTabbedPane.jaxx | 33 + .../compilerTest/errors/TabbedPaneWrongChild.jaxx | 30 + .../compilerTest/errors/TableWrongChild.jaxx | 30 + .../compilerTest/errors/TooManyCellChildren.jaxx | 39 + .../errors/TooManyScrollPaneChildren.jaxx | 29 + .../errors/TooManySplitPaneChildren.jaxx | 31 + .../compilerTest/errors/TooManyTabChildren.jaxx | 37 + .../compilerTest/errors/UnsupportedAttribute.jaxx | 27 + .../compilerTest/errors/UnsupportedEvent.jaxx | 27 + .../errors/css/UnsupportedPseudoclass.jaxx | 29 + .../compilerTest/errors/dependencies/test.css | 25 + .../compilerTest/errors/dependencies/test.script | 1 + .../jaxx/plugin/compilerTest/force/JButton.jaxx | 25 + .../jaxx/plugin/compilerTest/icon/Test1.jaxx | 28 + .../plugin/compilerTest/importTag/ImportTag.jaxx | 32 + .../compilerTest/initializers/Initializers.jaxx | 61 + .../compilerTest/innerClasses/InnerClasses.jaxx | 41 + .../jaxx/plugin/compilerTest/log/nolog/NoLog.jaxx | 25 + .../plugin/compilerTest/log/nolog/NoLogSon.jaxx | 25 + .../plugin/compilerTest/log/withlog/WithLog.jaxx | 25 + .../compilerTest/log/withlog/WithLogTwo.jaxx | 25 + .../overridingDataBindings/CurrentTime.jaxx | 41 + .../OverriddenCurrentTime.jaxx | 25 + .../OverridingDataBindings.jaxx | 36 + .../compilerTest/script/JScriptInitializer.jaxx | 43 + .../specialSubclassing/JComboBoxTest1.jaxx | 27 + .../specialSubclassing/JComboBoxTest2.jaxx | 27 + .../specialSubclassing/JListTest1.jaxx | 27 + .../specialSubclassing/JListTest2.jaxx | 27 + .../specialSubclassing/JTreeTest1.jaxx | 27 + .../specialSubclassing/JTreeTest2.jaxx | 27 + .../specialSubclassing/SpecialSubclassing.jaxx | 50 + .../compilerValidatorTest/ValidatorErrors.xml | 53 + .../plugin/compilerValidatorTest/ValidatorOk.xml | 52 + .../errors/AutoFieldComponentNotFound.jaxx | 29 + .../validator/errors/DuplicatedBean.jaxx | 27 + .../validator/errors/DuplicatedBean2.jaxx | 29 + .../validator/errors/DuplicatedErrorListModel.jaxx | 28 + .../errors/DuplicatedErrorTableModel.jaxx | 28 + .../errors/DuplicatedFieldInSameValidator.jaxx | 31 + .../errors/FieldBeanPropertyNotFound.jaxx | 29 + .../validator/errors/FieldComponentDuplicated.jaxx | 31 + .../validator/errors/FieldComponentNotFound.jaxx | 29 + .../validator/errors/FieldComponentNotFound2.jaxx | 29 + .../validator/errors/FieldNoName.jaxx | 29 + .../validator/errors/FieldNoName2.jaxx | 29 + .../validator/errors/Model.java | 90 + .../validator/errors/NoBean.jaxx | 29 + .../validator/errors/UnfoundBean.jaxx | 27 + .../validator/errors/UnfoundErrorList.jaxx | 27 + .../validator/errors/UnfoundErrorListModel.jaxx | 27 + .../validator/errors/UnfoundErrorTable.jaxx | 27 + .../validator/errors/UnfoundErrorTableModel.jaxx | 27 + .../validator/errors/UnfoundParentValidator.jaxx | 27 + .../validator/ok/Validation.jaxx | 298 + .../validator/ok/ValidationBeanClass.jaxx | 136 + .../nuiton/jaxx/plugin/dataBindingTest/First.jaxx | 48 + .../jaxx/plugin/dataBindingTest/simpleBinding.xml | 51 + .../jaxx/plugin/decoratorTest/BoxedDecorator.jaxx | 27 + .../nuiton/jaxx/plugin/decoratorTest/Decorator.xml | 52 + .../nuiton/jaxx/plugin/evolution74Test/error.xml | 52 + .../plugin/evolution74Test/error/swingcombo.jaxx | 28 + .../plugin/evolution74Test/error/swinglist.jaxx | 28 + .../plugin/evolution74Test/error/swingtree.jaxx | 28 + .../org/nuiton/jaxx/plugin/evolution74Test/ok.xml | 51 + .../jaxx/plugin/evolution74Test/ok/jaxxcombo.jaxx | 28 + .../jaxx/plugin/evolution74Test/ok/jaxxlist.jaxx | 28 + .../jaxx/plugin/evolution74Test/ok/jaxxtree.jaxx | 28 + .../jaxx/plugin/evolution74Test/ok/swingcombo.jaxx | 26 + .../jaxx/plugin/evolution74Test/ok/swinglist.jaxx | 25 + .../jaxx/plugin/evolution74Test/ok/swingtree.jaxx | 26 + .../org/nuiton/jaxx/plugin/i18nTest/I18nText.xml | 52 + .../org/nuiton/jaxx/plugin/i18nTest/I18nTitle.xml | 52 + .../jaxx/plugin/i18nTest/I18nToolTipText.xml | 52 + .../nuiton/jaxx/plugin/i18nTest/text/JButton.jaxx | 25 + .../nuiton/jaxx/plugin/i18nTest/title/JDialog.jaxx | 25 + .../jaxx/plugin/i18nTest/title/JTabbedPane.jaxx | 27 + .../jaxx/plugin/i18nTest/title/JTabbedPane2.jaxx | 29 + .../jaxx/plugin/i18nTest/tooltiptext/JButton.jaxx | 25 + .../plugin/i18nTest/tooltiptext/JTabbedPane.jaxx | 27 + .../plugin/i18nTest/tooltiptext/JTabbedPane2.jaxx | 27 + .../plugin/i18nTest/tooltiptext/JTabbedPane3.jaxx | 29 + trunk/jaxx-runtime/LICENSE.txt | 166 + trunk/jaxx-runtime/README.txt | 2 + trunk/jaxx-runtime/changelog.txt | 109 + trunk/jaxx-runtime/pom.xml | 108 + .../src/license/THIRD-PARTY.properties | 20 + .../src/main/java/jaxx/runtime/Base64Coder.java | 267 + .../java/jaxx/runtime/ComponentDescriptor.java | 73 + .../java/jaxx/runtime/DataBindingListener.java | 68 + .../jaxx/runtime/DataBindingUpdateListener.java | 68 + .../src/main/java/jaxx/runtime/JAXXAction.java | 45 + .../src/main/java/jaxx/runtime/JAXXBinding.java | 60 + .../src/main/java/jaxx/runtime/JAXXContext.java | 132 + .../src/main/java/jaxx/runtime/JAXXObject.java | 170 + .../java/jaxx/runtime/JAXXObjectDescriptor.java | 64 + .../src/main/java/jaxx/runtime/JAXXUtil.java | 639 ++ .../src/main/java/jaxx/runtime/SwingUtil.java | 1276 +++ .../jaxx/runtime/binding/DefaultJAXXBinding.java | 165 + .../runtime/binding/SimpleJAXXObjectBinding.java | 84 + .../java/jaxx/runtime/context/DataContext.java | 452 + .../runtime/context/DefaultApplicationContext.java | 476 + .../jaxx/runtime/context/DefaultJAXXContext.java | 232 + .../jaxx/runtime/context/JAXXContextEntryDef.java | 141 + .../jaxx/runtime/context/JAXXInitialContext.java | 121 + .../main/java/jaxx/runtime/css/DataBinding.java | 52 + .../main/java/jaxx/runtime/css/Pseudoclasses.java | 205 + .../src/main/java/jaxx/runtime/css/Rule.java | 76 + .../src/main/java/jaxx/runtime/css/Selector.java | 122 + .../src/main/java/jaxx/runtime/css/Stylesheet.java | 66 + .../main/java/jaxx/runtime/swing/Application.java | 75 + .../java/jaxx/runtime/swing/BlockingLayerUI.java | 345 + .../java/jaxx/runtime/swing/BlockingLayerUI2.java | 238 + .../main/java/jaxx/runtime/swing/CardLayout2.java | 253 + .../java/jaxx/runtime/swing/CardLayout2Ext.java | 131 + .../src/main/java/jaxx/runtime/swing/GBC.java | 132 + .../src/main/java/jaxx/runtime/swing/HBox.java | 119 + .../main/java/jaxx/runtime/swing/HBoxBeanInfo.java | 76 + .../main/java/jaxx/runtime/swing/HBoxLayout.java | 149 + .../src/main/java/jaxx/runtime/swing/Item.java | 253 + .../java/jaxx/runtime/swing/JAXXButtonGroup.java | 253 + .../main/java/jaxx/runtime/swing/JAXXComboBox.java | 315 + .../src/main/java/jaxx/runtime/swing/JAXXList.java | 417 + .../src/main/java/jaxx/runtime/swing/JAXXTab.java | 31 + .../java/jaxx/runtime/swing/JAXXToggleButton.java | 125 + .../src/main/java/jaxx/runtime/swing/JAXXTree.java | 281 + .../runtime/swing/OneClicListSelectionModel.java | 208 + .../src/main/java/jaxx/runtime/swing/Spacer.java | 32 + .../src/main/java/jaxx/runtime/swing/TabInfo.java | 234 + .../swing/TabInfoPropertyChangeListener.java | 68 + .../src/main/java/jaxx/runtime/swing/Table.java | 82 + .../src/main/java/jaxx/runtime/swing/VBox.java | 119 + .../main/java/jaxx/runtime/swing/VBoxBeanInfo.java | 76 + .../main/java/jaxx/runtime/swing/VBoxLayout.java | 149 + .../runtime/swing/application/ActionExecutor.java | 279 + .../runtime/swing/application/ActionWorker.java | 178 + .../swing/application/ApplicationRunner.java | 250 + .../runtime/swing/editor/BooleanCellEditor.java | 83 + .../jaxx/runtime/swing/editor/ClassCellEditor.java | 126 + .../java/jaxx/runtime/swing/editor/EnumEditor.java | 143 + .../jaxx/runtime/swing/editor/LocaleEditor.java | 74 + .../runtime/swing/editor/MyDefaultCellEditor.java | 127 + .../jaxx/runtime/swing/help/JAXXHelpBroker.java | 590 ++ .../java/jaxx/runtime/swing/help/JAXXHelpUI.java | 44 + .../jaxx/runtime/swing/help/JAXXHelpUIHandler.java | 33 + .../model/AbstractGenericListSelectionModel.java | 275 + .../jaxx/runtime/swing/model/GenericListEvent.java | 44 + .../runtime/swing/model/GenericListListener.java | 40 + .../jaxx/runtime/swing/model/GenericListModel.java | 164 + .../swing/model/GenericListSelectionModel.java | 53 + .../java/jaxx/runtime/swing/nav/NavBridge.java | 125 + .../jaxx/runtime/swing/nav/NavDataProvider.java | 46 + .../java/jaxx/runtime/swing/nav/NavHelper.java | 965 ++ .../main/java/jaxx/runtime/swing/nav/NavNode.java | 223 + .../jaxx/runtime/swing/nav/NavNodeChildLoador.java | 170 + .../main/java/jaxx/runtime/swing/nav/package.html | 87 + .../nav/tree/AbstractNavTreeCellRenderer.java | 128 + .../jaxx/runtime/swing/nav/tree/NavTreeBridge.java | 240 + .../jaxx/runtime/swing/nav/tree/NavTreeHelper.java | 185 + .../jaxx/runtime/swing/nav/tree/NavTreeNode.java | 428 + .../swing/nav/tree/NavTreeNodeChildLoador.java | 44 + .../java/jaxx/runtime/swing/nav/tree/package.html | 45 + .../swing/nav/treetable/NavTreeTableBridge.java | 297 + .../swing/nav/treetable/NavTreeTableHelper.java | 183 + .../swing/nav/treetable/NavTreeTableModel.java | 215 + .../swing/nav/treetable/NavTreeTableNode.java | 379 + .../nav/treetable/NavTreeTableNodeChildLoador.java | 42 + .../jaxx/runtime/swing/nav/treetable/package.html | 45 + .../swing/renderer/BooleanCellRenderer.java | 85 + .../swing/renderer/DecoratorListCellRenderer.java | 78 + .../DecoratorProviderListCellRenderer.java | 78 + .../DecoratorProviderTableCellRenderer.java | 76 + .../swing/renderer/DecoratorTableCellRenderer.java | 65 + .../renderer/EmptyNumberTableCellRenderer.java | 64 + .../swing/renderer/EnumTableCellRenderer.java | 69 + .../swing/renderer/I18nTableCellRenderer.java | 109 + .../swing/renderer/LocaleListCellRenderer.java | 152 + .../renderer/MultiDecoratorListCellRenderer.java | 85 + .../renderer/MultiDecoratorTableCelleRenderer.java | 100 + .../runtime/swing/wizard/BusyChangeListener.java | 116 + .../jaxx/runtime/swing/wizard/WizardModel.java | 312 + .../java/jaxx/runtime/swing/wizard/WizardStep.java | 44 + .../jaxx/runtime/swing/wizard/WizardStepUI.java | 38 + .../java/jaxx/runtime/swing/wizard/WizardUI.java | 84 + .../jaxx/runtime/swing/wizard/WizardUILancher.java | 255 + .../java/jaxx/runtime/swing/wizard/WizardUtil.java | 194 + .../runtime/swing/wizard/ext/WizardExtModel.java | 438 + .../runtime/swing/wizard/ext/WizardExtStep.java | 78 + .../swing/wizard/ext/WizardExtStepModel.java | 111 + .../jaxx/runtime/swing/wizard/ext/WizardExtUI.java | 60 + .../runtime/swing/wizard/ext/WizardExtUtil.java | 124 + .../jaxx/runtime/swing/wizard/ext/WizardState.java | 51 + .../jaxx/runtime/swing/wizard/ext/package.html | 33 + .../java/jaxx/runtime/swing/wizard/package.html | 33 + .../resources/i18n/jaxx-runtime_en_GB.properties | 15 + .../resources/i18n/jaxx-runtime_fr_FR.properties | 15 + .../src/main/resources/icons/action-delete.png | Bin 0 -> 783 bytes .../resources/icons/action-wizard-config-16.png | Bin 0 -> 611 bytes .../main/resources/icons/action-wizard-config.png | Bin 0 -> 4639 bytes .../resources/icons/action-wizard-message-16.png | Bin 0 -> 778 bytes .../main/resources/icons/action-wizard-message.png | Bin 0 -> 4433 bytes .../main/resources/icons/action-wizard-next-16.png | Bin 0 -> 676 bytes .../main/resources/icons/action-wizard-next.png | Bin 0 -> 4458 bytes .../resources/icons/action-wizard-pause-16.png | Bin 0 -> 598 bytes .../main/resources/icons/action-wizard-pause.png | Bin 0 -> 4323 bytes .../resources/icons/action-wizard-previous-16.png | Bin 0 -> 655 bytes .../resources/icons/action-wizard-previous.png | Bin 0 -> 4449 bytes .../resources/icons/action-wizard-refresh-16.png | Bin 0 -> 685 bytes .../main/resources/icons/action-wizard-refresh.png | Bin 0 -> 4761 bytes .../resources/icons/action-wizard-start-16.png | Bin 0 -> 592 bytes .../main/resources/icons/action-wizard-start.png | Bin 0 -> 4469 bytes .../icons/action-wizard-state-canceled-16.png | Bin 0 -> 587 bytes .../icons/action-wizard-state-canceled.png | Bin 0 -> 4340 bytes .../icons/action-wizard-state-failed-16.png | Bin 0 -> 701 bytes .../resources/icons/action-wizard-state-failed.png | Bin 0 -> 4197 bytes .../icons/action-wizard-state-need_fix-16.png | Bin 0 -> 666 bytes .../icons/action-wizard-state-need_fix.png | Bin 0 -> 4567 bytes .../icons/action-wizard-state-pending-16.png | Bin 0 -> 403 bytes .../icons/action-wizard-state-pending.png | Bin 0 -> 4284 bytes .../icons/action-wizard-state-running-16.png | Bin 0 -> 592 bytes .../icons/action-wizard-state-running.png | Bin 0 -> 4483 bytes .../icons/action-wizard-state-successed-16.png | Bin 0 -> 537 bytes .../icons/action-wizard-state-successed.png | Bin 0 -> 4447 bytes .../src/main/resources/icons/error.png | Bin 0 -> 701 bytes .../src/main/resources/icons/fatal.png | Bin 0 -> 715 bytes .../jaxx-runtime/src/main/resources/icons/info.png | Bin 0 -> 778 bytes .../src/main/resources/icons/warning.png | Bin 0 -> 666 bytes trunk/jaxx-runtime/src/site/rst/index.rst | 39 + trunk/jaxx-runtime/src/site/site_fr.xml | 70 + .../src/test/java/jaxx/runtime/UtilTest.java | 53 + .../context/DataContextEntryIteratorTest.java | 288 + .../context/DefaultApplicationContextTest.java | 224 + .../runtime/context/DefaultJAXXContextTest.java | 259 + .../src/test/resources/log4j.properties | 32 + trunk/jaxx-swing-action/LICENSE.txt | 166 + trunk/jaxx-swing-action/README.txt | 2 + trunk/jaxx-swing-action/changelog.txt | 10 + trunk/jaxx-swing-action/pom.xml | 111 + .../AbstractActionConfigurationResolver.java | 88 + .../jaxx/action/ActionAnnotationProcessing.java | 408 + .../java/org/nuiton/jaxx/action/ActionConfig.java | 129 + .../action/ActionConfigConfigurationResolver.java | 80 + .../jaxx/action/ActionConfigurationResolver.java | 65 + .../java/org/nuiton/jaxx/action/ActionFactory.java | 160 + .../jaxx/action/ActionFactoryFromProvider.java | 495 + .../org/nuiton/jaxx/action/ActionNameProvider.java | 44 + .../org/nuiton/jaxx/action/ActionProvider.java | 48 + .../jaxx/action/ActionProviderAnnotation.java | 44 + .../jaxx/action/ActionProviderFromProperties.java | 145 + .../org/nuiton/jaxx/action/MyAbstractAction.java | 270 + .../org/nuiton/jaxx/action/SelectActionConfig.java | 102 + .../SelectActionConfigConfigurationResolver.java | 64 + .../org/nuiton/jaxx/action/ToggleActionConfig.java | 163 + .../ToggleActionConfigConfigurationResolver.java | 92 + .../java/org/nuiton/jaxx/tab/TabContentConfig.java | 60 + .../main/java/org/nuiton/jaxx/tab/TabFactory.java | 243 + .../main/java/org/nuiton/jaxx/tab/TabModel.java | 54 + .../org/nuiton/jaxx/util/AbstractUIAction.java | 65 + .../main/java/org/nuiton/jaxx/util/DialogUI.java | 147 + .../java/org/nuiton/jaxx/util/DialogUIDef.java | 248 + .../java/org/nuiton/jaxx/util/DialogUIHandler.java | 82 + .../java/org/nuiton/jaxx/util/DialogUIModel.java | 107 + .../nuiton/jaxx/util/FactoryWindowListener.java | 94 + .../java/org/nuiton/jaxx/util/FormElement.java | 41 + .../java/org/nuiton/jaxx/util/ShowUIAction.java | 150 + .../main/java/org/nuiton/jaxx/util/UIFactory.java | 193 + .../main/java/org/nuiton/jaxx/util/UIHelper.java | 95 + .../main/java/org/nuiton/jaxx/util/UIProvider.java | 96 + .../services/javax.annotation.processing.Processor | 1 + .../i18n/jaxx-swing-action-en_GB.properties | 10 + .../i18n/jaxx-swing-action-fr_FR.properties | 10 + trunk/jaxx-swing-action/src/site/rst/Todo.rst | 30 + trunk/jaxx-swing-action/src/site/rst/index.rst | 37 + trunk/jaxx-swing-action/src/site/site_fr.xml | 98 + trunk/jaxx-validator/LICENSE.txt | 166 + trunk/jaxx-validator/README.txt | 0 trunk/jaxx-validator/changelog.txt | 0 trunk/jaxx-validator/pom.xml | 181 + .../src/license/THIRD-PARTY.properties | 21 + .../src/main/java/jaxx/runtime/JAXXValidator.java | 65 + .../runtime/validator/swing/SwingValidator.java | 361 + .../validator/swing/SwingValidatorMessage.java | 116 + .../swing/SwingValidatorMessageListModel.java | 194 + .../SwingValidatorMessageListMouseListener.java | 93 + .../swing/SwingValidatorMessageListRenderer.java | 134 + .../swing/SwingValidatorMessageTableModel.java | 380 + .../SwingValidatorMessageTableMouseListener.java | 129 + .../swing/SwingValidatorMessageTableRenderer.java | 123 + .../validator/swing/SwingValidatorUtil.java | 564 ++ .../runtime/validator/swing/meta/Validator.java | 48 + .../validator/swing/meta/ValidatorField.java | 63 + .../swing/ui/AbstractBeanValidatorUI.java | 83 + .../validator/swing/ui/IconValidationUI.java | 105 + .../validator/swing/ui/ImageValidationUI.java | 94 + .../swing/ui/TranslucentValidationUI.java | 76 + .../resources/i18n/jaxx-validator_en_GB.properties | 9 + .../resources/i18n/jaxx-validator_es_ES.properties | 9 + .../resources/i18n/jaxx-validator_fr_FR.properties | 9 + trunk/jaxx-validator/src/site/rst/index.rst | 39 + trunk/jaxx-validator/src/site/site_fr.xml | 69 + .../src/test/resources/log4j.properties | 32 + .../src/test/resources/validators.xml | 62 + trunk/jaxx-widgets/LICENSE.txt | 166 + trunk/jaxx-widgets/README.txt | 2 + trunk/jaxx-widgets/changelog.txt | 5 + trunk/jaxx-widgets/pom.xml | 180 + .../src/license/THIRD-PARTY.properties | 20 + .../main/java/jaxx/runtime/swing/AboutPanel.jaxx | 142 + .../java/jaxx/runtime/swing/AboutPanelHandler.java | 190 + .../java/jaxx/runtime/swing/BaseActionPanel.java | 78 + .../main/java/jaxx/runtime/swing/ClockWidget.jaxx | 83 + .../jaxx/runtime/swing/ComboToListSelector.jaxx | 89 + .../java/jaxx/runtime/swing/ErrorDialogUI.jaxx | 87 + .../jaxx/runtime/swing/ErrorDialogUIHandler.java | 98 + .../main/java/jaxx/runtime/swing/FontSizor.jaxx | 90 + .../java/jaxx/runtime/swing/FontSizorHandler.java | 84 + .../main/java/jaxx/runtime/swing/HidorButton.jaxx | 77 + .../jaxx/runtime/swing/HidorButtonHandler.java | 97 + .../java/jaxx/runtime/swing/JAXXDatePicker.jaxx | 61 + .../java/jaxx/runtime/swing/JAXXWidgetUtil.java | 63 + .../main/java/jaxx/runtime/swing/ListSelector.jaxx | 80 + .../java/jaxx/runtime/swing/ListSelectorModel.java | 187 + .../jaxx/runtime/swing/ListToListSelector.jaxx | 90 + .../jaxx/runtime/swing/MemoryStatusWidget.jaxx | 81 + .../runtime/swing/MemoryStatusWidgetHandler.java | 101 + .../jaxx/runtime/swing/StatusMessagePanel.jaxx | 143 + .../runtime/swing/StatusMessagePanelHandler.java | 127 + .../java/jaxx/runtime/swing/editor/FileEditor.jaxx | 80 + .../runtime/swing/editor/FileEditorHandler.java | 169 + .../java/jaxx/runtime/swing/editor/I18nEditor.jaxx | 147 + .../runtime/swing/editor/I18nEditorHandler.java | 250 + .../jaxx/runtime/swing/editor/KeyStrokeEditor.java | 82 + .../jaxx/runtime/swing/editor/NumberEditor.jaxx | 199 + .../runtime/swing/editor/NumberEditorHandler.java | 642 ++ .../runtime/swing/editor/NumberEditorPopup.css | 50 + .../java/jaxx/runtime/swing/editor/TimeEditor.css | 61 + .../java/jaxx/runtime/swing/editor/TimeEditor.jaxx | 90 + .../runtime/swing/editor/TimeEditorHandler.java | 347 + .../runtime/swing/editor/bean/BeanComboBox.jaxx | 153 + .../swing/editor/bean/BeanComboBoxHandler.java | 389 + .../runtime/swing/editor/bean/BeanListHeader.jaxx | 139 + .../swing/editor/bean/BeanListHeaderHandler.java | 274 + .../jaxx/runtime/swing/editor/bean/BeanUIUtil.java | 404 + .../jaxx/runtime/swing/editor/bean/package.html | 35 + .../runtime/swing/editor/cell/DateCellEditor.java | 55 + .../runtime/swing/editor/cell/FileCellEditor.java | 73 + .../swing/editor/cell/KeyStrokeCellEditor.java | 64 + .../swing/editor/cell/NumberCellEditor.java | 129 + .../swing/editor/config/ConfigCallBackUI.jaxx | 66 + .../editor/config/ConfigCallBackUIHandler.java | 190 + .../swing/editor/config/ConfigCategoryUI.css | 68 + .../swing/editor/config/ConfigCategoryUI.jaxx | 133 + .../swing/editor/config/ConfigTableEditor.java | 161 + .../swing/editor/config/ConfigTableRenderer.java | 138 + .../jaxx/runtime/swing/editor/config/ConfigUI.css | 34 + .../jaxx/runtime/swing/editor/config/ConfigUI.jaxx | 67 + .../swing/editor/config/ConfigUIHandler.java | 349 + .../swing/editor/config/ConfigUIHelper.java | 157 + .../swing/editor/config/model/CallBackEntry.java | 81 + .../editor/config/model/CallBackFinalizer.java | 43 + .../swing/editor/config/model/CallBackMap.java | 59 + .../editor/config/model/CallBacksManager.java | 252 + .../swing/editor/config/model/CategoryModel.java | 213 + .../editor/config/model/ConfigTableModel.java | 156 + .../swing/editor/config/model/ConfigUIModel.java | 354 + .../editor/config/model/ConfigUIModelBuilder.java | 333 + .../editor/config/model/MainCallBackFinalizer.java | 66 + .../swing/editor/config/model/OptionModel.java | 164 + .../runtime/swing/editor/config/model/package.html | 31 + .../jaxx/runtime/swing/editor/config/package.html | 42 + .../java/jaxx/runtime/swing/editor/package.html | 36 + .../jaxx/runtime/swing/log/JAXXLog4jAppender.java | 141 + .../jaxx/runtime/swing/log/JAXXLog4jHandler.java | 126 + .../java/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx | 121 + .../src/main/java/jaxx/runtime/swing/package.html | 49 + .../runtime/swing/renderer/DateCellRenderer.java | 62 + .../plaf/basic/ExtendedBasicDatePickerUI.java | 91 + .../resources/i18n/jaxx-widgets_en_GB.properties | 86 + .../resources/i18n/jaxx-widgets_es_ES.properties | 86 + .../resources/i18n/jaxx-widgets_fr_FR.properties | 86 + .../src/main/resources/icons/action-add.png | Bin 0 -> 733 bytes .../main/resources/icons/action-bean-sort-down.png | Bin 0 -> 594 bytes .../main/resources/icons/action-bean-sort-up.png | Bin 0 -> 599 bytes .../src/main/resources/icons/action-bean-sort.png | Bin 0 -> 463 bytes .../src/main/resources/icons/action-collapse.png | Bin 0 -> 372 bytes .../main/resources/icons/action-combobox-reset.png | Bin 0 -> 396 bytes .../main/resources/icons/action-combobox-sort.png | Bin 0 -> 574 bytes .../main/resources/icons/action-config-quit.png | Bin 0 -> 688 bytes .../main/resources/icons/action-config-reset.png | Bin 0 -> 587 bytes .../main/resources/icons/action-config-save.png | Bin 0 -> 838 bytes .../src/main/resources/icons/action-expand.png | Bin 0 -> 371 bytes .../main/resources/icons/action-font-size-down.png | Bin 0 -> 300 bytes .../main/resources/icons/action-font-size-up.png | Bin 0 -> 356 bytes .../src/main/resources/icons/action-font-size.png | Bin 0 -> 295 bytes .../src/main/resources/icons/action-i18n-be.png | Bin 0 -> 449 bytes .../src/main/resources/icons/action-i18n-ca.png | Bin 0 -> 628 bytes .../src/main/resources/icons/action-i18n-ch.png | Bin 0 -> 367 bytes .../src/main/resources/icons/action-i18n-de.png | Bin 0 -> 545 bytes .../src/main/resources/icons/action-i18n-dk.png | Bin 0 -> 495 bytes .../src/main/resources/icons/action-i18n-es.png | Bin 0 -> 469 bytes .../src/main/resources/icons/action-i18n-fi.png | Bin 0 -> 489 bytes .../src/main/resources/icons/action-i18n-fr.png | Bin 0 -> 545 bytes .../src/main/resources/icons/action-i18n-gb.png | Bin 0 -> 599 bytes .../src/main/resources/icons/action-i18n-it.png | Bin 0 -> 420 bytes .../src/main/resources/icons/action-i18n-nl.png | Bin 0 -> 453 bytes .../src/main/resources/icons/action-i18n-no.png | Bin 0 -> 512 bytes .../src/main/resources/icons/action-i18n-se.png | Bin 0 -> 542 bytes .../src/main/resources/icons/action-i18n-us.png | Bin 0 -> 609 bytes .../icons/action-numbereditor-calculator.png | Bin 0 -> 543 bytes .../resources/icons/action-numbereditor-reset.png | Bin 0 -> 396 bytes .../icons/action-numbereditor-validate.png | Bin 0 -> 537 bytes .../src/main/resources/icons/action-open.png | Bin 0 -> 606 bytes .../src/main/resources/icons/action-remove.png | Bin 0 -> 715 bytes .../src/main/resources/icons/action-select.png | Bin 0 -> 733 bytes .../src/main/resources/icons/action-unselect.png | Bin 0 -> 715 bytes trunk/jaxx-widgets/src/site/rst/index.rst | 52 + trunk/jaxx-widgets/src/site/site_fr.xml | 69 + .../config/model/ConfigUIModelBuilderTest.java | 298 + .../swing/editor/config/model/MyConfig.java | 241 + .../src/test/resources/log4j.properties | 34 + trunk/pom.xml | 645 ++ trunk/src/site/resources/demo1.png | Bin 0 -> 104591 bytes trunk/src/site/resources/demo2.png | Bin 0 -> 65982 bytes trunk/src/site/resources/jaxx.png | Bin 0 -> 9503 bytes .../site/resources/tutos/alwaysEnabledButton.png | Bin 0 -> 3011 bytes trunk/src/site/resources/tutos/disabledButton.png | Bin 0 -> 2794 bytes trunk/src/site/resources/tutos/enabledButton.png | Bin 0 -> 3315 bytes trunk/src/site/resources/tutos/helloworld.png | Bin 0 -> 2697 bytes .../resources/tutos/helloworld2-red-big-button.png | Bin 0 -> 4337 bytes .../site/resources/tutos/helloworld2-red-big.png | Bin 0 -> 3323 bytes trunk/src/site/resources/tutos/helloworld2-red.png | Bin 0 -> 2778 bytes trunk/src/site/resources/tutos/sliderAfter100.png | Bin 0 -> 3511 bytes trunk/src/site/resources/tutos/sliderBefore100.png | Bin 0 -> 4138 bytes trunk/src/site/resources/tutos/webstart.gif | Bin 0 -> 1806 bytes trunk/src/site/rst/BeanValidator.rst | 177 + trunk/src/site/rst/Core.rst | 180 + trunk/src/site/rst/I18n.rst | 115 + trunk/src/site/rst/JAXXContext.rst | 186 + trunk/src/site/rst/JAXXFile.rst | 49 + trunk/src/site/rst/NavigationModel.rst | 296 + trunk/src/site/rst/Todo.rst | 34 + trunk/src/site/rst/contractProgramming.rst | 97 + trunk/src/site/rst/dataBinding.rst | 95 + trunk/src/site/rst/demo.rst | 58 + trunk/src/site/rst/index.rst | 355 + trunk/src/site/rst/javaBeans.rst | 58 + trunk/src/site/rst/migration.rst | 64 + .../site/rst/old-compiler-doc/BeanValidator.rst | 206 + trunk/src/site/rst/old-compiler-doc/I18n.rst | 81 + trunk/src/site/rst/old-compiler-doc/Interface.rst | 63 + .../src/site/rst/old-compiler-doc/JAXXContext.rst | 186 + trunk/src/site/rst/old-compiler-doc/JavaBean.rst | 75 + .../rst/old-compiler-doc/NavigationTreeModel.rst | 193 + trunk/src/site/rst/presentation.rst | 50 + trunk/src/site/rst/scripting.rst | 104 + trunk/src/site/rst/spec-validator2.rst | 80 + trunk/src/site/rst/tutoriels.rst | 33 + trunk/src/site/rst/tutos/config.rst | 54 + trunk/src/site/rst/tutos/css.rst | 140 + trunk/src/site/rst/tutos/data-binding.rst | 131 + trunk/src/site/rst/tutos/helloworld.rst | 186 + trunk/src/site/rst/tutos/helloworld2.rst | 140 + trunk/src/site/rst/useStylesheets.rst | 169 + trunk/src/site/rst/useSwingObjects.rst | 69 + trunk/src/site/site_fr.xml | 148 + 902 files changed, 120564 insertions(+) diff --git a/trunk/LICENSE.txt b/trunk/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/README.txt b/trunk/README.txt new file mode 100644 index 0000000..d2e50d3 --- /dev/null +++ b/trunk/README.txt @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install diff --git a/trunk/changelog.txt b/trunk/changelog.txt new file mode 100644 index 0000000..745ec8d --- /dev/null +++ b/trunk/changelog.txt @@ -0,0 +1,41 @@ +1.7.1 + +1.7.0 + * reorganize modules + +1.6.0-rc-6 + * migrate to nuiton + +1.5.1 chemit 20090511 + * 20090511 [chemit] - bump versions (lutinproject, jrst, lutinutil, maven-i18n-plugin, maven-license-switcher-plugin) + +1.5 + * 20090506 [chemit] - super-pom has no dependencies, use lutinutil 1.0.5 + * 20090404 [chemit] - introduce module jaxx-runtime-swing-widget for swing widgets designed with jaxx. + +1.4 + * 20090402 [chemit] - use lutinproject 3.5.3 + - use doxia-module-jrst 1.0.0 (instead of maven-jrst-plugin) + - use maven-i18n-plugin 0.11 + - use maven-license-switcher 0.7 + +1.3 chemit 20090409 + * 20090329 [chemit] - add java help mojo + * 20090313 [chemit] - use i18n 0.10 + +1.2 ??? 2009???? + * 20090223 [chemit] - move sources from jaxx-util to jaxx-swing-action module + - delete jaxx-util module + +1.1 chemit 20090220 + * 20090203 [chemit] - use i18n 0.9 (zeroConf) + * 20090203 [chemit] - use lutinproject 3.4 + * 20090122 [chemit] - refactor poms (sibling dependencies, pluginsManagment,...) + +1.0 chemit 20090111 + * 20081210 [chemit] - integrate new architecture to allow to have runtime code with NO link with compiler :) + - use lutinproject 3.3 + +0.7 chemit 20081210 + * 20081210 [chemit] use lutinutil 1.0 and lutinproject 3.2 + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file diff --git a/trunk/jaxx-compiler/LICENSE.txt b/trunk/jaxx-compiler/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/jaxx-compiler/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/jaxx-compiler/README.txt b/trunk/jaxx-compiler/README.txt new file mode 100644 index 0000000..d2e50d3 --- /dev/null +++ b/trunk/jaxx-compiler/README.txt @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install diff --git a/trunk/jaxx-compiler/changelog.txt b/trunk/jaxx-compiler/changelog.txt new file mode 100644 index 0000000..f5bf405 --- /dev/null +++ b/trunk/jaxx-compiler/changelog.txt @@ -0,0 +1,120 @@ +1.3 chemit 20090409 + * 20090327 [chemit] - refactor clientProperties (no more generation in handler but in decorator) + - add javax help mecanism + + * 20090321 [chemit] - add compilerCount in launchro to known how mush files where generated + * 20090313 [chemit] - can now use geneticType on javaBean object + - add an extra method $afterCompleteSetup method to be included if find in script at last statement of $completeSetup method + + * 20090309 [chemit] - must get the goal property from the event id to make possible inheritance + - improve override properties create method : when same type do not re-instanciate it + * 20090229 [chemit] - fix bug in ClassDescriptorLoader when searching for an arrayof primitive type + - add a profile mode + * 20090228 [chemit] - fix bug in MethodDescriptor when no returnType defined (constructor method) in getReturnType method invocation + - generate default constructors only if none defined in script + - add primitive type void in ClassDescriptorLoader + - add a contextInitialized property in JAXX generated file to control JAXXContext initialization + * 20090225 [chemit] - add a mecanism to make possible injection of client properties + +1.2 letellier 20090225 (release for isis) + +1.1 chemit 20090220 + * 20090202 [chemit] - can now generate abstract and generic classes + * 20090202 [chemit] - introduce a property validatorFQN in CompilerOptions to specify the validator implementation + * 20090124 [chemit] - introduce a flag useUIManagerForIcon to retreave icons from UIManager + * 20090123 [chemit] - cache the lineSeparator property in JAXXCompiler + - can directly give the icon relatif path (in /icons/ directory) + - add an actionIcon attribute to be surronded in the Util.createActionIcon + + * 20090122 [chemit] - refactor poms (sibling dependencies, pluginsManagment,...) + +1.0 chemit 20090111 + * 20081228 [chemit] - generify ClassDescriptor + - introduce StylesheetHelper helper class to detach Stylesheet, Rule and Selector classes from + JAXXCompiler and make possible to extract compiler engine from runtime + + * 20081227 [chemit] - add PCS on ValidatorErrorTable to be used by table validation + * 20081218 [chemit] - improve generation of methods + * 20081214 [chemit] - can now in validation, put error with args (all args must be separated by a ##) + - improve event naming : replace the $evXXX by doMEthodName__on__field (except with optimize option) + - add jaww.runtime.swing.Utils.fillComboBox to fill a combobox model from a collection + - add addSourcesToClassPath property to add sources directories in class-path + - improve classloader managment + - keep in DataSource objetCode + - fix bug when processDataBinding on a null objectCode + - always clean demoNode cached values when selected it + - add usefull databinding method in Util + + * 20081213 [chemit] - improve navigation tree demoNode rendering with some caches + - introduce a ChildBuilder to simplify building of child nodes from a collection or array + +0.7 chemit 20081210 + * 20081210 [chemit] - fix bug 1751 + * 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 demoNode + * 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 + + 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) + * 20081002 [chemit] Improve i18n integration (works now also for tabs) diff --git a/trunk/jaxx-compiler/pom.xml b/trunk/jaxx-compiler/pom.xml new file mode 100644 index 0000000..e35ee20 --- /dev/null +++ b/trunk/jaxx-compiler/pom.xml @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Compiler + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jaxx</artifactId> + <version>2.5.2</version> + </parent> + + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-compiler</artifactId> + + <dependencies> + + <!-- sibling dependencies --> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-validator</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.eugene</groupId> + <artifactId>eugene</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JAXX :: Compiler</name> + <description>JAXX Compiler api</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <build> + + <plugins> + <!-- expose new plexus components --> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-component-metadata</artifactId> + <executions> + <execution> + <goals> + <goal>generate-metadata</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <profiles> + + <!-- perform only on a release stage when using the maven-release-plugin --> + <profile> + <id>reporting</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <reporting> + + <plugins> + + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-maven-plugin</artifactId> + <version>${plexusPluginVersion}</version> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>cobertura-maven-plugin</artifactId> + <version>${coberturaPluginVersion}</version> + </plugin> + + </plugins> + </reporting> + + </profile> + </profiles> +</project> diff --git a/trunk/jaxx-compiler/src/license/THIRD-PARTY.properties b/trunk/jaxx-compiler/src/license/THIRD-PARTY.properties new file mode 100644 index 0000000..97fda2c --- /dev/null +++ b/trunk/jaxx-compiler/src/license/THIRD-PARTY.properties @@ -0,0 +1,22 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - BSD License +# - BSD style +# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 +# - Common Public License Version 1.0 +# - GNU General Public License - Version 2 with the class path exception +# - Indiana University Extreme! Lab Software License, vesion 1.1.1 +# - Lesser General Public License (LGPL) +# - Lesser General Public License (LGPL) v 3.0 +# - Lesser General Public License (LPGL) +# - Lesser General Public License (LPGL) v 2.1 +# - MIT License +# - MPL 1.1 +# - The Apache Software License, Version 2.0 +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Fri Jun 29 10:36:17 CEST 2012 +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/ClassMap.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/ClassMap.java new file mode 100644 index 0000000..3e83a83 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/ClassMap.java @@ -0,0 +1,117 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +/** + * A Map implementation which uses Classes as keys. <code>ClassMap</code> differs from typical maps + * in that it takes subclasses into account; mapping a class to a value also maps all subclasses of + * that class to the value. + * <p/> + * A <code>get</code> operation will return the value associated with the class itself, or failing + * that, with its nearest ancestor for which there exists a mapping. + * @param <T> type of the class + */ +public class ClassMap<T> extends HashMap<ClassDescriptor, T> { + + private static final long serialVersionUID = 5149779660675529037L; + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(ClassMap.class); + /** + * Keeps track of automatically-added Classes so we can distinguish them from user-added + * Classes. Unknown Classes are automatically added to the map during <code>get</code> + * calls to speed up subsequent requests, but they must be updated when the mappings + * for their superclasses are modified. + */ + private List<ClassDescriptor> autoKeys = new ArrayList<ClassDescriptor>(); + + /** + * Returns the value associated with the key <code>Class</code>. If the class itself does not have + * a mapping, its superclass will be checked, and so on until an ancestor class with a mapping is + * located. If none of the class' ancestors have a mapping, <code>null</code> is returned. + * + * @param key the class to check + * @return the mapping for the class + */ + @Override + public T get(Object key) { + T result = null; + ClassDescriptor c = (ClassDescriptor) key; + while (c != null) { + result = super.get(c); + if (result != null) { + break; + } + c = c.getSuperclass(); + } + + if (result == null && ((ClassDescriptor) key).isInterface()) { + result = get(ClassDescriptorHelper.getClassDescriptor(Object.class)); + } + + if (c != key && result != null) { // no mapping for the class itself, but found one for a superclass + put((ClassDescriptor) key, result); + autoKeys.add((ClassDescriptor) key); + } + return result; + } + + /** + * Associates a value with a class and all of its descendents. + * + * @param key the class to map + * @param value the value to map to the class + * @return the old value associated with the class + */ + @Override + public T put(ClassDescriptor key, T value) { + //if (!(key instanceof ClassDescriptor)) { + // throw new IllegalArgumentException("expected ClassDescriptor, got " + key); + //} + if (autoKeys.size() > 0) { // remove all automatic keys which descend from the class being modified + Iterator<ClassDescriptor> i = autoKeys.iterator(); + while (i.hasNext()) { + ClassDescriptor auto = i.next(); + if (key.isAssignableFrom(auto)) { + i.remove(); + remove(auto); + } + } + } + return super.put(key, value); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java new file mode 100644 index 0000000..d25d85d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObject.java @@ -0,0 +1,794 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.tags.TagManager; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.lang3.StringUtils; + +import java.awt.Container; +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; + + /** + * The type of the object without fqn if possible. + * <p/> + * This is used when casting on an overridden object and only available if + * {@link #override} is set to {@code true}. + */ + private String simpleType; + + /** + * 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 StringBuilder initializationCode = new StringBuilder(); + + /** + * 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 StringBuilder additionCode = new StringBuilder(); + + /** 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 overide) */ + private ClassDescriptor overrideType; + + /** the decorator */ + private CompiledObjectDecorator decorator; + + /** client properties */ + private Map<String, String> clientProperties; + + /** initializer of the object */ + private String initializer; + + public String getSimpleType() { + return simpleType; + } + + public class ChildRef { + + CompiledObject child; + + String constraints; + + String childJavaCode; + + private String delegateCode; + + public ChildRef(CompiledObject child, + String constraints, + String childJavaCode, + String delegateCode) { + this.child = child; + this.constraints = constraints; + this.childJavaCode = childJavaCode; + this.delegateCode = delegateCode; + } + + + public String getConstraints() { + return constraints; + } + + public String getDelegateCode() { + return delegateCode; + } + + public CompiledObject getChild() { + return child; + } + + public String getChildJavaCode() { + return childJavaCode; + } + + public void setChildJavaCode(String childJavaCode) { + this.childJavaCode = childJavaCode; + } + + public void addToAdditionCode(StringBuilder buffer, + boolean isRootObject) { + //TC-20091026 do not prefix if on root object + String prefix; + if (isRootObject) { + prefix = ""; + } else { + prefix = javaCode + delegateCode + "."; + } + if (constraints != null) { + buffer.append(prefix); + buffer.append("add("); + buffer.append(childJavaCode); + buffer.append(", "); + buffer.append(constraints); + buffer.append(");"); + } else { + buffer.append(prefix); + buffer.append("add("); + buffer.append(childJavaCode); + buffer.append(");"); + } + buffer.append(JAXXCompiler.getLineSeparator()); + } + } + + private List<ChildRef> childs; + + /** + * Creates a new <code>CompiledObject</code>. + * <p/> + * To be useful, the object should be registered with a + * <code>JAXXCompiler</code> using + * {@link JAXXCompiler#registerCompiledObject(CompiledObject)} . + * + * @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(CompiledObject)} . + * + * @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(CompiledObject)} . + * + * @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; + childs = new ArrayList<ChildRef>(); + } + + 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(boolean) + */ + public boolean isOverride() { + return override; + } + + /** + * {@code true} when overrides an object in the superclass of the class + * being compiled AND type is also override. + * + * @return {@code true} if this object is an override AND override type + */ + public boolean isOverrideType() { + return isOverride() && !getObjectClass().equals(getOverrideType()); + } + + /** + * 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; + } + + /** + * Sets the simple type of the object. + * <p/> + * Used when castin an overridden object. + * + * @param simpleType the simple type to use (or the fqn if there is a + * conflict with already imported types of the compiler). + * @since 2.4 + */ + public void setSimpleType(String simpleType) { + this.simpleType = simpleType; + } + + /** + * 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 + * @throws IllegalArgumentException if parent is not a {@link Container} + */ + public void setParent(CompiledObject parent) throws IllegalArgumentException { + if (!ClassDescriptorHelper.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" + StringUtils.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" + StringUtils.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 + if (simpleType == null) { + + // means overridden but stil on the same type + result = javaCode; + } else { + result = "((" + simpleType + ") " + javaCode + ")"; +// result = "((" + JAXXCompiler.getCanonicalName(this) + ") " + javaCode + ")"; + } + } + return result; + } + + public String getJavaCodeForProperty(String property) { + if (!isOverride() || simpleType == null) { + return javaCode; + } + String result = "((" + simpleType + ") " + javaCode + ")"; +// String result = "((" + JAXXCompiler.getCanonicalName(this) + ") " + javaCode + ")"; +// String result = "((" + JAXXCompiler.getCanonicalName(getObjectClass()) + ") " + javaCode + ")"; + + String methodName = StringUtils.capitalize(property); + try { + MethodDescriptor methodDescriptor = overrideType.getMethodDescriptor("get" + methodName); + if (methodDescriptor != null) { + if (overrideType.getMethodDescriptor("set" + methodName, 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(String) + */ + 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; + } + + public String getInitializer() { + return initializer; + } + + public void setInitializer(String initializer) { + this.initializer = initializer; + } + + /** + * 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) { + StringBuilder result = new StringBuilder(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]; + String type = compiler.getImportedType(listenerClass.getName()); + String prefix = compiler.getImportedType(JAXXUtil.class); + + //TC-20091026 use 'this' instead of root object javaCode + //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple name + return getJavaCode() + '.' + addMethod.getName() + "(" + prefix + ".getEventListener(" + type + ".class, " + + TypeManager.getJavaCode(handler.getListenerMethod().getName()) + ", this, " + + 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(JAXXCompiler) + */ + public void appendInitializationCode(String code) { + if (!code.isEmpty()) { + initializationCode.append(code); + 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) { + if (!code.isEmpty()) { + additionCode.append(code); + 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()}. + * + * @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); + } + + public boolean hasClientProperties() { + return clientProperties != null && !clientProperties.isEmpty(); + } + + public void addClientProperty(String property, String value) { + getClientProperties().put(property, value); + } + + public String getClientProperty(String key) { + if (!hasClientProperties()) { + return null; + } + return clientProperties.get(key); + } + + public Map<String, String> getClientProperties() { + if (clientProperties == null) { + clientProperties = new HashMap<String, String>(); + } + return clientProperties; + } + + /** + * Returns all properties which have been set for this object. + * + * @return a <code>Map</code> containing all properties defined for this object + * @see #addProperty(String, String) + */ + public Map<?, ?>/*<String, String>*/ getProperties() { + return properties; + } + + /** + * 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(EventHandler, JAXXCompiler) + */ + 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().contains(".")) { + // 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); + + ChildRef ref = newChildRef(child, constraints, delegateCode); + childs.add(ref); + } + } + + protected ChildRef newChildRef(CompiledObject child, String constraints, String delegateCode) { + return new ChildRef(child, + constraints, + child.getJavaCode(), + delegateCode + ); + } + + @Override + public String toString() { + return getObjectClass().getName() + "[id='" + id + "']"; + } + + public String getGenericTypes() { + if (getGenericTypesLength() == 0) { + // not using it + return ""; + } + String result = ""; + for (int i = 0, j = getGenericTypesLength(); i < j; i++) { + result += ", " + genericTypes[i]; + } + return "< " + result.substring(2) + " >"; + } + + public void setGenericTypes(String... genericTypes) { + if (genericTypes == null) { + this.genericTypes = null; + return; + } + this.genericTypes = new String[genericTypes.length]; + for (int i = 0, j = genericTypes.length; i < j; i++) { + this.genericTypes[i] = genericTypes[i].trim(); + } + } + + 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; + } + + public List<ChildRef> getChilds() { + return childs; + } + + public CompiledObjectDecorator getDecorator() { + return decorator; + } + + public void setDecorator(CompiledObjectDecorator decorator) { + this.decorator = decorator; + } + + public void finalizeCompiler(JAXXCompiler compiler) { + + List<ChildRef> refList = getChilds(); + if (refList != null && !refList.isEmpty()) { + // compute additionCode for all childs + StringBuilder buffer = new StringBuilder(); + for (ChildRef childRef : refList) { + childRef.addToAdditionCode(buffer, + equals(compiler.getRootObject())); + } + additionCode = buffer.append(additionCode); + } + } + + public int getGenericTypesLength() { + return genericTypes == null ? 0 : genericTypes.length; + } + + public String getGetterName() { + return "get" + StringUtils.capitalize(id); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObjectDecorator.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObjectDecorator.java new file mode 100644 index 0000000..61f9c12 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompiledObjectDecorator.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.java.JavaFile; + +/** + * Contract of compiled object decorator at generation time. + * <p/> + * Note : The implementation of this class must be stateless. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.2 + */ +public interface CompiledObjectDecorator { + + /** + * @return the name of the decorator (match the content of a decorator + * attribute value in a JAXX file) + */ + String getName(); + + /** + * Obtain the setup code of the given {@code object} from the + * {@code compiler} to be inject in the generated method + * {@code $completeSetup}. + * + * @param compiler the compiler to use + * @param object the compiled object to treate + * @param javaFile the file to treate + * @return the code to inject in $completeSetup method in file + */ + String createCompleteSetupMethod(JAXXCompiler compiler, + CompiledObject object, + JavaFile javaFile); + + /** + * Create the initializer code for the given compiled {@code object} and + * inject it in the {@code code}. + * + * @param compiler the compiler to use + * @param root the root compiled object of the jaxx file + * @param object the compiled object to treate + * @param code where to store code to inject + * @param lastWasMethodCall {@code true} if last instruction call was a method call + * @return {@code true} if the last instruction was a method call + */ + boolean createInitializer(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + StringBuilder code, + boolean lastWasMethodCall); + + /** + * Finalize the given compiled object before any generation in the {@code file}. + * + * @param compiler the compiler to use + * @param root the root compiled object of the jaxx file + * @param object the compiled object to treate + * @param javaFile the file to treate + * @param packageName the package name + * @param className the (simple ?) class name + * @param fullClassName the fully class name + * @throws ClassNotFoundException if a class is not found + */ + void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException; + + /** + * Obtain the creation code of the given {@code object} from the {@code compiler} to inject in generate method + * {@code $initialize} or {@code createXXX} in not inline. + * + * @param compiler the compiler to use + * @param object the compiled object to treate + * @return the code to inject in $initialize (or in the createXXX in not inline) method to create the given object + * @throws CompilerException if any pb + */ + String getCreationCode(JAXXCompiler compiler, + CompiledObject object) throws CompilerException; +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java new file mode 100644 index 0000000..ec6cf47 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompilerConfiguration.java @@ -0,0 +1,140 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.spi.Initializer; +import jaxx.runtime.JAXXContext; + +import java.io.File; +import java.util.Map; + +/** + * Configuration of a compiler task. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public interface CompilerConfiguration { + + /** @return the class loader used by compilers */ + ClassLoader getClassLoader(); + + /** @return the type of compiler to use */ + Class<? extends JAXXCompiler> getCompilerClass(); + + /** @return the type of default decorator to use if none specified */ + Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass(); + + /** @return the type of the default error UI to use for validation */ + Class<?> getDefaultErrorUI(); + + /** @return extra imports to add on all generated jaxx object */ + String[] getExtraImports(); + + /** + * @return the FQN of the help broker (can not directly a type since + * the help broker should (may?) be inside the sources. + */ + String getHelpBrokerFQN(); + + /** @return the type of context to use in each generated jaxx object */ + Class<? extends JAXXContext> getJaxxContextClass(); + + /** + * Returns whether or not optimization should be performed. + * + * @return whether or not optimizations should be performed + */ + boolean getOptimize(); + + /** + * Returns whether or not auto css should be used. + * + * @return {@code true} if a css file with same name as jaxx file should + * be included in jaxx file if found. + * @since 2.0.2 + */ + boolean isAutoImportCss(); + + /** + * Returns whether or not should recurse in css for existing JAXX Object. + * <p/> + * <b>Note:</b> This functionnality was here at the beginning of the project + * but offers nothing very usefull, will be remove probably in JAXX 3.0. + * + * @return {@code true} if a css file with same name as jaxx file should + * be included in jaxx file if found. + * @since 2.0.2 + */ + boolean isAutoRecurseInCss(); + + /** + * Returns the target directory. + * + * @return the target directory + */ + File getTargetDirectory(); + + /** @return {@code true} if a logger must add on each generated jaxx object */ + boolean isAddLogger(); + + /** @return {@code true} if we are generating help */ + boolean isGenerateHelp(); + + /** @return {@code true} if we use the i18n system */ + boolean isI18nable(); + + /** @return {@code true} to generate optimized code */ + boolean isOptimize(); + + /** @return {@code true} if a profile pass must be done */ + boolean isProfile(); + + /** @return {@code true} if states must be reset after the compilation */ + boolean isResetAfterCompile(); + + /** @return {@code true} if UIManager is used to retrieve icons */ + boolean isUseUIManagerForIcon(); + + /** @return {@code true} if compiler is verbose */ + boolean isVerbose(); + + /** + * @return {@code true} to trace the Class descriptor loading. + * @since 2.4 + */ + boolean isShowClassDescriptorLoading(); + + /** @return the encoding to use to write files */ + String getEncoding(); + + Map<String, CompiledObjectDecorator> getDecorators(); + + Map<String, JAXXCompilerFinalizer> getFinalizers(); + + Map<String, Initializer> getInitializers(); +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompilerException.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompilerException.java new file mode 100644 index 0000000..da1e789 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/CompilerException.java @@ -0,0 +1,71 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +/** Thrown by the compiler when an error occurs. */ +public class CompilerException extends RuntimeException { + + private static final long serialVersionUID = -9099889519671482440L; + + /** Creates a new <code>ParseException</code>. */ + public CompilerException() { + } + + /** + * Creates a new <code>ParseException</code> with the specified detail message. + * + * @param msg the exception's detail message + */ + public CompilerException(String msg) { + super(msg); + } + + /** + * Creates a new <code>ParseException</code> with the specified cause. + * + * @param initCause the exception's initCause + */ + public CompilerException(Throwable initCause) { + super(initCause); + } + + /** + * Creates a new <code>ParseException</code> with the specified detail message and cause. + * + * @param msg the exception's detail message + * @param initCause the exception's initCause + */ + public CompilerException(String msg, Throwable initCause) { + super(msg, initCause); + } + +// @Override +// public void printStackTrace() { +// super.printStackTrace(); +// System.err.println("CompilerException printed from:"); +// Thread.dumpStack(); +// } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/DefaultCompilerConfiguration.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/DefaultCompilerConfiguration.java new file mode 100644 index 0000000..2b836f5 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/DefaultCompilerConfiguration.java @@ -0,0 +1,315 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.spi.Initializer; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.UIManager; +import java.io.File; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.TreeMap; + +/** Options of the {@link JAXXCompiler} and {@link JAXXEngine}. */ +public class DefaultCompilerConfiguration implements CompilerConfiguration { + + /** Logger. */ + private static final Log log = + LogFactory.getLog(DefaultCompilerConfiguration.class); + + /** where to generate */ + private File targetDirectory; + + /** flag to optimize generated code */ + private boolean optimize; + + /** verbose flag */ + private boolean verbose; + + /** to do a profile pass after generation */ + private boolean profile; + + /** 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 JAXXContext} + * to be used on {@link JAXXObject}. + */ + protected Class<? extends JAXXContext> jaxxContextClass; + + /** list of fqn of class to import for all generated jaxx files */ + protected String[] extraImports; + + /** default error ui */ + private Class<?> defaultErrorUI; + + /** class loader to use in compiler */ + private ClassLoader classLoader = getClass().getClassLoader(); + + /** the compiler class to use */ + private Class<? extends JAXXCompiler> compilerClass; + + /** + * the default compiled object decorator to use if none specifed via + * decorator attribute + */ + private Class<? extends CompiledObjectDecorator> defaultDecoratorClass; + + /** a flag to use {@link UIManager} to retreave icons. */ + private boolean useUIManagerForIcon; + + /** a flag to generate javax help for any */ + private boolean generateHelp; + + /** + * Fully qualified name of help broker, can not use a class here + * since this class should be in sources (so not yet compiled) + */ + private String helpBrokerFQN; + + /** Encoding to use to write files */ + private String encoding; + + private boolean autoImportCss; + + private boolean autoRecurseInCss; + + /** decorators available in engine */ + protected Map<String, CompiledObjectDecorator> decorators; + + /** finalizers available in engine */ + protected Map<String, JAXXCompilerFinalizer> finalizers; + + /** initializes availables */ + protected Map<String, Initializer> initializers; + + /** + * To trace class descriptor loading. + * + * @since 2.4 + */ + private boolean showClassDescriptorLoading; + + @Override + public File getTargetDirectory() { + return targetDirectory; + } + + @Override + public boolean getOptimize() { + return optimize; + } + + @Override + public boolean isVerbose() { + return verbose; + } + + @Override + public boolean isShowClassDescriptorLoading() { + return showClassDescriptorLoading; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + public boolean isI18nable() { + return i18nable; + } + + @Override + public boolean isUseUIManagerForIcon() { + return useUIManagerForIcon; + } + + @Override + public boolean isAddLogger() { + return addLogger; + } + + @Override + public Class<? extends JAXXContext> getJaxxContextClass() { + return jaxxContextClass; + } + + @Override + public String[] getExtraImports() { + return extraImports; + } + + @Override + public boolean isResetAfterCompile() { + return resetAfterCompile; + } + + @Override + public boolean isOptimize() { + return optimize; + } + + @Override + public Class<?> getDefaultErrorUI() { + return defaultErrorUI; + } + + @Override + public ClassLoader getClassLoader() { + return classLoader; + } + + @Override + public Class<? extends JAXXCompiler> getCompilerClass() { + return compilerClass; + } + + @Override + public Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass() { + return defaultDecoratorClass; + } + + @Override + public boolean isProfile() { + return profile; + } + + @Override + public boolean isGenerateHelp() { + return generateHelp; + } + + @Override + public String getHelpBrokerFQN() { + return helpBrokerFQN; + } + + @Override + public String getEncoding() { + return encoding; + } + + @Override + public Map<String, CompiledObjectDecorator> getDecorators() { + if (decorators == null) { + decorators = new TreeMap<String, CompiledObjectDecorator>(); + ClassLoader classloader = + Thread.currentThread().getContextClassLoader(); + if (log.isInfoEnabled()) { + log.info("with cl " + classloader); + } + + // load decorators + ServiceLoader<CompiledObjectDecorator> services = + ServiceLoader.load(CompiledObjectDecorator.class, + classloader); + for (CompiledObjectDecorator decorator : services) { + if (log.isInfoEnabled()) { + log.info("detected " + decorator); + } + decorators.put(decorator.getName(), decorator); + } + } + return decorators; + } + + @Override + public Map<String, JAXXCompilerFinalizer> getFinalizers() { + if (finalizers == null) { + finalizers = new TreeMap<String, JAXXCompilerFinalizer>(); + + ClassLoader classloader = + Thread.currentThread().getContextClassLoader(); + if (log.isInfoEnabled()) { + log.info("with cl " + classloader); + } + + ServiceLoader<JAXXCompilerFinalizer> services = + ServiceLoader.load(JAXXCompilerFinalizer.class, + classloader); + for (JAXXCompilerFinalizer finalizer : services) { + if (log.isInfoEnabled()) { + log.info("detected " + finalizer); + } + finalizers.put(finalizer.getClass().getName(), finalizer); + } + } + return finalizers; + } + + @Override + public Map<String, Initializer> getInitializers() { + if (initializers == null) { + initializers = new TreeMap<String, Initializer>(); + ClassLoader classloader = + Thread.currentThread().getContextClassLoader(); + if (log.isInfoEnabled()) { + log.info("with cl " + classloader); + } + + ServiceLoader<Initializer> loader = + ServiceLoader.load(Initializer.class, classloader); + + for (Initializer initializer : loader) { + if (log.isInfoEnabled()) { + log.info("detected " + initializer); + } + initializers.put(initializer.getClass().getName(), initializer); + } + } + return initializers; + } + + @Override + public boolean isAutoImportCss() { + return autoImportCss; + } + + @Override + public boolean isAutoRecurseInCss() { + return autoRecurseInCss; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString( + this, ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/EventHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/EventHandler.java new file mode 100644 index 0000000..1916340 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/EventHandler.java @@ -0,0 +1,89 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; + +public class EventHandler { + + private String eventId; + + private String objectCode; + + private ClassDescriptor listenerClass; + + private MethodDescriptor addMethod; + + private MethodDescriptor listenerMethod; + + private String javaCode; + + public EventHandler(String eventId, + String objectCode, + MethodDescriptor addMethod, + ClassDescriptor listenerClass, + MethodDescriptor listenerMethod, + String javaCode) { + this.eventId = eventId; + this.objectCode = objectCode; + this.addMethod = addMethod; + this.listenerClass = listenerClass; + this.listenerMethod = listenerMethod; + this.javaCode = javaCode; + } + + public String getEventId() { + return eventId; + } + + public String getObjectCode() { + return objectCode; + } + + public MethodDescriptor getAddMethod() { + return addMethod; + } + + public ClassDescriptor getListenerClass() { + return listenerClass; + } + + public MethodDescriptor getListenerMethod() { + return listenerMethod; + } + + public String getJavaCode() { + return javaCode; + } + + @Override + public String toString() { + return "EventHandler[" + eventId + ", " + + listenerClass.getName() + ", " + + objectCode + ", " + javaCode + "]"; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/I18nHelper.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/I18nHelper.java new file mode 100644 index 0000000..273601d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/I18nHelper.java @@ -0,0 +1,97 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; + +import java.util.Arrays; +import java.util.List; + +/** + * I18n methods to add {@link I18n#_(String, Object...)} method on some attributes. + * <p/> + * Make sure to set an i18nable compiler to have his {@link CompilerConfiguration#isI18nable()} returning true. + * + * @author tchemit <chemit@codelutin.com> + */ +public class I18nHelper { + + protected static final Log log = LogFactory.getLog(I18nHelper.class); + + public static final List<String> I18N_ATTRIBUTES = Arrays.asList("text", "title", "toolTipText"); + + /** + * Test if we have an active i18n attribute (says an i18n attribute on a i18neable compiler). + * + * @param attributeName name of attribute to test + * @param compiler current used compiler (contains options) + * @return <code>true</code> if wa have an active i18n attribute, <code>false</code> otherwise. + */ + public static boolean isI18nableAttribute(String attributeName, JAXXCompiler compiler) { + return compiler.getConfiguration().isI18nable() && isI18nAttribute(attributeName); + } + + /** + * Test if we have an i18n attribute. + * + * @param attributeName name of attribute to test + * @return <code>true</code> if wa have an active i18n attribute, <code>false</code> otherwise. + */ + public static boolean isI18nAttribute(String attributeName) { + return I18N_ATTRIBUTES.contains(attributeName); + } + + /** + * Add the i18n on a attribute. + * <p/> + * Note: <b>Be ware : </b> no test is done here to ensure we are on a i18neable attribute for an i18nable compiler. + * <p/> + * Make sure with the method {@link I18nHelper#isI18nableAttribute(String, JAXXCompiler)} returns + * <code>true</code< before using this method. + * + * @param widgetId the id of the widget + * @param attributeName the name of the attribute + * @param attributeValueCode the value code of the attribute value + * @param compiler the current used compile + * @return the surrender i18n call if attribute name is matchrf the attributeValueCode otherwise + */ + public static String addI18nInvocation(String widgetId, String attributeName, String attributeValueCode, JAXXCompiler compiler) { + + if (log.isDebugEnabled()) { + log.debug(" try i18n support for [" + widgetId + ":" + attributeName + "] : " + attributeValueCode); + } + if (attributeValueCode.contains("_(") && attributeValueCode.contains(")")) { + compiler.reportWarning("\n\tjaxx supports i18n, no need to add explicit call to I18n._ for attribute '" + attributeName + "' in component '" + widgetId + "' : [" + attributeValueCode + "]"); + } else { + compiler.addImport("static " + I18n.class.getName() + "._"); + attributeValueCode = "_(" + attributeValueCode + ")"; + } + + return attributeValueCode; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/IDHelper.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/IDHelper.java new file mode 100644 index 0000000..064ecd0 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/IDHelper.java @@ -0,0 +1,120 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +/** + * A usefull class to generate Ids. + * <p/> + * Created: 27 nov. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class IDHelper { + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(IDHelper.class); + /** + * Counter by type + */ + protected final Map<String, Integer> autoGenIds = new TreeMap<String, Integer>(); + /** + * Maps of uniqued id for objects used in compiler + */ + protected final Map<Object, String> uniqueIds = new HashMap<Object, String>(); + /** + * Optimized Counter + */ + protected int optimizedAutogenId = 0; + + /** + * Flag to use optimized id + */ + protected final boolean optimize; + + public IDHelper(boolean optimize) { + this.optimize = optimize; + } + + public String nextId(String name) { + + if (optimize) { + return "$" + Integer.toString(optimizedAutogenId++, 36); + } + + Integer integer = autoGenIds.get(name); + + if (integer == null) { + integer = 0; + } + name = name.substring(name.lastIndexOf(".") + 1); + String result = "$" + name + integer; + autoGenIds.put(name, ++integer); + if (log.isTraceEnabled()) { + log.trace("new id = " + result); + } + return result; + } + + public void revertId(String name) { + if (optimize) { + optimizedAutogenId--; + } else { + name = name.substring(name.lastIndexOf(".") + 1); + Integer integer = autoGenIds.get(name); + if (integer != null) { + autoGenIds.put(name, --integer); + } + } + } + + public String getUniqueId(Object object) { + String result = uniqueIds.get(object); + if (result == null) { + result = "$u" + uniqueIds.size(); + uniqueIds.put(object, result); + } + if (log.isTraceEnabled()) { + log.trace("new uniqueid = " + result); + } + return result; + } + + public void clear() { + autoGenIds.clear(); + uniqueIds.clear(); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java new file mode 100644 index 0000000..73c1650 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompiler.java @@ -0,0 +1,2002 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.css.StylesheetHelper; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaField; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; +import jaxx.compiler.java.parser.ParseException; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.script.ScriptManager; +import jaxx.compiler.tags.DefaultObjectHandler; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.tags.TagManager; +import jaxx.runtime.ComponentDescriptor; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.runtime.css.Rule; +import jaxx.runtime.css.Stylesheet; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.java.JavaGeneratorUtil; +import org.nuiton.eugene.java.extension.ImportsManager; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.AttributesImpl; +import org.xml.sax.helpers.XMLFilterImpl; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; +import java.awt.BorderLayout; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +/** + * Compiles a given {@link #jaxxFile} into a {@link #javaFile}. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.0.0 + */ +public class JAXXCompiler { + + /** Logger */ + protected static final Log log = LogFactory.getLog(JAXXCompiler.class); + + /** + * True to throw exceptions when we encounter unresolvable classes, + * false to ignore. + * <p/> + * 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 run without error anyway). + */ + public static boolean STRICT_CHECKS; + + + 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. */ + public static final int INLINE_THRESHOLD = 300; + + /** Line separator cached value */ + protected static String lineSeparator = + System.getProperty("line.separator", "\n"); + + public static final String BORDER_LAYOUT_PREFIX = BorderLayout.class.getSimpleName() + "."; + + /** The unique object handler used in first pass */ + protected final DefaultObjectHandler firstPassClassTagHandler; + + /*------------------------------------------------------------------------*/ + /*-- compiler fields -----------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + /** flag to detect 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; + + /** Contains strings of the form "javax.swing.Timer" */ + protected Set<String> importedClasses; + + /** Keeps track of open components (components still having children added). */ + protected Stack<CompiledObject> openComponents; + + /** to generate ids */ + protected final IDHelper idHelper; + + /** Binding Util */ + protected final DataBindingHelper bindingHelper; + + /** table of symbols for this compiler */ + protected SymbolTable 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; + + /** script manager */ + protected ScriptManager scriptManager; + + /** + * Combination of all stylesheets registered using + * {@link #registerStylesheet(Stylesheet)}. + */ + protected Stylesheet stylesheet; + + /** Contains all attributes defined inline on class tags. */ + protected List<Rule> inlineStyles; + + /** + * 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; + + /** Map of event handler method names used in compiler */ + protected Map<EventHandler, String> eventHandlerMethodNames; + + /** + * ClassLoader which searches the user-specified class path in + * addition to the normal class path + */ + protected ClassLoader classLoader; + + /** + * A list of Runnables which will be run after the first compilation pass. + * <p/> + * 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; + + /** + * extra interfaces which can by passed to root object via the + * 'implements' attribute + */ + private String[] extraInterfaces; + + /** a flag to generate a abstract class */ + private boolean abstractClass; + + /** the possible generic type of the class */ + private String genericType; + + /** the possible generic type of the super class */ + private String superGenericType; + + /** Extra code to be added to the instance initializer. */ + protected StringBuilder initializer; + + /** Extra code to be added at the end of the instance initializer. */ + protected StringBuilder lateInitializer; + + /** Extra code to be added to the class body. */ + protected StringBuilder bodyCode; + + /** true if a main() method has been declared in a script */ + protected boolean mainDeclared; + + /** the file to be generated */ + protected JavaFile javaFile; + + /** Used for error reporting purposes, so we can report the right line number. */ + protected Stack<Element> tagsBeingCompiled; + + /** Used for error reporting purposes, so we can report the right source file. */ + protected Stack<File> sourceFiles; + + /** + * Maps object ID strings to the objects themselves. + * <p/> + * These are created during the second compilation pass. + */ + protected Map<String, CompiledObject> objects; + + /** + * Maps objects to their ID strings. + * <p/> + * These are created during the second compilation pass. + */ + protected Map<CompiledObject, String> ids; + + /** default decodator to use if none specified */ + protected CompiledObjectDecorator defaultDecorator; + + /** + * engine which references this compiler + * (can be null if compiler is standalone) + */ + protected final JAXXEngine engine; + + protected final CompilerConfiguration defaultConfiguration = + new DefaultCompilerConfiguration(); + + protected final JAXXCompilerFile jaxxFile; + + /** + * Flag to know if jaxx file ident css was found, otherwise add it + * when {@link CompilerConfiguration#isAutoImportCss()} is sets to {@code true} + * at the end of the second compile pass. + * + * @since 2.0.2 + */ + protected boolean identCssFound; + + /** + * A flag to know if SwingUtil msut be imported. + * + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0, it is not a good + * idea to do special treatment for a particular class, to use SwingUtil, + * do like for other class : import it! + */ + @Deprecated + protected boolean needSwingUtil; + + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + + public JAXXCompiler() { + this(null, null, null); + } + + /** + * Creates a new JAXXCompiler. + * + * @param engine engine which use the compiler (could be null if not attach to any engine) + * @param jaxxFile the file to compile + * @param defaultImports list of default imports to add to java files + */ + public JAXXCompiler(JAXXEngine engine, + JAXXCompilerFile jaxxFile, + List<String> defaultImports) { + this.engine = engine; + this.jaxxFile = jaxxFile; + + ids = new LinkedHashMap<CompiledObject, String>(); + objects = new LinkedHashMap<String, CompiledObject>(); + bodyCode = new StringBuilder(); + lateInitializer = new StringBuilder(); + initializer = new StringBuilder(); + tagsBeingCompiled = new Stack<Element>(); + initializers = new ArrayList<Runnable>(); + eventHandlerMethodNames = new HashMap<EventHandler, String>(); + eventHandlers = + new HashMap<String, Map<ClassDescriptor, List<EventHandler>>>(); + inlineStyles = new ArrayList<Rule>(); + scriptManager = new ScriptManager(this); + symbolTable = new SymbolTable(); + openComponents = new Stack<CompiledObject>(); + importedPackages = new HashSet<String>(); + importedClasses = new HashSet<String>(); + sourceFiles = new Stack<File>(); + if (jaxxFile == null) { + src = null; + baseDir = null; + outputClassName = null; + } else { + src = jaxxFile.getJaxxFile(); + baseDir = src.getParentFile(); + outputClassName = jaxxFile.getClassName(); + sourceFiles.push(src); + addImport(outputClassName.substring( + 0, outputClassName.lastIndexOf(".") + 1) + "*"); + } + + firstPassClassTagHandler = new DefaultObjectHandler( + ClassDescriptorHelper.getClassDescriptor(Object.class) + ); + bindingHelper = new DataBindingHelper(this); + + if (defaultImports != null) { + for (String defaultImport : defaultImports) { + addDefaultImport(defaultImport); + } + } + + if (engine != null) { + CompilerConfiguration configuration = engine.getConfiguration(); + // add extra imports from configuration + if (configuration.getExtraImports() != null) { + for (String extraImport : configuration.getExtraImports()) { + addImport(extraImport); + } + } + defaultDecorator = engine.getDecorator( + configuration.getDefaultDecoratorClass()); + if (defaultDecorator == null) { + throw new IllegalArgumentException( + "could not find default decorator : " + + configuration.getDefaultDecoratorClass() + ); + } + idHelper = new IDHelper(configuration.isOptimize()); + } else { + idHelper = new IDHelper(false); + } + } + + /*------------------------------------------------------------------------*/ + /*-- Initializer methods -------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public 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(DefaultObjectHandler.ID_ATTRIBUTE); + MethodDescriptor methodDescriptor; + if (!id.isEmpty()) { + symbolTable.getClassTagIds().put(id, fullClassName); + if (tag.getAttributeNode(DefaultObjectHandler.JAVA_BEAN_ATTRIBUTE) != null) { + // add java bean support for this property + String capitalizeName = StringUtils.capitalize(id); + // add method + + methodDescriptor = new MethodDescriptor( + "get" + capitalizeName, + Modifier.PUBLIC, + fullClassName, + EMPTY_STRING_ARRAY, + classLoader + ); + symbolTable.getScriptMethods().add(methodDescriptor); + if (Boolean.class.getName().equals(fullClassName)) { + methodDescriptor = new MethodDescriptor( + "is" + capitalizeName, + Modifier.PUBLIC, + fullClassName, + EMPTY_STRING_ARRAY, + classLoader + ); + symbolTable.getScriptMethods().add(methodDescriptor); + } + methodDescriptor = new MethodDescriptor( + "set" + capitalizeName, + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + new String[]{fullClassName}, + classLoader + ); + symbolTable.getScriptMethods().add(methodDescriptor); + } else { + // add simple get support + String capitalizeName = StringUtils.capitalize(id); + // add method + methodDescriptor = new MethodDescriptor( + "get" + capitalizeName, + Modifier.PUBLIC, + fullClassName, + EMPTY_STRING_ARRAY, + classLoader + ); + symbolTable.getScriptMethods().add(methodDescriptor); + } + } + String interfacesStr = + tag.getAttribute(DefaultObjectHandler.IMPLEMENTS_ATTRIBUTE); + if (!interfacesStr.isEmpty()) { + // there is some interfaces to deal with + + + try { + String[] interfaces = + JavaGeneratorUtil.splitFqnList(interfacesStr, ','); + if (log.isDebugEnabled()) { + log.debug("detect interfaces : " + + Arrays.toString(interfaces)); + } + symbolTable.setInterfaces(interfaces); + } catch (Exception e) { + // the syntax is not valid (missed one >) + throw new CompilerException( + "Syntax error of interfaces " + + interfacesStr); + } +// StringTokenizer stk = new StringTokenizer(interfacesStr, ","); +// List<String> tmp = new ArrayList<String>(); +// while (stk.hasMoreTokens()) { +// String c = stk.nextToken(); +// if (c.contains("<") && !c.contains(">")) { +// // deal with a generic interface with more than one +// // parameter +// boolean done = false; +// while (stk.hasMoreTokens()) { +// +// String next = stk.nextToken(); +// if (!next.contains(">")) { +// // still a parameter of the generic type +// continue; +// } +// // ok find the ending token +// done = true; +// break; +// } +// if (!done) { +// // the syntax is not valid (missed one >) +// throw new CompilerException( +// "Syntax error of interfaces " + +// interfacesStr); +// } +// //c = c.substring(0, c.indexOf("<")); +// } +// tmp.add(c.trim()); +// } +// String[] interfaces = tmp.toArray(new String[tmp.size()]); +// if (log.isDebugEnabled()) { +// log.debug("detect interfaces : " + +// Arrays.toString(interfaces)); +// } +// symbolTable.setInterfaces(interfaces); + } + + } + // 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 (!firstPassClassTagHandler.equals(handler) && + handler instanceof DefaultObjectHandler) { + fullClassName = + ((DefaultObjectHandler) handler).getBeanClass().getName(); + handler = firstPassClassTagHandler; + } + if (firstPassClassTagHandler.equals(handler)) { + final String finalClassName = fullClassName; + + // register an initializer which will create the + // CompiledObject after pass 1 + + registerInitializer(new Runnable() { + + @Override + 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) { + reportError("Could not find a Java class corresponding to: <" + + tag.getTagName() + ">"); + failed = true; + } else { + try { + handler.compileFirstPass(tag, this); + } catch (CompilerException e) { + reportError(e); + } + } + + Element finished = tagsBeingCompiled.pop(); + if (finished != tag) { + throw new IllegalStateException( + "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) { + reportError("Could not find a Java class corresponding to: <" + + tag.getTagName() + ">"); + failed = true; + } else { + handler.compileSecondPass(tag, this); + } + + Element finished = tagsBeingCompiled.pop(); + if (!tag.equals(finished)) { + throw new RuntimeException( + "internal error: just finished compiling " + tag + + ", but top of tagsBeingCompiled stack is " + finished); + } + } + + public void compileFirstPass() throws IOException { + InputStream in = new FileInputStream(src); + try { + document = parseDocument(in); + compileFirstPass(document.getDocumentElement()); + } catch (SAXParseException e) { + reportError(e.getLineNumber(), "Invalid XML: " + e.getMessage()); + } catch (SAXException e) { + reportError(null, "Error parsing XML document: " + e); + } finally { + in.close(); + } + } + + public 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 { + if (constraints != null) { + + // try to add the constraints class in imports + if (constraints.startsWith(BORDER_LAYOUT_PREFIX)) { + addImport(BorderLayout.class.getName()); + } + } + 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 (component == null) { + throw new NullPointerException("can not close a null component"); + } + if (!component.equals(openComponents.pop())) { + throw new IllegalArgumentException( + "can only close the topmost open object"); + } + } + + public void registerCompiledObject(CompiledObject object) { +// assert engine.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); + if (object.getDecorator() == null) { + // use default decorator + object.setDecorator(defaultDecorator); + } + } + + public CompiledObject getCompiledObject(String id) { + runInitializers(); +// assert engine.symbolTables.values().contains(symbolTable) : +// "attempting to retrieve CompiledObject before pass 1 is complete"; + return objects.get(id); + } + + public boolean inlineCreation(CompiledObject object) { + return object.getId().startsWith("$") && + object.getInitializationCode(this).length() < INLINE_THRESHOLD; + } + + public void checkOverride(CompiledObject object) throws CompilerException { + String fieldName = object.getId(); + if (fieldName.startsWith("$")) { + return; + } + ClassDescriptor ancestor = root.getObjectClass(); + if (object.getObjectClass().equals(ancestor)) { + return; + } + while (ancestor != null) { + try { + FieldDescriptor f = + ancestor.getDeclaredFieldDescriptor(fieldName); + if (!f.getType().isAssignableFrom(object.getObjectClass())) { + reportError( + "attempting to redefine superclass member '" + + fieldName + "' as incompatible type (was " + + f.getType() + ", redefined as " + + object.getObjectClass() + ")" + ); + } + object.setOverride(true); + object.setOverrideType(f.getType()); + if (!getCanonicalName(f.getType()).equals(getCanonicalName(object))) { + + // types are not the same + String simpleType = + getImportedType(getCanonicalName(object)); + if (log.isDebugEnabled()) { + log.debug("Simple type for " + object.getId() + + " : " + getCanonicalName(object) + + " against : " + + getCanonicalName(f.getType())); + } + object.setSimpleType(simpleType); + } + break; + } catch (NoSuchFieldException e) { + if (log.isDebugEnabled()) { + log.debug(">>>>> could not find declared field [" + fieldName + "] in " + ancestor.getName()); + } + ancestor = ancestor.getSuperclass(); + } + } + } + + /*------------------------------------------------------------------------*/ + /*-- DataBinding methods -------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public DataBindingHelper getBindingHelper() { + return bindingHelper; + } + + 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) { + if (getConfiguration().isOptimize()) { + result = "$ev" + eventHandlerMethodNames.size(); + } else { + //TC-20090309 must get the goal property from the event id + // to make possible inheritance + String id = handler.getEventId().substring( + 0, handler.getEventId().indexOf(".")); + + result = "do" + StringUtils.capitalize(handler.getListenerMethod().getName()) + "__on__" + id; + //TC-20091105 : check the method name is available + // using css can have multi methods with result name (see priority) + if (eventHandlerMethodNames.containsValue(result)) { + int index = 0; + String result2; + do { + result2 = result + "_" + index++; + + } while (eventHandlerMethodNames.containsValue(result2)); + result = result2; + } + } + 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;")) { + 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 (!sourceFile.equals(pop)) { + 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 --------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + +// public File getIdentCssFile() { +// String extension = FileUtil.extension(src); +// String jaxxFileName = src.getName(); +// String identCssFilename = jaxxFileName.substring( +// 0, +// jaxxFileName.length() - extension.length()) + "css"; +// File identCssFile = new File(src.getParentFile(), identCssFilename); +// return identCssFile; +// } + + public boolean isIdentCssFound() { + return identCssFound; + } + + public void registerStyleSheetFile(File styleFile) throws IOException { + if (!identCssFound && getConfiguration().isAutoImportCss()) { + + // detects if the given css file is ident to jaxx file + File identCssFile = jaxxFile.getCssFile(); + + if (identCssFile.exists()) { + + // ok found ident css file + identCssFound = true; + + reportWarning("autoImportCss mode is on, you can remove " + + "style declaration with source " + styleFile); + } + + } + String content = loadFile(styleFile); +// String content = StylesheetHelper.loadCssFile(this, styleFile); + getSourceFiles().push(styleFile); + try { + Stylesheet stylesheet = StylesheetHelper.processStylesheet(content); + registerStylesheet(stylesheet); + } finally { + + // whatever could be result, must pop this source file + getSourceFiles().pop(); + } + } + + public void applyStylesheets() { + for (Object o : new ArrayList<CompiledObject>(objects.values())) { + CompiledObject object = (CompiledObject) o; + DefaultObjectHandler tagHandler = + TagManager.getTagHandler(object.getObjectClass()); + if (log.isDebugEnabled()) { + log.debug("will apply css on object " + object.getId() + + " from handler " + tagHandler); + } + tagHandler.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) { + Rule style = StylesheetHelper.inlineAttribute( + object, + propertyName, + dataBinding + ); + inlineStyles.add(style); + } + + /*------------------------------------------------------------------------*/ + /*-- 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 srcFile = sourceFiles.peek(); + try { + srcFile = srcFile.getCanonicalFile(); + } catch (IOException e) { + // ignore ? + } + StringBuilder buffer = new StringBuilder(); + buffer.append(srcFile); + if (lineNumber != null) { + buffer.append(":"); + buffer.append(sourceFiles.size() == 1 ? + Integer.parseInt(lineNumber) + lineOffset : + lineOffset + 1 + ); + } + buffer.append(getLineSeparator()).append(warning.trim()); + if (engine != null) { + engine.addWarning(buffer.toString()); + } else { + System.err.println(buffer.toString()); + } + } + + 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 (UnsupportedAttributeException.class.equals(ex.getClass()) || + UnsupportedTagException.class.equals(ex.getClass())) { + String exceptionName = ex.getClass().getName(); + message = exceptionName.substring( + exceptionName.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 errorFile = sourceFiles.isEmpty() ? null : sourceFiles.peek(); + try { + if (errorFile != null) { + errorFile = errorFile.getCanonicalFile(); + } + } catch (IOException e) { + // ignore ? + } + StringBuilder buffer = new StringBuilder(); + buffer.append(errorFile != null ? errorFile.getPath() : + "<unknown source>"); + if (lineNumber > 0) { + buffer.append(":").append(lineNumber); + } + buffer.append(getLineSeparator()).append(": ").append(error); + if (engine != null) { + engine.addError(buffer.toString()); + } else { + System.err.println(buffer.toString()); + } + failed = true; + } + + /*------------------------------------------------------------------------*/ + /*-- Getter methods ------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public Map<String, CompiledObject> getObjects() { + return objects; + } + + public Map<String, Map<ClassDescriptor, List<EventHandler>>> getEventHandlers() { + return eventHandlers; + } + + public CompilerConfiguration getConfiguration() { + JAXXEngine engine = getEngine(); + if (engine == null) { + return defaultConfiguration; + } + return engine.getConfiguration(); + } + + public String getOutputClassName() { + return outputClassName; + } + + public File getBaseDir() { + return baseDir; + } + + public Set<String> getImportedClasses() { + return importedClasses; + } + + public Set<String> getImportedPackages() { + return importedPackages; + } + + public 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 FieldDescriptor getScriptField(String fieldName) { + for (FieldDescriptor f : symbolTable.getScriptFields()) { + if (fieldName.equals(f.getName())) { + return f; + } + } + return null; + } + + public MethodDescriptor[] getScriptMethods() { + List<MethodDescriptor> scriptMethods = symbolTable.getScriptMethods(); + return scriptMethods.toArray( + new MethodDescriptor[scriptMethods.size()]); + } + + public MethodDescriptor getScriptMethod(String methodName) { + for (MethodDescriptor m : symbolTable.getScriptMethods()) { + if (methodName.equals(m.getName())) { + return m; + } + } + return null; + } + + public boolean isFailed() { + return failed; + } + + public IDHelper getIdHelper() { + return idHelper; + } + + /** + * 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) { + CompilerConfiguration configuration = getConfiguration(); + if (configuration.getClassLoader() != null) { + classLoader = configuration.getClassLoader(); + } else { + throw new NullPointerException( + "compiler configuration requires a classLoader! :\n" + + configuration); + } + } + + return classLoader; + } + + /** + * Checks if the super class of the mirrored javaFile is aware of the + * iven {@code type}. + * <p/> + * <strong>Note:</strong> If no super-class exist, then returns + * {@code false}. + * + * @param type the type to check against super class + * @return {@code true} if super class exists and is assignable against the + * given type, {@code false} otherwise + * @throws ClassNotFoundException if could not find class descriptor for + * super-class + */ + public boolean isSuperClassAware(Class<?> type) throws ClassNotFoundException { + ClassDescriptor superClass = root.getObjectClass(); + if (superClass == null) { + + // no super class, not awre of anything + return false; + } + + boolean aware = ClassDescriptorHelper.isAssignableFrom(superClass, + type); + return aware; + } + + 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].equals(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 css = getStylesheet(); + if (css == null) { + css = new Stylesheet(); + } + + return new JAXXObjectDescriptor(descriptors, css); + } + + /*------------------------------------------------------------------------*/ + /*-- Buffer --------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public StringBuilder getInitializer() { + return initializer; + } + + public StringBuilder getLateInitializer() { + return lateInitializer; + } + + public StringBuilder getBodyCode() { + return bodyCode; + } + + + public boolean isMainDeclared() { + return mainDeclared; + } + + public void setMainDeclared(boolean mainDeclared) { + this.mainDeclared = mainDeclared; + } + + public void appendInitializerCode(String code) { + initializer.append(code); + } + + public void appendBodyCode(String code) { + bodyCode.append(code); + } + + public void appendLateInitializer(String code) { + lateInitializer.append(code); + } + + public boolean hasMethod(String methodName) { + for (JavaMethod method : getJavaFile().getMethods()) { + if (methodName.equals(method.getName())) { + return true; + } + } + return false; + } + + /*------------------------------------------------------------------------*/ + /*-- Other methods -------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ + + public void addImport(Class<?> clazz) { + addImport(clazz.getName()); + } + + public void addImport(String text) { + if (text.endsWith("*")) { + importedPackages.add(text.substring(0, text.length() - 1)); + } else { + importedClasses.add(text); + } + + if (!text.equals("*")) { + getJavaFile().addImport(text); + } + } + + protected void addDefaultImport(String text) { + if (text.endsWith("*")) { + importedPackages.add(text.substring(0, text.length() - 1)); + } else { + importedClasses.add(text); + } + } + + public void addDependencyClass(String className) { + + if (engine.containsJaxxFileClassName(className)) { + + // already registred in engine + return; + } + + // register the jaxx file into the engine + + URL jaxxURL = ClassDescriptorHelper.getURL(getClassLoader(), className, "jaxx"); + + if (jaxxURL == null) { + + // not a jaxx file, can quit now + return; + } + + if (!engine.isCompileFirstPassTask()) { + throw new IllegalStateException( + "Internal error: adding dependency class " + + className + " during second compilation pass"); + } + + //FIXME tchemit 20100518 Must unify this with ClassDescriptorHelper to use the less costless resource + if (jaxxURL.toString().startsWith("file:")) { + File jaxxFile = URLtoFile(jaxxURL); + try { + jaxxFile = jaxxFile.getCanonicalFile(); + } catch (IOException ex) { + // ignore ? (at least log it...) + log.error(ex); + } + String jaxxFileName = + className.substring(className.lastIndexOf(".") + 1) + + ".jaxx"; + + assert jaxxFile.getName().equalsIgnoreCase(jaxxFileName) : + "expecting file name to match " + + className + ", but found " + jaxxFile.getName(); + if (jaxxFile.getName().equals(jaxxFileName)) { + engine.addFileToCompile(jaxxFile, className); + } + } + } + + /** + * Loads the given file and returns its content. + * <p/> + * <b>Note:</b> If any errors encounters, then report an error in the + * compiler and returns an empty string. + * + * @param file the file to load + * @return the content of the file or empty string if something was wrong + */ + public String loadFile(File file) { + if (!file.exists()) { + reportError("Could not found file " + file); + return ""; + } + try { + FileReader in = new FileReader(file); + try { + StringWriter styleBuffer = new StringWriter(); + char[] readBuffer = new char[2048]; + int c; + while ((c = in.read(readBuffer)) > 0) { + styleBuffer.write(readBuffer, 0, c); + } + return styleBuffer.toString(); + } finally { + in.close(); + } + } catch (IOException e) { + reportError("Could not read file " + file + " for reason " + + e.getMessage()); + return ""; + } + } + + /** + * Verifies that a snippet of Java code parses correctly. + * <p/> + * 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; + } + + public String getAutoId(String name) { + return idHelper.nextId(name); + } + + public String getUniqueId(Object object) { + return idHelper.getUniqueId(object); + } + + public void setExtraInterfaces(String[] extraInterfaces) { + this.extraInterfaces = extraInterfaces; + } + + public String[] getExtraInterfaces() { + return extraInterfaces; + } + + public boolean isAbstractClass() { + return abstractClass; + } + + public void setAbstractClass(boolean abstractClass) { + this.abstractClass = abstractClass; + } + + public String getGenericType() { + return genericType; + } + + public void setGenericType(String genericType) { + this.genericType = genericType; + } + + public String getSuperGenericType() { + return superGenericType; + } + + public void setSuperGenericType(String superGenericType) { + this.superGenericType = superGenericType; + } + + public void addSimpleField(JavaField javaField) { + getJavaFile().addSimpleField(javaField); + } + + public JavaFile getJavaFile() { + if (javaFile == null) { + String outputClassName = getOutputClassName(); + if (outputClassName == null) { + javaFile = JavaElementFactory.newFile(0, ""); + } else { + int dotPos = outputClassName.lastIndexOf("."); + String packageName = dotPos != -1 ? + outputClassName.substring(0, dotPos) : null; + String simpleClassName = outputClassName.substring(dotPos + 1); + + javaFile = JavaElementFactory.newFile( + Modifier.PUBLIC, + packageName + "." + simpleClassName); + } + } + return javaFile; + } + + public void preFinalizeCompiler() throws Exception { + + } + + public void finalizeCompiler() throws Exception { + + int dotPos = getOutputClassName().lastIndexOf("."); + String packageName = dotPos != -1 ? + getOutputClassName().substring(0, dotPos) : null; + String simpleClassName = getOutputClassName().substring(dotPos + 1); + CompiledObject compiledObject = getRootObject(); + + String genericType = getGenericType(); + if (StringUtils.isNotEmpty(genericType)) { + + // add the generic type to the root object + + // generictype can be on form E extends XXX + //keep only the first thing... + StringBuilder sb = new StringBuilder(); + String[] allTypes = JavaGeneratorUtil.splitFqnList(genericType, ','); + for (String type : allTypes) { + int anExtends = type.indexOf("extends"); + if (anExtends > -1) { + type = type.substring(0, anExtends - 1).trim(); + } + sb.append(", ").append(type); + } + String finalType; + if (allTypes.length > 0) { + finalType = sb.substring(2); + } else { + finalType = sb.toString(); + } + compiledObject.setGenericTypes(finalType); + } + // finalize all objects via their decorator + + for (CompiledObject object : getObjects().values()) { + CompiledObjectDecorator decorator = object.getDecorator(); + decorator.finalizeCompiler(this, + root, + object, + javaFile, + packageName, + simpleClassName, + getOutputClassName()); + } + + // obtain list of finalizers to apply + + List<JAXXCompilerFinalizer> realFinalizers = + new ArrayList<JAXXCompilerFinalizer>(); + for (JAXXCompilerFinalizer finalizer : + getConfiguration().getFinalizers().values()) { + if (finalizer.accept(this)) { + realFinalizers.add(finalizer); + } + } + + // call the finalizers finalizeCompiler method + + for (JAXXCompilerFinalizer finalizer : realFinalizers) { + // check if finalizer can be apply of this compiler + if (finalizer.accept(this)) { + finalizer.finalizeCompiler(compiledObject, + this, + javaFile, + packageName, + simpleClassName + ); + } + } + + // call the compiled objects finalizeCompiler method + + for (CompiledObject object : getObjects().values()) { + object.finalizeCompiler(this); + } + + // compile bindings + + getBindingHelper().finalizeBindings(); + + // call the finalizers prepareJavaFile method + + for (JAXXCompilerFinalizer finalizer : realFinalizers) { + finalizer.prepareJavaFile(compiledObject, + this, + javaFile, + packageName, + simpleClassName + ); + } + } + + public void generate(JavaFileGenerator generator) throws IOException { + File dest; + String fqn = getOutputClassName(); + if (getConfiguration().getTargetDirectory() != null) { + dest = new File(getConfiguration().getTargetDirectory(), + fqn.replace('.', File.separatorChar) + ".java" + ); + } else { + dest = new File(getBaseDir(), + fqn.substring(fqn.lastIndexOf(".") + 1) + ".java" + ); + } + + // make sure directory exists + File parentFile = dest.getParentFile(); + if (parentFile == null) { + throw new IOException("No parent file for " + dest); + } + if (!parentFile.exists() && !parentFile.mkdirs()) { + throw new IOException("Could not create directory " + parentFile); + } + if (dest.exists() && !dest.setLastModified(System.currentTimeMillis())) { + log.warn("could not touch file " + dest); + } + PrintWriter out = new PrintWriter(new FileWriter(dest)); + try { + generator.generateFile(javaFile, out); + } finally { + out.close(); + } + } + + /** + * Returns the system line separator string. + * + * @return the string used to separate lines + */ + public static String getLineSeparator() { + return lineSeparator; + } + + // 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.getGenericTypesLength() > 0) { + canonicalName += compiled.getGenericTypes(); + } + return canonicalName + "[]"; + } + return null; + } + + String canonicalName = clazz.getName().replace('$', '.'); + if (compiled.getGenericTypesLength() > 0) { + canonicalName += compiled.getGenericTypes(); + } + return canonicalName; + } + + /** + * 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) { + StringBuilder out = new StringBuilder(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() { + + @Override + public void warning( + TransformerException ex) throws TransformerException { + throw ex; + } + + @Override + public void error( + TransformerException ex) throws TransformerException { + throw ex; + } + + @Override + public void fatalError( + TransformerException ex) throws TransformerException { + throw ex; + } + }); + + DOMResult result = new DOMResult(); + transformer.transform( + new SAXSource(new XMLFilterImpl(getSAXParser().getXMLReader()) { + + Locator locator; + + @Override + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + @Override + public void startElement(String uri, + String localName, + String qName, + Attributes atts) throws SAXException { + AttributesImpl resultAtts = new AttributesImpl(atts); + resultAtts.addAttribute( + JAXX_INTERNAL_NAMESPACE, + "line", + "internal:line", + "CDATA", + String.valueOf(locator.getLineNumber()) + ); + getContentHandler().startElement(uri, + localName, + qName, + resultAtts + ); + } + }, new InputSource(in)), result); + return (Document) result.getNode(); + } catch (TransformerConfigurationException e) { + throw new RuntimeException(e); + } catch (TransformerException e) { + Throwable ex = e; + while (ex.getCause() != null) { + ex = ex.getCause(); + } + if (ex instanceof IOException) { + throw (IOException) ex; + } + if (ex instanceof SAXException) { + throw (SAXException) ex; + } + if (ex instanceof RuntimeException) { + throw (RuntimeException) ex; + } + throw new RuntimeException(ex); + } + } + + public JAXXEngine getEngine() { + return engine; + } + + public void clear() { + idHelper.clear(); + bindingHelper.clear(); + objects.clear(); + ids.clear(); + if (symbolTable != null) { + symbolTable.clear(); + } + } + + public void setIdentCssFound(boolean identCssFound) { + this.identCssFound = identCssFound; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * Try to import the given type into the underlying java file of this compiler. + * <p/> + * If import can not be done, will then returns the fully qualified name of + * the type. + * + * @param type the type to simplify + * @return the simplify type or the fqn if type could not be imported for the underlying java file. + * @since 2.4.1 + */ + public String getImportedType(Class<?> type) { + return getJavaFile().getImportedType(type); + } + + /** + * Try to import the given type into the underlying java file of this compiler. + * <p/> + * If import can not be done, will then returns the fully qualified name of + * the type. + * + * @param type the fqn of the type to simplify + * @return the simplify type or the fqn if type could not be imported for the underlying java file. + * @since 2.4.1 + */ + public String getImportedType(String type) { + return getJavaFile().getImportedType(type); + } + + /** + * @return the javafile import manager + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0 : do not want + * to expose eugene export manager in rest of api, this is purpose of + * JavaFile only + */ + @Deprecated + public ImportsManager getImportManager() { + return getJavaFile().getImportManager(); + } + + /** + * @return + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0, has no effect do not use it... + */ + @Deprecated + public boolean isNeedSwingUtil() { + return needSwingUtil; + } + + /** + * @param needSwingUtil + * @since 2.4 + * @deprecated since 2.4.1, will be removed in version 3.0, has no effect do not use it... + */ + @Deprecated + public void setNeedSwingUtil(boolean needSwingUtil) { + this.needSwingUtil = needSwingUtil; + } + + public boolean containsScriptField(String fieldName) { + FieldDescriptor[] scriptFields = getScriptFields(); + for (FieldDescriptor f : scriptFields) { + if (fieldName.equals(f.getName())) { + return true; + } + } + return false; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompilerFile.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompilerFile.java new file mode 100644 index 0000000..f34e9b3 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXCompilerFile.java @@ -0,0 +1,207 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.FileUtil; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * Represents a file to be treated by the {@link JAXXCompiler}. + * <p/> + * It contains informations about jaxx file, ident css, class name,... + * <p/> + * <b>Note:</b> This class will be more used in next version (will have the + * compiler it-self, symbols table,...). + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class JAXXCompilerFile { + + /** Logger */ + private static final Log log = LogFactory.getLog(JAXXCompilerFile.class); + + /** root directory of the source roots. */ + protected final File basedir; + + /** relative path from {@link #basedir} to {@link #jaxxFile}. */ + private final String relativePath; + + /** location of the jaxx file */ + protected File jaxxFile; + + /** location of the ident css file */ + protected File cssFile; + + /** full qualified name of the jaxx file class */ + protected String className; + + /** compiler associated to the file */ + protected JAXXCompiler compiler; + + public JAXXCompilerFile(File basedir, File jaxxFile) { + this.basedir = basedir; + this.jaxxFile = jaxxFile; + String absolutePath = jaxxFile.getAbsolutePath(); + String baseAbsolutePath = basedir.getAbsolutePath(); + if (!absolutePath.startsWith(baseAbsolutePath)) { + throw new IllegalStateException( + "Jaxx file " + jaxxFile + " is not in basedir " + basedir); + } + + relativePath = absolutePath.substring(baseAbsolutePath.length() + 1); + if (log.isDebugEnabled()) { + log.debug("relativePath = " + relativePath); + } + } + + public JAXXCompilerFile(File jaxxFile, String className) { + + this.jaxxFile = jaxxFile; + this.className = className; + + String extension = FileUtil.extension(jaxxFile); + String[] paths = className.split("\\."); + File basedir = jaxxFile; + for (int i = paths.length - 1; i > -1; i--) { + if (basedir == null) { + throw new IllegalStateException( + "Could not find base dir for " + jaxxFile + + " according to fqn " + className + ); + } + + String path = paths[i]; + if (basedir.equals(jaxxFile)) { + // first in loop + path += "." + extension; + } + + // check path = base filename + if (!path.equals(basedir.getName())) { + throw new IllegalStateException( + "Should have found directory " + path + ", but was " + + basedir.getName() + ); + } + + basedir = basedir.getParentFile(); + } + + if (log.isDebugEnabled()) { + log.debug("basedir = " + basedir); + } + + // must guess the base directory and relative path + + String relativePath = jaxxFile.getAbsolutePath().substring( + basedir.getAbsolutePath().length() + 1 + ); + + if (log.isDebugEnabled()) { + log.debug("relative path = " + relativePath); + } + + this.basedir = basedir; + this.relativePath = relativePath; + } + + public File getBasedir() { + return basedir; + } + + public String getRelativePath() { + return relativePath; + } + + public JAXXCompiler getCompiler() { + return compiler; + } + +// public SymbolTable getSymbolTable() { +// return compiler==null?null:compiler.getSymbolTable(); +// } + + public File getJaxxFile() { + if (jaxxFile == null) { + jaxxFile = new File(basedir, relativePath); + } + return jaxxFile; + } + + public URL getJAXXFileURL() { + File file = getJaxxFile(); + URL url = null; + try { + url = file.toURI().toURL(); + return url; + } catch (MalformedURLException e) { + throw new IllegalStateException("Url of the jaxx file is malformed... "+file); + } + } + public File getCssFile() { + if (cssFile == null) { + File file = getJaxxFile(); + String extension = FileUtil.extension(file); + String fileName = file.getName(); + int length = fileName.length() - extension.length(); + String identCssFilename = fileName.substring(0, length) + "css"; + cssFile = new File(file.getParentFile(), identCssFilename); + } + return cssFile; + } + + public String getClassName() { + if (className == null) { + + className = relativePath.substring(0, relativePath.lastIndexOf(".")); + className = className.replace(File.separatorChar, '.'); + className = className.replace('/', '.'); + className = className.replace('\\', '.'); + className = className.replace(':', '.'); + + } + return className; + } + + public void clear() { + if (compiler != null) { + compiler.clear(); + } + } + +// public void setSymbolTable(SymbolTable symbolTable) { +// this.symbolTable = symbolTable; +// } + + public void setCompiler(JAXXCompiler compiler) { + this.compiler = compiler; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java new file mode 100644 index 0000000..deaeda7 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXEngine.java @@ -0,0 +1,482 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tasks.CompileFirstPassTask; +import jaxx.compiler.tasks.CompileSecondPassTask; +import jaxx.compiler.tasks.FinalizeTask; +import jaxx.compiler.tasks.GenerateConstructorsTask; +import jaxx.compiler.tasks.GenerateTask; +import jaxx.compiler.tasks.InitTask; +import jaxx.compiler.tasks.JAXXEngineTask; +import jaxx.compiler.tasks.ProfileTask; +import jaxx.compiler.tasks.StyleSheetTask; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * The engine to compile jaxx files. + * <p/> + * The method {@link #run()} launch the compilation of files. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 was previously JAXXCompilerLaunchor + */ +public class JAXXEngine { + + /** Logger */ + private static final Log log = LogFactory.getLog(JAXXEngine.class); + + /** configuration of the launchor and underlines compilers */ + protected final CompilerConfiguration configuration; + + /** original list of files to compile (says the detected modfied files) */ + protected final JAXXCompilerFile[] incomingFiles; + + /** Files to compile */ + protected final List<JAXXCompilerFile> compilingFiles; + + /** Warnings detected while running. */ + protected final List<String> warnings; + + /** Errors detected while running. */ + protected final List<String> errors; + + /** tasks to launch */ + protected JAXXEngineTask[] tasks; + + /** current pass of the engine */ + protected JAXXEngineTask currentTask; + + /** profile attached to the engine (can be null) */ + protected JAXXProfile profiler; + + protected JAXXEngine(CompilerConfiguration configuration, + File base, + String... relativePaths) { + + if (configuration == null) { + + // use a default configuration + configuration = new DefaultCompilerConfiguration(); + } + + this.configuration = configuration; + warnings = new ArrayList<String>(); + errors = new ArrayList<String>(); + compilingFiles = new ArrayList<JAXXCompilerFile>(); + + if (configuration.isShowClassDescriptorLoading()) { + ClassDescriptorHelper.setShowLoading(true); + } + // add all default files to compile + for (String relativePath : relativePaths) { + JAXXCompilerFile compilerFile = + new JAXXCompilerFile(base, new File(base, relativePath)); + addFileToCompile(compilerFile); + } + + // fix once for all incoming files to compile + incomingFiles = compilingFiles.toArray( + new JAXXCompilerFile[compilingFiles.size()]); + } + + public JAXXEngineTask[] getTasks() { + if (tasks == null) { + List<JAXXEngineTask> tasks = new ArrayList<JAXXEngineTask>(); + + tasks.add(new InitTask()); + tasks.add(new CompileFirstPassTask()); + tasks.add(new CompileSecondPassTask()); + tasks.add(new StyleSheetTask()); + tasks.add(new FinalizeTask()); + tasks.add(new GenerateConstructorsTask()); + tasks.add(new GenerateTask()); + + if (getConfiguration().isProfile()) { + tasks.add(new ProfileTask()); + } + + this.tasks = tasks.toArray(new JAXXEngineTask[tasks.size()]); + } + return tasks; + } + + /** @return the errors of the engine */ + public List<String> getErrors() { + return errors; + } + + /** @return the warnings of the engine */ + public List<String> getWarnings() { + return warnings; + } + + public JAXXProfile getProfiler() { + if (profiler == null && getConfiguration().isProfile()) { + profiler = new JAXXProfile(); + } + return profiler; + } + + public CompilerConfiguration getConfiguration() { + return configuration; + } + + public JAXXCompilerFile[] getIncomingFiles() { + return incomingFiles; + } + +// public JAXXCompilerFile[] getCompilingFiles() { +// return compilingFiles.toArray( +// new JAXXCompilerFile[compilingFiles.size()]); +// } + + public JAXXCompilerFile[] getFilesToCompile() { + List<JAXXCompilerFile> files = new ArrayList<JAXXCompilerFile>(); + for (JAXXCompilerFile file : compilingFiles) { + if (file.getCompiler() == null) { + files.add(file); + } + } + return files.toArray(new JAXXCompilerFile[files.size()]); + } + + public JAXXCompilerFile[] getCompiledFiles() { + List<JAXXCompilerFile> files = new ArrayList<JAXXCompilerFile>(); + for (JAXXCompilerFile file : compilingFiles) { + if (file.getCompiler() != null) { + files.add(file); + } + } + // always send a copy to be safe. + return files.toArray(new JAXXCompilerFile[files.size()]); + } + + public boolean containsJaxxFileClassName(String className) { + for (JAXXCompilerFile file : compilingFiles) { + if (className.equals(file.getClassName())) { + return true; + } + } + return false; + } + + public boolean isCompileFirstPassTask() { + return currentTask != null && + CompileFirstPassTask.TASK_NAME.equals(currentTask.getName()); + } + + /** Resets all state in preparation for a new compilation session. */ + protected void reset(boolean cleanReports) { + for (JAXXCompilerFile compilerFile : compilingFiles) { + compilerFile.clear(); + } + compilingFiles.clear(); + if (profiler != null) { + profiler.clear(); + profiler = null; + } + if (cleanReports) { + clearReports(); + } + + ClassDescriptorHelper.setShowLoading(false); + } + + public void clearReports() { + getWarnings().clear(); + getErrors().clear(); + } + + public String getVersion() { + return "2.4"; + } + + /** + * Obtain the jaxx compiler of the given class name. + * + * @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 JAXXCompilerFile getJAXXCompilerFile(String className) { + for (JAXXCompilerFile compilingFile : compilingFiles) { + if (className.equals(compilingFile.getClassName())) { + return compilingFile; + } + } + return null; + } + + /** + * Obtain the jaxx compiler of the given class name. + * + * @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 JAXXCompiler getJAXXCompiler(String className) { + JAXXCompilerFile compilerFile = getJAXXCompilerFile(className); + if (compilerFile == null) { + return null; + } + return compilerFile.getCompiler(); + } + + /** + * Obtain the symbo table for the given class name. + * + * @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 SymbolTable getSymbolTable(String className) { + JAXXCompiler compiler = getJAXXCompiler(className); + if (compiler == null) { + return null; + } + return compiler.getSymbolTable(); + } + + /** + * Obtain the decorator of the given name. + * + * @param name the name of the decorator + * @return the decorator found. + * @throws IllegalArgumentException if decorator not found for the given name. + */ + public CompiledObjectDecorator getDecorator(String name) + throws IllegalArgumentException { + Map<String, CompiledObjectDecorator> decorators = + getConfiguration().getDecorators(); + CompiledObjectDecorator decorator = decorators.get(name); + if (decorator == null) { + throw new IllegalArgumentException( + "could not find decorator with key " + name + + " (known decorators : " + decorators.keySet() + ")"); + } + return decorator; + } + + /** + * Obtain the decorator of the given type. + * + * @param type the type of the decorator (syas his fqn) + * @return the decorator found + */ + public CompiledObjectDecorator getDecorator(Class<?> type) { + Map<String, CompiledObjectDecorator> decorators = + getConfiguration().getDecorators(); + for (CompiledObjectDecorator decorator : decorators.values()) { + if (decorator.getClass().equals(type)) { + return decorator; + } + } + return null; + } + + /** + * Add a warning to the engine. + * + * @param warning the warning to add + */ + public void addWarning(String warning) { + warnings.add(warning); + } + + /** + * Add an error to the engine. + * + * @param error the error to add + */ + public void addError(String error) { + errors.add(error); + } + + /** + * Compiled a set of files. + * + * @return {@code -1} if errors appears, the number of generated files + * otherwise. + */ + public int run() { + try { + boolean success = true; + + for (JAXXEngineTask task : getTasks()) { + if (!success) { + // stop as soon as a engine phase failed + break; + } + + currentTask = task; + long t0 = System.nanoTime(); + if (isVerbose()) { + log.info("Start task '" + task.getName() + "' on " + + compilingFiles.size() + " file(s)"); + } + success = task.perform(this); + if (isVerbose()) { + log.info("task '" + task.getName() + "' done in " + + StringUtil.convertTime(System.nanoTime() - t0) + ); + } + } + return success ? compilingFiles.size() : -1; + + //FIXME : deal better the exception treatment... + } catch (CompilerException e) { + log.error(e.getMessage(), e); + return -1; + } catch (Throwable e) { + log.error(e.getMessage(), e); + return -1; + } finally { + if (configuration.isResetAfterCompile()) { + reset(false); + } + } + } + + /** + * Adds a {@code file} to be compiled. + * + * @param file the {@link JAXXCompilerFile} to add. + */ + public void addFileToCompile(JAXXCompilerFile file) { + + if (isVerbose()) { + log.info("register jaxx file " + file.getJaxxFile()); + } + compilingFiles.add(file); + } + + /** + * Adds a {@link JAXXCompilerFile} given the jaxx file and the + * corresponding class fully qualified name. + * + * @param jaxxFile the jaxx file location + * @param jaxxClassName the fully qualified name of the jaxx class + */ + public void addFileToCompile(File jaxxFile, String jaxxClassName) { + + if (log.isDebugEnabled()) { + log.debug("file = " + jaxxFile + ", fqn = " + jaxxClassName); + } + + JAXXCompilerFile file = new JAXXCompilerFile(jaxxFile, jaxxClassName); + addFileToCompile(file); + } + + /** + * Create a new compiler and attach it to the given {@code jaxxFile}. + * + * @param jaxxFile the definition of jaxx file to compile + * @return the new compiler + * @throws Exception if any pb while creating of compiler + */ + public JAXXCompiler newCompiler(JAXXCompilerFile jaxxFile) throws Exception { + + Class<?> compilerClass = + getConfiguration().getCompilerClass(); + + if (compilerClass == null) { + throw new NullPointerException( + "Configuration compilerClass is null"); + } + + Constructor<?> cons = compilerClass.getConstructor( + JAXXEngine.class, + JAXXCompilerFile.class, + List.class + ); + + /* + Arrays.asList( + "java.awt.*", + "java.awt.event.*", + "java.io.*", + "java.lang.*", + "java.util.*", + "javax.swing.*", + "javax.swing.border.*", + "javax.swing.event.*", + "jaxx.runtime.*", + "jaxx.runtime.swing.*", + "static org.nuiton.i18n.I18n._", + "static jaxx.runtime.SwingUtil.createImageIcon" + ) + */ + JAXXCompiler jaxxCompiler = (JAXXCompiler) cons.newInstance( + this, + jaxxFile, + Arrays.asList( + "java.awt.*", +// "java.awt.event.*", +// "java.io.*", + "java.lang.*", +// "java.util.*", + "javax.swing.*", + "javax.swing.border.*", +// "javax.swing.event.*", +// "jaxx.runtime.*", + "jaxx.runtime.swing.*" + ) + ); + jaxxFile.setCompiler(jaxxCompiler); + return jaxxCompiler; + } + + public boolean isVerbose() { + return getConfiguration().isVerbose(); + } + + /** + * Add a profile time for the given compiler and key. + * <p/> + * Note: if {@link #profiler} is {@code null}, do nothing + * + * @param compiler the compiler to profile + * @param key the key of profiling + */ + public void addProfileTime(JAXXCompiler compiler, String key) { + JAXXProfile profiler = getProfiler(); + if (profiler != null) { + profiler.addTime(compiler, key); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXFactory.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXFactory.java new file mode 100644 index 0000000..efc1c3b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXFactory.java @@ -0,0 +1,160 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler; + +import jaxx.compiler.spi.Initializer; +import jaxx.compiler.tags.TagManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; +import java.util.ServiceLoader; + +/** + * Factory of {@link JAXXCompiler} and {@link JAXXEngine}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class JAXXFactory { + + /** Logger */ + private static final Log log = LogFactory.getLog(JAXXFactory.class); + + /** shared instance of engine. */ + protected static JAXXEngine engine; + + /** shared instance of configuration * */ + protected static CompilerConfiguration configuration; + + protected JAXXFactory() { + // no instance + } + + public static void setConfiguration(CompilerConfiguration configuration) { + JAXXFactory.configuration = configuration; + } + + /** + * Create a new empty launchor and set it as current launchor accessible + * via method {@link #getEngine()}. + * + * @return the new instanciated launchor + */ + public static JAXXEngine newDummyEngine() { + return newEngine(null); + } + + /** + * Create a new launchor and set it as current launchor accessible via + * method {@link #getEngine()}. + * <p/> + * The launchor will be prepared to run 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"). + * + * @param basedir the directory against which to resolve relative paths + * @param relativePaths a list of relative paths to .jaxx files being compiled + * @return the new instanciated launchor + */ + public static JAXXEngine newEngine(File basedir, String... relativePaths) { + checkConfiguration(); + if (engine != null) { + engine.reset(true); + } + engine = new JAXXEngine(configuration, basedir, relativePaths); + return engine; + } + + /** + * Creates a dummy Compiler for use in unit testing or dettached use of an + * engine. + * + * @param classLoader class loader to use + * @return the compiler + */ + public static JAXXCompiler newDummyCompiler(ClassLoader classLoader) { + JAXXCompiler compiler = new JAXXCompiler(); + if (classLoader != null) { + compiler.setClassLoader(classLoader); + } + return compiler; + } + + /** + * @return the current launchor + * @throws NullPointerException if no launchor was registred via a + * <code>newEngine-like</code> method. + */ + public static JAXXEngine getEngine() throws NullPointerException { + checkConfiguration(); + checkEngine(); + return engine; + } + + /** + * @return <code> if there is an engine registred, + * <code>false</code> otherwise. + */ + public static boolean isEngineRegistred() { + return engine != null; + } + + /** + * Load the {@link Initializer} services found via the{@link ServiceLoader} + * mecanism. + */ + public static void initFactory() { + + // must have a configuration + checkConfiguration(); + + TagManager.reset(); + + boolean verbose = configuration.isVerbose(); + for (Initializer initializer : + configuration.getInitializers().values()) { + if (verbose) { + log.info("load initializer " + initializer); + } + initializer.initialize(); + } + + } + + protected static void checkConfiguration() throws NullPointerException { + if (configuration == null) { + throw new NullPointerException("No configuration was registred."); + } + } + + protected static void checkEngine() throws NullPointerException { + if (engine == null) { + throw new NullPointerException("No engine was registred."); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXProfile.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXProfile.java new file mode 100644 index 0000000..686811d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/JAXXProfile.java @@ -0,0 +1,389 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.tasks.CompileFirstPassTask; +import jaxx.compiler.tasks.CompileSecondPassTask; +import jaxx.compiler.tasks.FinalizeTask; +import jaxx.compiler.tasks.GenerateTask; +import jaxx.compiler.tasks.StyleSheetTask; +import org.nuiton.util.StringUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * Pour profiler les temps d'execution pendant une compilation. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public class JAXXProfile { + + void clear() { + entries.clear(); + compilers.clear(); + } + + protected class CompilerEntry { + + JAXXCompiler compiler; + + SortedMap<String, Long> times; + + public CompilerEntry(JAXXCompiler compiler) { + this.compiler = compiler; + times = new TreeMap<String, Long>(); + } + } + + public static class ProfileResult { + + long min, max, average, total; + + Map<JAXXCompiler, Long> delta; + + List<Long> times; + + ProfileResult(Map<JAXXCompiler, Long> delta) { + this.delta = delta; + times = new ArrayList<Long>(delta.values()); + Collections.sort(times); + min = times.get(0); + max = times.get(times.size() - 1); + total = 0; + average = 0; + for (Long t : times) { + total += t; + } + average = total / times.size(); + } + + public long getTime(JAXXCompiler compiler) { + for (Entry<JAXXCompiler, Long> entry : delta.entrySet()) { + if (entry.getKey().equals(compiler)) { + return entry.getValue(); + } + } + throw new IllegalArgumentException("could not find time for compiler " + compiler); + } + + public void clear() { + times.clear(); + delta.clear(); + } + + public JAXXCompiler getCompiler(Long l) { + for (Entry<JAXXCompiler, Long> entry : delta.entrySet()) { + if (entry.getValue().equals(l)) { + return entry.getKey(); + } + } + throw new IllegalArgumentException("could not find compiler for time " + l); + } + } + + SortedMap<Integer, CompilerEntry> entries; + + List<JAXXCompiler> compilers; + + public JAXXProfile() { + compilers = new ArrayList<JAXXCompiler>(); + entries = new TreeMap<Integer, CompilerEntry>(); + } + + public void addTime(JAXXCompiler compiler, String key) { + CompilerEntry e = getEntry(compiler); + e.times.put(key, System.nanoTime()); + } + + public Map<JAXXCompiler, Long> getDelta(String keyOne, String keyTwo) { + Map<JAXXCompiler, Long> result = new HashMap<JAXXCompiler, Long>(); + for (Map.Entry<Integer, CompilerEntry> e : entries.entrySet()) { + JAXXCompiler c = getCompiler(e.getKey()); + CompilerEntry entry = e.getValue(); + Long t0 = entry.times.get(keyOne); + Long t1 = entry.times.get(keyTwo); + if (t0 == null) { + throw new NullPointerException( + "could not find time for " + keyOne + + " on compiler " + c.getOutputClassName()); + } + if (t1 == null) { + throw new NullPointerException( + "could not find time for " + keyTwo + + " on compiler " + c.getOutputClassName()); + } + long delta = t1 - t0; + result.put(c, delta); + } + return result; + } + + public ProfileResult newProfileResult(String name) { + ProfileResult result; + Map<JAXXCompiler, Long> delta = + getDelta(name + "_start", name + "_end"); + result = new ProfileResult(delta); + return result; + } + + public ProfileResult newProfileResult(ProfileResult... toCumul) { + ProfileResult result; + Map<JAXXCompiler, Long> delta = new HashMap<JAXXCompiler, Long>(); + for (JAXXCompiler c : compilers) { + long total = 0; + for (ProfileResult cumul : toCumul) { + long time = cumul.getTime(c); + total += time; + } + delta.put(c, total); + } + result = new ProfileResult(delta); + return result; + } + + public StringBuilder computeProfileReport() { + + StringBuilder buffer = new StringBuilder(); + + if (compilers.isEmpty()) { + return buffer.append("no jaxx file treated, no profile report"); + } + + // compute max size of the fqn of a compiled file + int maxLength = 0; + for (JAXXCompiler compiler : compilers) { + int l = compiler.getOutputClassName().length(); + if (l > maxLength) { + maxLength = l; + } + } + + ProfileResult cfp = newProfileResult(CompileFirstPassTask.TASK_NAME); + ProfileResult csp = newProfileResult(CompileSecondPassTask.TASK_NAME); + ProfileResult ssp = newProfileResult(StyleSheetTask.TASK_NAME); + ProfileResult fp = newProfileResult(FinalizeTask.TASK_NAME); + ProfileResult gp = newProfileResult(GenerateTask.TASK_NAME); + ProfileResult total = newProfileResult(cfp, csp, ssp, fp, gp); + + String reportPattern = "\n|%1$-" + maxLength + + "s|%2$15s|%3$15s|%4$15s|%5$15s|%6$15s|%7$15s|"; + + char[] tmpC = new char[maxLength]; + Arrays.fill(tmpC, '-'); + String line = String.format(reportPattern, + new String(tmpC), + "---------------", + "---------------", + "---------------", + "---------------", + "---------------", + "---------------"); + + buffer.append(line); + + buffer.append(String.format(reportPattern, + "(files / stats) \\ passes", + "compile round 1", + "compile round 2", + "stylesheet", + "finalize", + "generation", + "all passes") + ); + + buffer.append(line); + + // affiche les temps de tous les fichiers en temp total croissant + for (Long l : total.times) { + JAXXCompiler c = total.getCompiler(l); + printReportLine(buffer, + reportPattern, + c.getOutputClassName(), + cfp.getTime(c), + csp.getTime(c), + ssp.getTime(c), + fp.getTime(c), + gp.getTime(c), + total.getTime(c) + ); + } + + buffer.append(line); + + if (compilers.size() > 1) { + printReportLine(buffer, + reportPattern, + "total (" + compilers.size() + " files)", + cfp.total, + csp.total, + ssp.total, + fp.total, + gp.total, + total.total + ); + + buffer.append(line); + + printReportLine2(buffer, + reportPattern, + "min", + cfp.min, + csp.min, + ssp.min, + fp.min, + gp.min, + total.min + ); + printReportLine2(buffer, + reportPattern, + "max", + cfp.max, + csp.max, + ssp.max, + fp.max, + gp.max, + total.max + ); + printReportLine(buffer, + reportPattern, + "average", + cfp.average, + csp.average, + ssp.average, + fp.average, + gp.average, + total.average + ); + buffer.append(line); + } + cfp.clear(); + csp.clear(); + ssp.clear(); + gp.clear(); + total.clear(); + + return buffer; + } + + public static final String TIME_PATTERN = "%1$9s - %2$2d%%"; + + protected void printReportLine(StringBuilder buffer, + String reportPattern, + String label, + long firstPassCounter, + long secondPassCounter, + long cssCounter, + long finalizeCounter, + long generatorCounter, + long totalCounter) { + + float percentCFP = (float) firstPassCounter / totalCounter * 100; + float percentCSP = (float) secondPassCounter / totalCounter * 100; + float percentCSSP = (float) cssCounter / totalCounter * 100; + float percentFP = (float) finalizeCounter / totalCounter * 100; + float percentGP = (float) generatorCounter / totalCounter * 100; + + String strCFP = String.format(TIME_PATTERN, + StringUtil.convertTime(firstPassCounter), + (int) percentCFP + ); + String strCSP = String.format(TIME_PATTERN, + StringUtil.convertTime(secondPassCounter), + (int) percentCSP + ); + String strCSSP = String.format(TIME_PATTERN, + StringUtil.convertTime(cssCounter), + (int) percentCSSP + ); + String strFP = String.format(TIME_PATTERN, + StringUtil.convertTime(finalizeCounter), + (int) percentFP + ); + String strGP = String.format(TIME_PATTERN, + StringUtil.convertTime(generatorCounter), + (int) percentGP + ); + + buffer.append(String.format(reportPattern, + label, + strCFP, + strCSP, + strCSSP, + strFP, + strGP, + StringUtil.convertTime(totalCounter)) + ); + } + + protected void printReportLine2(StringBuilder buffer, + String reportPattern, + String label, + long firstPassCounter, + long secondPassCounter, + long cssCounter, + long finalizeCounter, + long generatorCounter, + long totalCounter) { + buffer.append(String.format(reportPattern, + label, + StringUtil.convertTime(firstPassCounter), + StringUtil.convertTime(secondPassCounter), + StringUtil.convertTime(cssCounter), + StringUtil.convertTime(finalizeCounter), + StringUtil.convertTime(generatorCounter), + StringUtil.convertTime(totalCounter)) + ); + } + + protected CompilerEntry getEntry(JAXXCompiler compiler) { + int key = compiler.getOutputClassName().hashCode(); + CompilerEntry result = entries.get(key); + if (result == null) { + result = new CompilerEntry(compiler); + entries.put(key, result); + compilers.add(compiler); + } + return result; + } + + protected JAXXCompiler getCompiler(int hasCode) { + for (JAXXCompiler c : compilers) { + if (hasCode == c.getOutputClassName().hashCode()) { + return c; + } + } + return null; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/SymbolTable.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/SymbolTable.java new file mode 100644 index 0000000..2becfc5 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/SymbolTable.java @@ -0,0 +1,92 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Symbol table constructed during the first pass of compilation. */ +public class SymbolTable { + + private String superclass; + // maps ID strings to class names -- we can't map directly to CompiledObjects, because we + // can't create those until after the first pass + + private Map<String, String> ids = new HashMap<String, String>(); + + private List<FieldDescriptor> scriptFields = new ArrayList<FieldDescriptor>(); + + private List<MethodDescriptor> scriptMethods = new ArrayList<MethodDescriptor>(); + + private String[] interfaces; + + /** @return the fully-qualified name of the superclass of the class described by this symbol table. */ + public String getSuperclassName() { + return superclass; + } + + public String[] getInterfaces() { + return interfaces; + } + + public void setSuperclassName(String superclass) { + this.superclass = superclass; + } + + /** + * @return a map of IDs to class names. Each entry in the map corresponds to a class tag with an + * <code>id</code> attribute. The <code>id</code> is the key, and the fully-qualified class name + * of the tag is the value. + */ + public Map<String, String> getClassTagIds() { + return ids; + } + + /** @return a list of <code>FieldDescriptors</code> for fields defined in <script> tags. */ + public List<FieldDescriptor> getScriptFields() { + return scriptFields; + } + + /** @return a list of <code>MethodDescriptors</code> for methods defined in <script> tags. */ + public List<MethodDescriptor> getScriptMethods() { + return scriptMethods; + } + + public void setInterfaces(String[] interfaces) { + this.interfaces = interfaces; + } + + public void clear() { + ids.clear(); + scriptFields.clear(); + scriptMethods.clear(); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedAttributeException.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedAttributeException.java new file mode 100644 index 0000000..ca011e6 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedAttributeException.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +/** + * Thrown by <code>TagHandler</code> when an unsupported attribute is encountered. + * + * @see jaxx.compiler.tags.TagHandler + */ +public class UnsupportedAttributeException extends CompilerException { + + private static final long serialVersionUID = -6919583037172920343L; + + /** Creates a new <code>UnsupportedAttributeException</code>. */ + public UnsupportedAttributeException() { + } + + /** + * Creates a new <code>UnsupportedAttributeException</code> with the specified detail message. + * + * @param msg the exception's detail message + */ + public UnsupportedAttributeException(String msg) { + super(msg); + } + + /** + * Creates a new <code>UnsupportedAttributeException</code> with the specified cause. + * + * @param initCause the exception's initCause + */ + public UnsupportedAttributeException(Throwable initCause) { + super(initCause); + } + + /** + * Creates a new <code>UnsupportedAttributeException</code> with the specified detail message and cause. + * + * @param msg the exception's detail message + * @param initCause the exception's initCause + */ + public UnsupportedAttributeException(String msg, Throwable initCause) { + super(msg, initCause); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedTagException.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedTagException.java new file mode 100644 index 0000000..f800a59 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/UnsupportedTagException.java @@ -0,0 +1,66 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler; + +/** Thrown by the compiler when an unregistered tag is encountered. */ +public class UnsupportedTagException extends CompilerException { + private static final long serialVersionUID = 3199732135804426699L; + + /** Creates a new <code>UnsupportedTagException</code>. */ + public UnsupportedTagException() { + } + + + /** + * Creates a new <code>UnsupportedTagException</code> with the specified detail message. + * + * @param msg the exception's detail message + */ + public UnsupportedTagException(String msg) { + super(msg); + } + + + /** + * Creates a new <code>UnsupportedTagException</code> with the specified cause. + * + * @param initCause the exception's initCause + */ + public UnsupportedTagException(Throwable initCause) { + super(initCause); + } + + + /** + * Creates a new <code>UnsupportedTagException</code> with the specified detail message and cause. + * + * @param msg the exception's detail message + * @param initCause the exception's initCause + */ + public UnsupportedTagException(String msg, Throwable initCause) { + super(msg, initCause); + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/BeanInfoUtil.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/BeanInfoUtil.java new file mode 100644 index 0000000..e1ebc2a --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/BeanInfoUtil.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import java.beans.Introspector; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** @author tchemit <chemit@codelutin.com> */ +public class BeanInfoUtil { + + public static String[] originalBeanInfoSearchPath; + + public static void addJaxxBeanInfoPath(String... packageNames) { + + String[] searchPath = Introspector.getBeanInfoSearchPath(); + if (originalBeanInfoSearchPath == null) { + originalBeanInfoSearchPath = searchPath; + } + List<String> listSearchPath = new ArrayList<String>(Arrays.asList(searchPath)); + for (String packageName : packageNames) { + if (!listSearchPath.contains(packageName)) { + listSearchPath.add(packageName); + } + } + + Introspector.setBeanInfoSearchPath(listSearchPath.toArray(new String[listSearchPath.size()])); + } + + public static void reset() { + if (originalBeanInfoSearchPath != null) { + Introspector.setBeanInfoSearchPath(originalBeanInfoSearchPath); + originalBeanInfoSearchPath = null; + } + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanDescriptor.java new file mode 100644 index 0000000..0ba5b6b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanDescriptor.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import jaxx.compiler.reflect.ClassDescriptor; + +/** + * Mirrors the class <code>java.beans.BeanDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXBeanDescriptor extends JAXXFeatureDescriptor { + + public JAXXBeanDescriptor(ClassDescriptor beanClass) { + super(beanClass, beanClass.getName()); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanInfo.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanInfo.java new file mode 100644 index 0000000..c968673 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXBeanInfo.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import jaxx.compiler.reflect.ClassDescriptor; + +/** + * Mirrors the class <code>java.beans.BeanInfo</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXBeanInfo { + + private JAXXBeanDescriptor beanDescriptor; + private JAXXPropertyDescriptor[] propertyDescriptors; + private JAXXEventSetDescriptor[] eventSetDescriptors; + + public JAXXBeanInfo(JAXXBeanDescriptor beanDescriptor, + JAXXPropertyDescriptor[] propertyDescriptors, + JAXXEventSetDescriptor[] eventSetDescriptors) { + this.beanDescriptor = beanDescriptor; + this.propertyDescriptors = propertyDescriptors; + this.eventSetDescriptors = eventSetDescriptors; + } + + public JAXXBeanDescriptor getJAXXBeanDescriptor() { + return beanDescriptor; + } + + public JAXXPropertyDescriptor[] getJAXXPropertyDescriptors() { + return propertyDescriptors; + } + + public JAXXEventSetDescriptor[] getJAXXEventSetDescriptors() { + return eventSetDescriptors; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXEventSetDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXEventSetDescriptor.java new file mode 100644 index 0000000..9e08239 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXEventSetDescriptor.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; + +/** + * Mirrors the class <code>java.beans.EventSetDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXEventSetDescriptor extends JAXXFeatureDescriptor { + + private MethodDescriptor addListenerMethod; + private MethodDescriptor removeListenerMethod; + private MethodDescriptor[] listenerMethods; + + public JAXXEventSetDescriptor(ClassDescriptor classDescriptor, String name, MethodDescriptor addListenerMethod, + MethodDescriptor removeListenerMethod, MethodDescriptor[] listenerMethods) { + super(classDescriptor, name); + this.addListenerMethod = addListenerMethod; + this.removeListenerMethod = removeListenerMethod; + this.listenerMethods = listenerMethods; + } + + public MethodDescriptor getAddListenerMethod() { + return addListenerMethod; + } + + public MethodDescriptor getRemoveListenerMethod() { + return removeListenerMethod; + } + + public MethodDescriptor[] getListenerMethods() { + return listenerMethods; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXFeatureDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXFeatureDescriptor.java new file mode 100644 index 0000000..6c8a597 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXFeatureDescriptor.java @@ -0,0 +1,77 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import jaxx.compiler.reflect.ClassDescriptor; + +import java.util.HashMap; +import java.util.Map; + +/** + * Mirrors the class <code>java.beans.FeatureDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXFeatureDescriptor { + + private String name; + private Map<String, Object> values; + private ClassDescriptor classDescriptor; + + JAXXFeatureDescriptor(ClassDescriptor classDescriptor, String name) { + if (name == null || classDescriptor == null) { + throw new NullPointerException(); + } + this.name = name; + this.classDescriptor = classDescriptor; + } + + public String getName() { + return name; + } + + public ClassDescriptor getClassDescriptor() { + return classDescriptor; + } + + public Object getValue(String key) { + return values != null ? values.get(key) : null; + } + + public void setValue(String key, Object value) { + if (values == null) { + values = new HashMap<String, Object>(); + } + values.put(key, value); + } + + public static String capitalize(String name) { + if (name.length() == 0) { + return name; + } + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXIntrospector.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXIntrospector.java new file mode 100644 index 0000000..8512c50 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXIntrospector.java @@ -0,0 +1,191 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.MethodDescriptor; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.HashMap; +import java.util.Map; + +/** + * Performs introspection on a <code>ClassDescriptor</code>. Ideally, I could just have copied Sun's Introspector + * and changed a few things, but the licensing terms are incompatible. This implementation is incomplete -- it only + * bothers to report info that JAXX actually checks. It also relaxes some of Introspector's rules a bit, but I + * don't believe it results in any meaningful incompatibilities. + * <p/> + * JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXIntrospector { + + private ClassDescriptor classDescriptor; + private Map<String, JAXXPropertyDescriptor> propertyDescriptors = new HashMap<String, JAXXPropertyDescriptor>(); + private Map<String, JAXXEventSetDescriptor> eventSetDescriptors = new HashMap<String, JAXXEventSetDescriptor>(); + + private JAXXIntrospector(ClassDescriptor classDescriptor) { + this.classDescriptor = classDescriptor; + } + + /** + * Returns the <code>JAXXBeanInfo</code> for a given class. + * + * @param classDescriptor the class to introspect + * @return the <code>JAXXBeanInfo</code> for the bean class + */ + public static JAXXBeanInfo getJAXXBeanInfo(ClassDescriptor classDescriptor) { + JAXXIntrospector introspector = new JAXXIntrospector(classDescriptor); + return introspector.createBeanInfo(); + } + + private JAXXBeanInfo createBeanInfo() { + ClassDescriptor explicitInfoClass = classDescriptor; + BeanInfo explicitBeanInfo = null; + while (explicitInfoClass != null) { + explicitBeanInfo = getExplicitBeanInfo(explicitInfoClass); + if (explicitBeanInfo != null) { + break; + } + explicitInfoClass = explicitInfoClass.getSuperclass(); + } + + if (explicitBeanInfo != null) { + PropertyDescriptor[] explicitProperties = explicitBeanInfo.getPropertyDescriptors(); + for (PropertyDescriptor explicitProperty : explicitProperties) { + Class<?> type = explicitProperty.getPropertyType(); + Method readMethod = explicitProperty.getReadMethod(); + Method writeMethod = explicitProperty.getWriteMethod(); + try { + ClassDescriptor typeDescriptor = ClassDescriptorHelper.getClassDescriptor(type.getName(), type.getClassLoader()); + JAXXPropertyDescriptor propertyDescriptor = new JAXXPropertyDescriptor(classDescriptor, explicitProperty.getName(), + readMethod != null ? classDescriptor.getMethodDescriptor(readMethod.getName()) : null, + writeMethod != null ? classDescriptor.getMethodDescriptor(writeMethod.getName(), typeDescriptor) : null); + propertyDescriptor.setBound(explicitProperty.isBound()); + Enumeration<String> attributeNames = explicitProperty.attributeNames(); + while (attributeNames.hasMoreElements()) { + String name = attributeNames.nextElement(); + propertyDescriptor.setValue(name, explicitProperty.getValue(name)); + } + propertyDescriptors.put(propertyDescriptor.getName(), propertyDescriptor); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Internal error: Could not find ClassDescriptor corresponding to Java " + type, e); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Internal error: Could not find expected MethodDescriptor in " + classDescriptor, e); + } + } + } + + // if the class broadcasts PropertyChangeEvent, assume all properties are bound (java.beans.Introspector + // does the same) + boolean propertyChangeSource; + try { + classDescriptor.getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); + propertyChangeSource = true; + } catch (NoSuchMethodException e) { + propertyChangeSource = false; + } + + MethodDescriptor[] methods = classDescriptor.getMethodDescriptors(); + for (MethodDescriptor method : methods) { + String name = method.getName(); + if (name.startsWith("get") && name.length() > 3 && Character.isUpperCase(name.charAt(3)) && method.getParameterTypes().length == 0) { + String propertyName = Introspector.decapitalize(name.substring(3)); + if (!propertyDescriptors.containsKey(propertyName)) { + propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, method, null, propertyChangeSource)); + } + } else if (name.startsWith("is") && name.length() > 2 && Character.isUpperCase(name.charAt(2)) && method.getParameterTypes().length == 0) { + String propertyName = Introspector.decapitalize(name.substring(2)); + if (!propertyDescriptors.containsKey(propertyName)) { + propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, method, null, propertyChangeSource)); + } + } else if (name.startsWith("set") && name.length() > 3 && Character.isUpperCase(name.charAt(3)) && method.getParameterTypes().length == 1) { + String propertyName = Introspector.decapitalize(name.substring(3)); + if (!propertyDescriptors.containsKey(propertyName)) { + propertyDescriptors.put(propertyName, new JAXXPropertyDescriptor(classDescriptor, propertyName, null, method, propertyChangeSource)); + } + } else if (name.startsWith("add") && name.length() > 3 && Character.isUpperCase(name.charAt(3))) { + ClassDescriptor[] parameters = method.getParameterTypes(); + if (parameters.length != 1 || !ClassDescriptorHelper.getClassDescriptor(EventListener.class).isAssignableFrom(parameters[0])) { + continue; // not an event listener method + } + try { + String eventSetName = method.getName().substring(3); + MethodDescriptor remove = classDescriptor.getMethodDescriptor("remove" + eventSetName, parameters); + eventSetDescriptors.put(eventSetName, new JAXXEventSetDescriptor(classDescriptor, eventSetName, method, remove, parameters[0].getMethodDescriptors())); + } catch (NoSuchMethodException e) { + // no matching remove method, not a valid event + } + } + } + + JAXXBeanDescriptor beanDescriptor = new JAXXBeanDescriptor(classDescriptor); + if (explicitBeanInfo != null) { + BeanDescriptor explicitBeanDescriptor = explicitBeanInfo.getBeanDescriptor(); + if (explicitBeanDescriptor != null) { + Enumeration<String> attributeNames = + explicitBeanDescriptor.attributeNames(); + while (attributeNames.hasMoreElements()) { + String name = attributeNames.nextElement(); + beanDescriptor.setValue(name, explicitBeanDescriptor.getValue(name)); + } + } + } + + return new JAXXBeanInfo(beanDescriptor, + propertyDescriptors.values().toArray(new JAXXPropertyDescriptor[propertyDescriptors.size()]), + eventSetDescriptors.values().toArray(new JAXXEventSetDescriptor[eventSetDescriptors.size()])); + } + + private static BeanInfo getExplicitBeanInfo(ClassDescriptor classDescriptor) { + try { + Class<?> beanClass = Class.forName(classDescriptor.getName(), true, classDescriptor.getClassLoader()); // see if there is a class by that name in this package + Method findExplicitBeanInfo = Introspector.class.getDeclaredMethod("findExplicitBeanInfo", new Class[]{Class.class}); + findExplicitBeanInfo.setAccessible(true); + return (BeanInfo) findExplicitBeanInfo.invoke(null, beanClass); + } catch (ClassNotFoundException e) { + return null; // happens for uncompiled classes + } catch (NoClassDefFoundError e) { + return null; // wrong case, etc. + } catch (NoSuchMethodException e) { + throw new RuntimeException("Error: could not find method 'findExplicitBeanInfo' in java.beans.Introspector. You are most likely running a version of Java against which JAXX has not been tested."); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXPropertyDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXPropertyDescriptor.java new file mode 100644 index 0000000..d7ec82d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/beans/JAXXPropertyDescriptor.java @@ -0,0 +1,112 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; + +/** + * Mirrors the class <code>java.beans.PropertyDescriptor</code>. JAXX uses its own introspector rather than the built-in + * <code>java.beans.Introspector</code> so that it can introspect {@link ClassDescriptor}, + * not just <code>java.lang.Class</code>. + */ +public class JAXXPropertyDescriptor extends JAXXFeatureDescriptor { + + private ClassDescriptor propertyType; + private MethodDescriptor readMethod; + private MethodDescriptor writeMethod; + private boolean bound; + + public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName) { + this(classDescriptor, propertyName, null, null); + } + + public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName, + MethodDescriptor readMethod, MethodDescriptor writeMethod) { + this(classDescriptor, propertyName, readMethod, writeMethod, false); + } + + public JAXXPropertyDescriptor(ClassDescriptor classDescriptor, String propertyName, + MethodDescriptor readMethod, MethodDescriptor writeMethod, + boolean bound) { + super(classDescriptor, propertyName); + this.readMethod = readMethod; + this.writeMethod = writeMethod; + this.bound = bound; + } + + public MethodDescriptor getReadMethodDescriptor() { + if (readMethod == null) { + try { + readMethod = getClassDescriptor().getMethodDescriptor("get" + capitalize(getName())); + } catch (NoSuchMethodException e) { + try { + readMethod = getClassDescriptor().getMethodDescriptor("is" + capitalize(getName())); + } catch (NoSuchMethodException e2) { + } + } + } + return readMethod; + } + + public MethodDescriptor getWriteMethodDescriptor() { + if (writeMethod == null) { + try { + String methodName = "set" + capitalize(getName()); + MethodDescriptor read = getReadMethodDescriptor(); + if (read != null) { + writeMethod = getClassDescriptor().getMethodDescriptor(methodName, read.getReturnType()); + } else { + throw new CompilerException("Internal error: requesting 'set' method for property of unknown type: '" + getName() + "' (in " + getClassDescriptor() + ")"); + } + } catch (NoSuchMethodException e) { + } + } + return writeMethod; + } + + public ClassDescriptor getPropertyType() { + if (propertyType == null) { + MethodDescriptor read = getReadMethodDescriptor(); + if (read != null) { + propertyType = read.getReturnType(); + } else { + MethodDescriptor write = getWriteMethodDescriptor(); + propertyType = write.getParameterTypes()[0]; + } + } + return propertyType; + } + + public boolean isBound() { + return bound; + } + + public void setBound(boolean bound) { + this.bound = bound; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java new file mode 100644 index 0000000..83ac1c2 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBinding.java @@ -0,0 +1,312 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.binding; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; +import jaxx.compiler.types.TypeManager; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * 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 { + + /** Logger. */ + protected static final Log log = LogFactory.getLog(DataBinding.class); + + /** Id of the data binding */ + private String id; + + /** Real Id of the data binding (can be suffix by a number for css binding to avoid collisions) */ + private String realId; + + /** Constant id build from the {@link #realId} and used instead of {@link #realId} in generated code */ + protected String constantId; + + /** source of the data binding */ + private String source; + + /** + * A Java snippet which will cause the destination property to be updated with the current value of + * the binding. + */ + private String assignment; + + /** A internal flag to */ + private boolean quickNoDependencies; + + /** Compiled data source */ + protected DataSource dataSource; + + /** code to add to processDataBinding (null if no binding) */ + protected String processDataBinding; + + /** code to register the databinding (null if no binding) */ + protected String initDataBinding; + + /** Extra method to add to the binding */ + protected final List<JavaMethod> methods = new ArrayList<JavaMethod>(); + + /** internal state passed to {@code true} when {@link #compile(JAXXCompiler)} method is invoked */ + private boolean compiled; + + /** + * Creates a new data binding. + * + * @param id the data binding destination in the form <code>id.propertyName</code> + * @param source the Java source code for the data binding expression + * @param assignment Java snippet which will cause the destination property to be updated with the current value of the binding + * @param quickNoDependencies internal flag to not treate process databinding in not a real binding + */ + public DataBinding(String id, String source, String assignment, boolean quickNoDependencies) { + this.id = id; + this.source = source; + this.assignment = assignment; + this.quickNoDependencies = quickNoDependencies; + if (log.isDebugEnabled()) { + log.debug("id=" + id + " assignement=" + assignment + " source=" + source + " quickNoDependencies=" + quickNoDependencies); + } + } + + public String getAssignment() { + return assignment; + } + + public String getSource() { + return source; + } + + public boolean isQuickNoDependencies() { + return quickNoDependencies; + } + + public String getProcessDataBinding() { + return processDataBinding; + } + + public String getInitDataBinding() { + return initDataBinding; + } + + public DataListener[] getTrackers() { + return dataSource == null ? null : dataSource.getTrackers(); + } + + public String getRealId() { + return realId; + } + + public String getConstantId() { + return constantId; + } + + public List<JavaMethod> getMethods() { + return methods; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append("id", id); + b.append("source", source.trim()); + b.append("assignement", assignment.trim()); + b.append("quickNoDependencies", quickNoDependencies); + if (compiled) { + b.append("realdId", realId); + b.append("constantId", getConstantId()); + b.append("objectCode", dataSource.getObjectCode()); + DataListener[] trackers = dataSource.getTrackers(); + if (trackers.length > 0) { + b.append("source:trackers", trackers.length); + for (DataListener d : trackers) { + b.append("source:tracker", d); + } + } + } + return b.toString(); + } + + /** + * 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 compiler compiler which includes the data binding + * @return {@code true} if the expression has dependencies, {@code false} otherwise + * @throws CompilerException if a compilation error occurs + */ + public boolean compile(JAXXCompiler compiler) throws CompilerException { + + if (compiled) { + throw new IllegalStateException(this + " has already been compiled"); + } + + DataBindingHelper bindingHelper = compiler.getBindingHelper(); + + // obtain a safe id + realId = bindingHelper.getSafeId(id.trim()); + + // compute the constant id of the binding + constantId = TypeManager.convertVariableNameToConstantName("binding_" + realId); + + dataSource = new DataSource(realId, constantId, getSource(), compiler, methods); + + // compile binding + + boolean binding = dataSource.compile(); + + if (!binding) { + + // free the generated id + + bindingHelper.revertSafeId(id.trim()); + } + + // was compiled + compiled = true; + + if (dataSource.showLog()) { + if (binding) { + log.info("detect a databinding : " + this); + } else { + log.info("reject a databinding : " + getSource()); + } + } + + // compute initDataBinding code + + initDataBinding = getInitDataBindingCode(compiler, dataSource, binding); + + // compute processDataBinding code + + processDataBinding = getProcessDataBindingCode(compiler, dataSource, binding); + + Set<String> ids = dataSource.getOverrideIds(); + + if (binding && ids != null && !ids.isEmpty()) { + + // there is some overrides, check trackers + DataListener[] listeners = dataSource.getTrackers(); + for (DataListener listener : listeners) { + String code = listener.getAddListenerCode(); + String newCode = replaceOverrides(compiler, ids, code); + if (code.equals(newCode)) { + listener.addListenerCode = newCode; + if (dataSource.showLog()) { + log.info("Replace overrides [" + code + "] --> [" + newCode + "]"); + } + } + code = listener.getRemoveListenerCode(); + newCode = replaceOverrides(compiler, ids, code); + if (code.equals(newCode)) { + listener.removeListenerCode = newCode; + if (dataSource.showLog()) { + log.info("Replace overrides [" + code + "] --> [" + newCode + "]"); + } + } + } + } + return binding; + } + + protected String getInitDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + String eol = JAXXCompiler.getLineSeparator(); + if (isBinding) { + return null; + } + if (isQuickNoDependencies()) { + // layout is specially handled early in the chain + if (!id.endsWith(".layout")) { + return getAssignment() + eol; + } + } + return null; + } + + protected String getProcessDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + if (!isBinding) { + // no binding = no process code + return null; + } + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder buffer = new StringBuilder(); + + String objectCode = dataSource.getObjectCode(); + + Set<String> overrideIds = dataSource.getOverrideIds(); + // no need to test objectCode not null if on root object + boolean needTest = objectCode != null && !objectCode.trim().isEmpty() && !compiler.getRootObject().getId().equals(objectCode + " != null"); + if (needTest) { + + objectCode = replaceOverrides(compiler, overrideIds, objectCode); + + buffer.append("if (").append(objectCode).append(") {").append(eol); + } + String assignment = getAssignment(compiler, overrideIds); + buffer.append(JavaFileGenerator.indent(assignment, needTest ? 4 : 0, false, eol)); + if (needTest) { + buffer.append(eol).append("}"); + } + return buffer.toString(); + } + + protected String getAssignment(JAXXCompiler compiler, Set<String> overrides) { + String s = getAssignment(); + + s = replaceOverrides(compiler, overrides, s); + + return s; + } + + protected String replaceOverrides(JAXXCompiler compiler, Set<String> overrides, String code) { + if (overrides != null && !overrides.isEmpty()) { + String tmp = code; + for (String override : overrides) { + CompiledObject o = compiler.getCompiledObject(override); + tmp = tmp.replaceAll(override + "\\.", o.getGetterName() + "()."); +// tmp = tmp.replaceFirst(override + ".", o.getJavaCode() + "."); + } + if (dataSource.showLog()) { + log.info("Assignment with overrides [" + code + "] to [" + tmp + "]"); + } + code = tmp; + } + return code; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBindingHelper.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBindingHelper.java new file mode 100644 index 0000000..52f0b3c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataBindingHelper.java @@ -0,0 +1,263 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Helper to be used by compiler to treate data bindings. + * <p/> + * Note : The code in this class was previously directly in JAXXCompiler, now prefer have a separate + * class to make {@link JAXXCompiler} more simple and clear. + * <p/> + * Created: 27 nov. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class DataBindingHelper { + + /** To debug binding without any log interference */ + public static boolean SHOW_LOG; + + /** left brace matcher */ + protected static final Matcher leftBraceMatcher = Pattern.compile("^(\\{)|[^\\\\](\\{)").matcher(""); + + /** right brace matcher */ + protected static final Matcher rightBraceMatcher = Pattern.compile("^(\\})|[^\\\\](\\})").matcher(""); + + /** + * Registred data binding for the compiler, then after the invocation of method {@link #finalizeBindings()} + * only the real data bindings, the simple bindings will be moved to {@link #simpleBindings}. + */ + protected final List<DataBinding> dataBindings = new ArrayList<DataBinding>(); + + /** Simpel bindings for the compiler */ + protected final List<DataBinding> simpleBindings = new ArrayList<DataBinding>(); + + /** Associated compiler */ + protected final JAXXCompiler compiler; + + /** Counter by unsafe type */ + protected final Map<String, Integer> autoUnsafeGenIds = new TreeMap<String, Integer>(); + + public DataBindingHelper(JAXXCompiler compiler) { + this.compiler = compiler; + } + + /** + * 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 + * @return a processed version of the expression + * @throws CompilerException ? + */ + public static String processDataBindings(String stringValue) throws CompilerException { + int pos = getNextLeftBrace(stringValue, 0); + if (pos != -1) { + StringBuilder expression = new StringBuilder(); + 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('"'); + } + boolean multi = expression.length() > 0; + if (multi) { + expression.append(" + "); + expression.append('('); + } + int pos2 = getNextRightBrace(stringValue, pos + 1); + if (pos2 == -1) { + throw new CompilerException("unmatched '{' in expression: " + stringValue); + } + expression.append(stringValue.substring(pos + 1, pos2)); + if (multi) { + 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('"'); + } + //TC-20091027 : developper must write extact databinding + // the fact of adding the String boxed for String type binding is not + // a good thing, since it add one more call to process in binding + // and add nothing special more ? +// return type == ClassDescriptorHelper.getClassDescriptor(String.class) ? "String.valueOf(" + expression + ")" : expression.toString(); + return expression.toString(); + } + return null; + } + + public DataBinding[] getDataBindings() { + return dataBindings.toArray(new DataBinding[dataBindings.size()]); + } + + public DataBinding[] getSimpleBindings() { + return simpleBindings.toArray(new DataBinding[simpleBindings.size()]); + } + + public void registerDataBinding(String id, String binding, String assignment) { + binding = compiler.checkJavaCode(binding); + registerDataBinding(new DataBinding(id, binding, assignment, true)); + } + + public void registerDataBinding(DataBinding binding) { + dataBindings.add(binding); + } + + public void clear() { + simpleBindings.clear(); + dataBindings.clear(); + autoUnsafeGenIds.clear(); + } + + /** + * Obtain the next safe id for the given binding id. + * <p/> + * With css, we can obtain the same binding id, so we must + * check for unicity each time we want a new binding id. + * <p/> + * If an id is already taken, we suffix by {@code _XXX} until + * found a free id. + * + * @param id the id of the binding + * @return the safe id of the binding + */ + public String getSafeId(String id) { + + Integer integer = autoUnsafeGenIds.get(id); + String result = id; + if (integer == null) { + integer = 0; + } else { + result += "_" + integer; + } + autoUnsafeGenIds.put(id, ++integer); + return result; + } + + /** + * Revert a previous computed safe id. + * <p/> + * This is needed when a binding compiled is not an data binding, we want to free + * the safe id to avoid hole in numbers. + * + * @param id the original id to revert in counter. + */ + public void revertSafeId(String id) { + Integer integer = autoUnsafeGenIds.get(id); + if (integer != null) { + integer--; + if (integer > 0) { + autoUnsafeGenIds.put(id, integer); + } else { + autoUnsafeGenIds.remove(id); + } + } + } + + /** + * Compile all binding discovered previously. + * <p/> + * If a binding is not a dataBinding, then move it from the list {@link #dataBindings} to {@link #simpleBindings}. + */ + public void finalizeBindings() { + + for (Iterator<DataBinding> itr = dataBindings.iterator(); itr.hasNext();) { + DataBinding binding = itr.next(); + boolean isBinding = binding.compile(compiler); + if (!isBinding) { + // ce n'est pas un binding, on enregistre le code d'init (si il existe) + simpleBindings.add(binding); + // on supprime le faux binding + itr.remove(); + } + } + } + + protected static int getNextLeftBrace(String string, int pos) { + leftBraceMatcher.reset(string); + return leftBraceMatcher.find(pos) ? Math.max(leftBraceMatcher.start(1), leftBraceMatcher.start(2)) : -1; + } + + protected static 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; + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataListener.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataListener.java new file mode 100644 index 0000000..e2483a4 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataListener.java @@ -0,0 +1,93 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class DataListener { + + /** + * Unique id of the data listener (should be something like objectId.propertyName + */ + protected final String symbol; + /** + * the nullity test to do before to add or remove the listener + */ + protected final String objectCode; + /** + * code of the add listener + */ + protected String addListenerCode; + /** + * code of the remove listener + */ + protected String removeListenerCode; + + public DataListener(String symbol, + String objectCode, + String addListenerCode, + String removeListenerCode) { + this.symbol = symbol; + this.objectCode = objectCode; + this.addListenerCode = addListenerCode; + this.removeListenerCode = removeListenerCode; + } + + public String getSymbol() { + return symbol; + } + + public String getObjectCode() { + return objectCode; + } + + public String getAddListenerCode() { + return addListenerCode; + } + + public String getRemoveListenerCode() { + return removeListenerCode; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append("symbol", symbol); + b.append("objectCode", objectCode); + b.append("addListenerCode", addListenerCode.trim()); + b.append("removeListenerCode", removeListenerCode.trim()); + return b.toString(); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java new file mode 100644 index 0000000..0433b01 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/DataSource.java @@ -0,0 +1,885 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.binding; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; +import jaxx.compiler.java.parser.JavaParser; +import jaxx.compiler.java.parser.JavaParserConstants; +import jaxx.compiler.java.parser.JavaParserTreeConstants; +import jaxx.compiler.java.parser.SimpleNode; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.tags.DefaultObjectHandler; +import jaxx.compiler.tags.TagManager; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.Introspector; +import java.io.StringReader; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 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 { + + /** Logger */ + protected static final Log log = LogFactory.getLog(DataSource.class); + + /** type attached to "null" constants in parsed expressions */ + private class NULL { + } + + /** id of data source */ + private final String id; + + /** Constant id */ + protected final String constantId; + + /** The Java source code for the expression. */ + private final String source; + + /** The current <code>JAXXCompiler</code>. */ + private final JAXXCompiler compiler; + + /** List of detected tracker (if none found, it is not a data binding) */ + private final List<DataListener> trackers; + + /** the delegate of property to be required */ + private String objectCode; + + protected final List<JavaMethod> methods; + + /** + * 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 constantId the DataSource constant id + * @param source the Java source code for the data source expression + * @param compiler the current <code>JAXXCompiler</code> + * @param methods where to store extra method to add to binding + */ + public DataSource(String id, + String constantId, + String source, + JAXXCompiler compiler, + List<JavaMethod> methods) { + this.id = id; + this.constantId = constantId; + this.source = source; + this.compiler = compiler; + this.methods = methods; + trackers = new ArrayList<DataListener>(); + } + + public String getObjectCode() { + return objectCode; + } + + public DataListener[] getTrackers() { + return trackers.toArray(new DataListener[trackers.size()]); + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append("source:id", id); + b.append("source:source", source); + b.append("source:objectCode", getObjectCode()); + if (!trackers.isEmpty()) { + b.append("source:trackers", trackers.size()); + for (DataListener d : trackers) { + b.append("source:tracker", d); + } + } + return b.toString(); + } + + public boolean showLog() { +// return DataBindingHelper.SHOW_LOG || log.isDebugEnabled(); + return DataBindingHelper.SHOW_LOG; + } + + /** + * 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. + * + * @return <code>true</code> if the expression has dependencies, <code>false</code> otherwise + * @throws CompilerException if a compilation error occurs + * @throws IllegalStateException if data source was already compiled + */ + protected boolean compile() throws CompilerException, IllegalStateException { + + if (showLog()) { + log.info("======= Start compile of " + source); + } + JavaParser p = new JavaParser(new StringReader(source)); + + // detect all expressions to treate + Map<SimpleNode, List<SimpleNode>> expressions = new LinkedHashMap<SimpleNode, List<SimpleNode>>(); + Map<SimpleNode, List<SimpleNode>> castsExpressions = new LinkedHashMap<SimpleNode, List<SimpleNode>>(); + List<SimpleNode> literalExpressions = new ArrayList<SimpleNode>(); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (log.isTraceEnabled()) { + log.trace("will scan node " + node.getText()); + } + JavaParserUtil.getExpressions(node, expressions, literalExpressions, castsExpressions); + } + + // remove literal expressions + + JavaParserUtil.removeLiteralExpressions(expressions, literalExpressions); + literalExpressions.clear(); + + // remove expressions with dependencies + + JavaParserUtil.removeNoneStandaloneExpressions(expressions, castsExpressions); + + // scan accepted expressions to detect dependencies and track listeners + + for (SimpleNode node : expressions.keySet()) { + if (showLog()) { + log.info("Will parse expression " + node.getText()); + } + scanNode(node); + } + + if (log.isDebugEnabled()) { + log.debug("trackers=" + trackers); + } + + boolean isBinding = !trackers.isEmpty(); + if (isBinding) { + + Set<String> result = JavaParserUtil.getRequired(expressions.keySet(), castsExpressions); + + if (result == null || result.isEmpty()) { + + // no requirements + + objectCode = ""; + } else { + + // build the fully test from requirements + + StringBuilder buffer = new StringBuilder(); + + Iterator<String> itr = result.iterator(); + + overrideIds = new HashSet<String>(); + + String realSource = getJavaCode(itr.next()); + buffer.append(realSource).append(" != null"); + while (itr.hasNext()) { + realSource = getJavaCode(itr.next()); + buffer.append(" && ").append(realSource).append(" != null"); + } + objectCode = buffer.toString().trim(); + } + } + castsExpressions.clear(); + expressions.clear(); + return isBinding; + } + + private Set<String> overrideIds; + + private String getJavaCode(String s) { + CompiledObject o = compiler.getCompiledObject(s); + if (o != null && o.isOverride()) { + + if (showLog()) { + log.info("Use an override identifier : " + o.getJavaCode()); + } + + overrideIds.add(s); + } + return s; + } + + public Set<String> getOverrideIds() { + return overrideIds; + } + + /** + * Examines a node to identify any dependencies it contains. + * + * @param node node to scan + * @throws CompilerException ? + */ + private void scanNode(SimpleNode node) throws CompilerException { + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || + node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { + return; + } + if (log.isTraceEnabled()) { + log.trace(node.getText()); + } + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + scanNode(node.getChild(i)); + } + // determine node type + ClassDescriptor type = null; + if (node.jjtGetNumChildren() == 1) { + type = node.getChild(0).getJavaType(); + } + switch (node.getId()) { + case JavaParserTreeConstants.JJTCLASSORINTERFACETYPE: + type = ClassDescriptorHelper.getClassDescriptor(Class.class); + break; + case JavaParserTreeConstants.JJTPRIMARYEXPRESSION: + type = determineExpressionType(node); + if (log.isDebugEnabled()) { + log.debug("result of determineExpressionType for " + node.getText() + " = " + type); + } + break; + case JavaParserTreeConstants.JJTLITERAL: + type = determineLiteralType(node); + break; + case JavaParserTreeConstants.JJTCASTEXPRESSION: + type = TagManager.resolveClass(node.getChild(0).getText(), compiler); + break; + } + node.setJavaType(type); + } + + /** + * 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 + * @return the class descriptor of the return type or null + */ + private ClassDescriptor determineExpressionType(SimpleNode expression) { + assert expression.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION; + SimpleNode prefix = expression.getChild(0); + if (log.isDebugEnabled()) { + log.debug("for expression " + expression.getText() + " - prefix " + prefix + " - nb childrens of prefix: " + prefix.jjtGetNumChildren() + ", nb childrens of expression : " + expression.jjtGetNumChildren()); + } + + 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 + ClassDescriptor classDescriptor = scanCompoundSymbol(prefix.getText().trim(), compiler.getRootObject().getObjectClass(), false); + if (log.isTraceEnabled()) { + log.trace("scanCompoundSymbol result for node " + prefix.getText().trim() + " = " + classDescriptor); + } + prefix.setJavaType(classDescriptor); + } + } + + 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); + if (log.isTraceEnabled()) { + log.trace("scanCompoundSymbol result for node " + lastNode + " = " + contextClass); + } + if (contextClass == null) { + return null; + } + int dotPos = lastNode.lastIndexOf("."); + String code = dotPos == -1 ? "" : lastNode.substring(0, dotPos); + for (int j = i - 2; j >= 0; j--) { + code = expression.getChild(j).getText() + code; + } + if (code.length() == 0) { + code = compiler.getRootObject().getJavaCode(); + } + String methodName = lastNode.substring(dotPos + 1).trim(); + if (log.isTraceEnabled()) { + log.trace("try to find type for method " + methodName + ", code : " + code); + } + try { + MethodDescriptor method = contextClass.getMethodDescriptor(methodName); + if (log.isDebugEnabled()) { + log.debug("Will trackMemberIfPossible from method " + method.getName() + " with objectCode = " + code); + } + trackMemberIfPossible(code, contextClass, method.getName(), true); + if (log.isTraceEnabled()) { + log.trace("method found = " + method); + } + return getMethodReturnType(contextClass, method); + } catch (NoSuchMethodException e) { + if (showLog()) { + log.info("Could not find method " + methodName + ", code : " + code + " on : " + contextClass); + if (log.isDebugEnabled()) { + for (MethodDescriptor descriptor : contextClass.getMethodDescriptors()) { + log.debug(" - " + Modifier.toString(descriptor.getModifiers()) + " " + descriptor.getName() + "(...) : " + descriptor.getReturnType()); + } + } + } + // 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) { + //TC-20091026 use the getScriptMethod from compiler + MethodDescriptor newMethod = compiler.getScriptMethod(methodName); + if (newMethod != null) { + //TC-20091202 must suffix dependency by property, otherwise can not have two bindings + // on the same parent... + String bindingId = compiler.getRootObject().getId() + "." + propertyName; + if (log.isDebugEnabled()) { + log.debug("detect a dependency [" + bindingId + "] from a script method " + newMethod.getName() + ", will try to add a listener in method is part of javaBean ..."); + } + // check this is a javaBean + CompiledObject compiledObject = compiler.getObjects().get(propertyName); + if (compiledObject != null && compiledObject.isJavaBean()) { + String objectCode = null; + if (showLog()) { + log.info("Detect a dependency from compiled object [" + objectCode + "]a script method '" + newMethod.getName() + "' which reflect a javaBean property " + propertyName); + log.info("Try to add a listener [symbol:" + bindingId + ",objectCode:" + objectCode + "]"); + log.debug(">> lastnode = " + lastNode + "(), suffix = " + suffix.getText() + ", expression = " + expression.getText()); + } + addListener(bindingId, + objectCode, + "addPropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator(), + "removePropertyChangeListener(\"" + propertyName + "\", this);" + JAXXCompiler.getLineSeparator()); + } + contextClass = newMethod.getReturnType(); + } + } + } + } + } + lastNode = suffix.getText().trim(); + if (lastNode.startsWith(".")) { + lastNode = lastNode.substring(1); + } + } + + return null; + } + + private ClassDescriptor determineLiteralType(SimpleNode node) { + assert node.getId() == JavaParserTreeConstants.JJTLITERAL; + if (node.jjtGetNumChildren() == 1) { + int childId = node.getChild(0).getId(); + if (childId == JavaParserTreeConstants.JJTBOOLEANLITERAL) { + return ClassDescriptorHelper.getClassDescriptor(boolean.class); + } + if (childId == JavaParserTreeConstants.JJTNULLLITERAL) { + return ClassDescriptorHelper.getClassDescriptor(NULL.class); + } + throw new RuntimeException("Expected BooleanLiteral or NullLiteral, found " + JavaParserTreeConstants.jjtNodeName[childId]); + } + int nodeId = node.firstToken.kind; + switch (nodeId) { + case JavaParserConstants.INTEGER_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("l")) { + return ClassDescriptorHelper.getClassDescriptor(long.class); + } + return ClassDescriptorHelper.getClassDescriptor(int.class); + case JavaParserConstants.CHARACTER_LITERAL: + return ClassDescriptorHelper.getClassDescriptor(char.class); + case JavaParserConstants.FLOATING_POINT_LITERAL: + if (node.firstToken.image.toLowerCase().endsWith("f")) { + return ClassDescriptorHelper.getClassDescriptor(float.class); + } + return ClassDescriptorHelper.getClassDescriptor(double.class); + case JavaParserConstants.STRING_LITERAL: + return ClassDescriptorHelper.getClassDescriptor(String.class); + default: + throw new RuntimeException("Expected literal token, found " + JavaParserConstants.tokenImage[nodeId]); + } + } + + /** + * 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 + * @return the type of the symbol (or null if it could not be determined). + */ + private ClassDescriptor scanCompoundSymbol(String symbol, ClassDescriptor contextClass, boolean isMethod) { + String[] tokens = symbol.split("\\s*\\.\\s*"); + if (log.isDebugEnabled()) { + log.debug("for symbol " + symbol + ", contextClass " + contextClass + ", isMethod " + isMethod); + log.debug("tokens " + Arrays.toString(tokens)); + } + StringBuilder currentSymbol = new StringBuilder(); + StringBuilder tokensSeenSoFar = new StringBuilder(); + // if this ends up false, it means we weren't able to figure out + boolean accepted; + // 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 (log.isTraceEnabled()) { + log.trace("try to find type for " + currentSymbol); + } + if (currentSymbol.indexOf(".") == -1) { + String memberName = currentSymbol.toString(); + CompiledObject object = compiler.getCompiledObject(memberName); + if (object != null) { + if (log.isTraceEnabled()) { + log.trace("detected an object " + object); + } + contextClass = object.getObjectClass(); + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + } else { + try { + FieldDescriptor field = contextClass.getFieldDescriptor(memberName); + if (log.isDebugEnabled()) { + log.debug("Will trackMemberIfPossible from field " + field.getName() + " with objectCode = " + tokensSeenSoFar.toString()); + } + trackMemberIfPossible(tokensSeenSoFar.toString(), contextClass, field.getName(), false); + try { + contextClass = field.getType(); + } catch (Exception e) { + log.warn("could not find type for field " + field); + throw new NoSuchFieldException(e.getMessage()); + } + + 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 newField = compiler.getScriptField(memberName); + if (newField != null) { + contextClass = newField.getType(); + if (showLog()) { + log.info("Detect a dependency from a script field '" + newField + "'"); + log.info("Try to add a listenenr [symbol:" + tokensSeenSoFar.toString() + ",objectCode:" + null + "]"); + } + String eol = JAXXCompiler.getLineSeparator(); + addListener(tokensSeenSoFar.toString(), + null, + "addPropertyChangeListener(\"" + memberName + "\", this);" + eol, +// "addPropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol, + "removePropertyChangeListener(\"" + memberName + "\", this);" + eol); +// "removePropertyChangeListener(\"" + memberName + "\", " + listenerId + ");" + eol); + + assert contextClass != null : "script field '" + memberName + "' is defined, but has type null"; + currentSymbol.setLength(0); + accepted = true; + recognizeClassNames = false; + } + } + } + } + } + if (currentSymbol.length() > 0 && recognizeClassNames) { + if (log.isDebugEnabled()) { + log.debug("Try to recognizeClassNames for symbol " + currentSymbol); + } + 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) { + if (log.isDebugEnabled()) { + log.debug("symbol " + symbol + " was not accepted."); + } + return null; + } + } + + return contextClass; + } + + private void trackMemberIfPossible(String objectCode, ClassDescriptor objectClass, String memberName, boolean method) { + + if (log.isDebugEnabled()) { + log.debug("for [objectCode:" + objectCode + ", objectClass:" + objectClass + ", memberName:" + memberName + ", isMethod:" + method); + } + DefaultObjectHandler handler = TagManager.getTagHandler(objectClass); + try { + if (handler.isMemberBound(memberName)) { + String bindingId = objectCode + "." + memberName + (method ? "()" : ""); + if (showLog()) { + log.info("Detect a dependency from a event handler for memberName '" + memberName + "' for class " + objectClass); + log.info("Try to add a listener [symbol:" + bindingId + ", objectCode:" + objectCode + "]"); + } + addListener(bindingId, + objectCode, + getAddMemberListenerCode(handler, objectCode, memberName, "this", compiler), + getRemoveMemberListenerCode(handler, objectCode, memberName, "this", compiler)); + } + } catch (UnsupportedAttributeException e) { + // ignore -- this is thrown for methods like toString(), for which there is no tracking and + // no setting support + } + } + + private void addListener(String dependencySymbol, + String objectCode, + String addCode, + String removeCode) { + if (objectCode != null) { + objectCode = objectCode.trim(); + } + boolean needTest = objectCode != null && + !compiler.getRootObject().getId().equals(objectCode); + if (!needTest) { + objectCode = null; + } + if (log.isDebugEnabled()) { + log.debug("try to add listener [dependencySymbol:" + + dependencySymbol + ", objectCode:" + objectCode + + ", addCode:" + addCode + "]"); + } + + for (DataListener tracker : trackers) { + if (dependencySymbol.equals(tracker.getSymbol())) { + // listener already existing + return; + } + } + DataListener tracker = new DataListener(dependencySymbol, + objectCode, + addCode, + removeCode + ); + if (log.isDebugEnabled()) { + log.debug("add tracker " + tracker); + } + trackers.add(tracker); + } + + public boolean hasMethod(String methodName) { + for (JavaMethod method : methods) { + if (methodName.equals(method.getName())) { + return true; + } + } + return false; + } + + /** + * 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 handler Object handler (containts known events + * @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 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(DefaultObjectHandler handler, + String objectCode, + String memberName, + String propertyChangeListenerCode, + JAXXCompiler compiler) { + if ("getClass".equals(memberName)) { + return null; + } + + DefaultObjectHandler.ProxyEventInfo eventInfo = handler.getEventInfo(memberName); + if (eventInfo != null) { + // a "proxied" event is one that doesn't fire PropertyChangeEvent, so we need to convert its native event type into PropertyChangeEvents + StringBuilder result = new StringBuilder(); + String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode.equals("this") ? constantId : propertyChangeListenerCode); + boolean methodExists = hasMethod(methodName); + ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); + String type = compiler.getImportedType(JAXXCompiler.getCanonicalName(eventClass)); + if (!methodExists) { + String code = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); + code += "propertyChange(null);"; + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + methodName, + code, + false, + JavaElementFactory.newArgument(type, "event")); + methods.add(method); + } + String code = objectCode + (eventInfo.getModelName() != null ? ".get" + StringUtils.capitalize(eventInfo.getModelName()) + "()" : ""); + result.append("$bindingSources.put(\"").append(code).append("\", ").append(code).append(");").append(JAXXCompiler.getLineSeparator()); + //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple listener name + ClassDescriptor listenerClass = eventInfo.getListenerClass(); + String listenerType = compiler.getImportedType(listenerClass.getName()); + String jaxxUtilPrefix = compiler.getImportedType(JAXXUtil.class); + result.append(code); + result.append('.'); + result.append(eventInfo.getAddMethod()); + result.append("( ").append(jaxxUtilPrefix).append(".getEventListener("); + result.append(listenerType); + result.append(".class, "); + result.append("this"); + result.append(", "); + result.append(TypeManager.getJavaCode(methodName)); + result.append("));"); + result.append(JAXXCompiler.getLineSeparator()); + if (eventInfo.getModelName() != null) { + String addCode = getAddMemberListenerCode( + handler, + objectCode, + "get" + StringUtils.capitalize(eventInfo.getModelName()), + jaxxUtilPrefix + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this" + ", " + constantId + ")", + compiler + ); + result.append(addCode); + } + return result.toString(); + } + String propertyName = null; + if (memberName.startsWith("get")) { + propertyName = Introspector.decapitalize(memberName.substring(3)); + } else if (memberName.startsWith("is")) { + propertyName = Introspector.decapitalize(memberName.substring(2)); + } else { + try { + handler.getBeanClass().getFieldDescriptor(memberName); + propertyName = memberName; + } catch (NoSuchFieldException e) { + // ignore ? + } + } + if (propertyName != null) { + //TC-20091026 when on root object, do not prefix with objectCode + String prefix = objectCode.trim() + "."; + if (objectCode.equals(compiler.getRootObject().getJavaCode())) { + prefix = ""; + } + //TC-20091203 : always use the property specific method, this is part of the javaBeans 1.1 norm + //TC-20091203 : if developpers do bad, shame on them... + return prefix + "addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; + +// try { +// // check for property-specific addPropertyChangeListener method +//// getBeanClass().getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), +// handler.getBeanClass().getMethodDescriptor("addPropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), +// ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); +// return prefix + "addPropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; +// } catch (NoSuchMethodException e) { +// if (log.isInfoEnabled()) { +// log.info("Could not get named addPropertyChangeListener on class " + handler.getBeanClass()); +// } +// // no property-specific method, use general one +// return prefix + "addPropertyChangeListener(" + propertyChangeListenerCode + ");\n"; +// } + } + return null; + } + + public String getRemoveMemberListenerCode(DefaultObjectHandler handler, + String objectCode, + String memberName, + String propertyChangeListenerCode, + JAXXCompiler compiler) { + if ("getClass".equals(memberName)) { + return null; + } + + DefaultObjectHandler.ProxyEventInfo eventInfo = handler.getEventInfo(memberName); + if (eventInfo != null) { + // a "proxied" event is one that doesn't fire PropertyChangeEvent, + // so we need to convert its native event type into PropertyChangeEvents + StringBuilder result = new StringBuilder(); + String methodName = "$pr" + compiler.getUniqueId(propertyChangeListenerCode.equals("this") ? constantId : propertyChangeListenerCode); + boolean methodExists = hasMethod(methodName); + if (!methodExists) { + ClassDescriptor eventClass = DefaultObjectHandler.getEventClass(eventInfo.getListenerClass()); + String type = compiler.getImportedType(JAXXCompiler.getCanonicalName(eventClass)); + String code = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); + code += "propertyChange(null);"; + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + methodName, + code, + false, + JavaElementFactory.newArgument(type, "event")); + methods.add(method); + } + try { + String modelMemberName = eventInfo.getModelName() != null ? "get" + StringUtils.capitalize(eventInfo.getModelName()) : null; + String modelClassName = modelMemberName != null ? handler.getBeanClass().getMethodDescriptor(modelMemberName).getReturnType().getName() : JAXXCompiler.getCanonicalName(handler.getBeanClass()); + String modelType = compiler.getImportedType(modelClassName); + String code = objectCode + (eventInfo.getModelName() != null ? "." + modelMemberName + "()" : ""); + String eol = JAXXCompiler.getLineSeparator(); + String jaxxUtilPrefix = compiler.getImportedType(JAXXUtil.class); + result.append(modelType).append(" $target = (").append(modelType).append(") $bindingSources.remove(\"").append(code).append("\");").append(eol); + //TC-20091105 test if $target is not null + result.append("if ($target != null) {").append(eol); + //TC-20091105 JAXXUtil.getEventListener is generic, no more need cast and use simple listener name + ClassDescriptor listenerClass = eventInfo.getListenerClass(); + String listenerType = compiler.getImportedType(listenerClass.getName()); + result.append(" $target."); + result.append(eventInfo.getRemoveMethod()); + result.append("( ").append(jaxxUtilPrefix).append(".getEventListener("); + result.append(listenerType); + result.append(".class, "); + result.append("this"); + result.append(", "); + result.append(TypeManager.getJavaCode(methodName)); + result.append("));"); + result.append(eol); + result.append("}").append(eol); + if (eventInfo.getModelName() != null) { + result.append(getRemoveMemberListenerCode(handler, objectCode, "get" + StringUtils.capitalize(eventInfo.getModelName()), + jaxxUtilPrefix + ".getDataBindingUpdateListener(" + compiler.getOutputClassName() + ".this, " + constantId + ")", + compiler)); + } + return result.toString(); + } catch (NoSuchMethodException e) { + throw new CompilerException("Internal error: " + e); + } + } + + 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 { + handler.getBeanClass().getFieldDescriptor(memberName); + propertyName = memberName; + } catch (NoSuchFieldException e) { + // ignore ? + } + } + if (propertyName == null) { + return null; + } + + String prefix = objectCode.trim() + "."; + if (objectCode.equals(compiler.getRootObject().getJavaCode())) { + prefix = ""; + } + //TC-20091203 : always use the property specific method, this is part of the javaBeans 1.1 norm + //TC-20091203 : if developpers do bad, shame on them... + return prefix + "removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; +// try { +// // check for property-specific removePropertyChangeListener method +// handler.getBeanClass().getMethodDescriptor("removePropertyChangeListener", ClassDescriptorHelper.getClassDescriptor(String.class), +// ClassDescriptorHelper.getClassDescriptor(PropertyChangeListener.class)); +// return prefix + "removePropertyChangeListener(\"" + propertyName + "\", " + propertyChangeListenerCode + ");\n"; +// } catch (NoSuchMethodException e) { +// // no property-specific method, use general one +// return prefix + "removePropertyChangeListener(" + propertyChangeListenerCode + ");\n"; +// } + } + + /** + * Given a method from a given context class, try to obtain his method + * return type. + * + * Sometimes, the return type is unknown (generics can not be bind for + * example). As a fallback, we try if the context class is exactly the + * root context class of the compiler, replace it by the script method with + * same name on which we can have more chance to obtain a return type... + * + * @param contextClass the context class of the method + * @param method the method + * @return the method return type + * @since 2.4.2 + */ + protected ClassDescriptor getMethodReturnType(ClassDescriptor contextClass, + MethodDescriptor method) { + ClassDescriptor returnType = method.getReturnType(); + if (returnType == null && + contextClass.equals(compiler.getRootObject().getObjectClass())) { + + // special case to deal with generics (we need to + // have the concrete type)... + method = compiler.getScriptMethod(method.getName()); + if (method != null) { + returnType = method.getReturnType(); + } + } + return returnType; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/JavaParserUtil.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/JavaParserUtil.java new file mode 100644 index 0000000..47a2104 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/JavaParserUtil.java @@ -0,0 +1,383 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding; + +import jaxx.compiler.java.parser.JavaParserTreeConstants; +import jaxx.compiler.java.parser.SimpleNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.Introspector; +import java.util.*; + +/** + * Created: 4 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class JavaParserUtil { + + /** + * Logger + */ + private static final Log log = LogFactory.getLog(JavaParserUtil.class); + + private static final Comparator<String> STRING_LENGTH_COMPARATOR = new Comparator<String>() { + + @Override + public int compare(String o1, String o2) { + return o1.length() - o2.length(); + } + }; + + /** + * Obtain all expressions of a node and store them in {@code store} with their dependencies expressions. + * <p/> + * Also fill the {@code literals} list of literal expressions. + * + * @param node the node to scan + * @param store the store of expressions detected with all the expression which compose the expression (can be empty) + * @param literals the list of literal expressions detected + * @param casts the list of casted expression detected + */ + public static void getExpressions(SimpleNode node, Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literals, Map<SimpleNode, List<SimpleNode>> casts) { + + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION || + node.getId() == JavaParserTreeConstants.JJTFIELDDECLARATION) { + //TODO add all others non intressing type of node to reject directly + return; + } + + if (node.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION) { + // get a primary expression, look for his dependencies + scanForExpressions(node, null, store, literals, casts); + return; + } + + // recurse of childs of node + for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { + getExpressions(node.getChild(i), store, literals, casts); + } + + } + + /** + * Remove from expressions store, all literal expressions and dependencies on it. + * + * @param store the store of expressions with theirs dependencies + * @param literalExpressions the unvierse of literal expressions + */ + public static void removeLiteralExpressions(Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literalExpressions) { + for (SimpleNode n : literalExpressions) { + + // on supprime toutes les dependences sur les expression literales + // car on en a pas besoin pour decouvrir les expressions qui peuvent etre nulles... + + if (log.isDebugEnabled()) { + log.debug("Reject literal expression " + n.getText()); + } + for (List<SimpleNode> dependencies : store.values()) { + dependencies.remove(n); + } + store.remove(n); + } + } + + /** + * Remove from expressions sotre, all expressions with dependencies. + * + * @param store the store of expressions with their dependencies + * @param castsExpressions list of cast expression to keep + */ + public static void removeNoneStandaloneExpressions(Map<SimpleNode, List<SimpleNode>> store, Map<SimpleNode, List<SimpleNode>> castsExpressions) { + List<SimpleNode> rejectedExpressions = new ArrayList<SimpleNode>(); + + for (Map.Entry<SimpleNode, List<SimpleNode>> e : store.entrySet()) { + + List<SimpleNode> dependencies = e.getValue(); + SimpleNode node = e.getKey(); + if (castsExpressions.containsKey(node)) { + // the expression is part of a cast, need to keep it + continue; + } + if (!dependencies.isEmpty()) { + + // expression with dependencies, don't treate it, but treate all in dependencies :) + rejectedExpressions.add(node); + if (log.isDebugEnabled()) { + log.debug("Reject expression " + node.getText() + " with " + dependencies.size() + " dependencies"); + for (SimpleNode n : dependencies) { + log.debug(" " + n.getText()); + } + } + } + } + + for (SimpleNode node : rejectedExpressions) { + store.remove(node); + } + + rejectedExpressions.clear(); + } + + + public static Set<String> getRequired(Set<SimpleNode> store, Map<SimpleNode, List<SimpleNode>> casts) { + if (store.isEmpty()) { + return null; + } + + Set<SimpleNode> castCodes = new LinkedHashSet<SimpleNode>(); + for (List<SimpleNode> cast : casts.values()) { + for (SimpleNode node : cast) { + castCodes.add(node); + if (log.isDebugEnabled()) { + log.debug("cast = " + node.getText().trim()); + } + } + } + + List<String> result = new ArrayList<String>(); + for (SimpleNode node : store) { + String expression = node.getText().trim(); + if (result.contains(expression)) { + // already treated + continue; + } + for (SimpleNode castCode : castCodes) { + String str = castCode.getText().trim(); + int index = expression.indexOf(str); + if (index > -1) { + // got a cast, replace the cast expression, by the simple expression + // we have (CAST)XXX --> XXX + if (log.isDebugEnabled()) { + log.debug("got a cast in expresion " + expression + " = " + castCode); + } + String tmp = ""; + //FIXME : should check this is a complete cast : could be only a conversion... + if (index > 1) { + tmp = expression.substring(0, index - 1); + } + tmp += ((SimpleNode) castCode.jjtGetChild(1)).getText().trim() + expression.substring(index + str.length() + 1); + if (log.isDebugEnabled()) { + log.debug("REMOVED CAST : " + tmp); + } + expression = tmp; + } + } + if (expression.indexOf(".") == -1) { + // not an expression to keep + // a simple field use like 'isEnabled()' or 'field' + // or a not method invocation + if (log.isDebugEnabled()) { + log.debug("Reject simple expression " + expression); + } + continue; + } + if (expression.indexOf("(") == -1) { + // expression with no called method, probably is a constant + // should test it, but for the moment just limits bindings to interfield expressions : a.b + // is not possible, use a.getB() instead of + if (log.isDebugEnabled()) { + log.debug("Reject constant or static expression " + expression); + } + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Keep expression " + expression); + } + result.add(expression); + } + + if (result.isEmpty()) { + return null; + } + + Collections.sort(result, STRING_LENGTH_COMPARATOR); + if (log.isDebugEnabled()) { + log.debug("======= start with values : " + result); + } + + + Set<String> objectCodes = new LinkedHashSet<String>(); + + for (String expression : result) { + + // test if we have a cast in this expression + + Set<String> tmp = new LinkedHashSet<String>(); + + String[] paths = expression.split("\\s*\\.\\s*"); + if (paths.length < 2) { + // just a simple expression + // TODO Should never come here... + continue; + } + + if (log.isDebugEnabled()) { + log.debug("Expression to treate : " + expression + " :: " + Arrays.toString(paths)); + } + + StringBuilder buffer = new StringBuilder(); + String last = paths[0].trim(); + if (last.indexOf("(") > -1) { + // first path is a method invocation or a cast + // at the moment allow cast only on the first member and do no perform any check + + // must check this is a complete method invocation + String args = getMethodInvocationParameters(last); + if (args == null) { + // this path is not a method invocation + // must break + continue; + } + if (!args.isEmpty()) { + // for the moment, we only accept method with no args + // must break + continue; + } + + } + buffer.append(last); + tmp.add(buffer.toString()); + for (int i = 1, max = paths.length - 1; i < max; i++) { + String s = paths[i].trim(); + String args = getMethodInvocationParameters(s); + if (args == null) { + // this path is not a method invocation + // must break + // if previous + break; + } + if (!args.isEmpty()) { + // for the moment, we only accept method with no args + // must break + break; + } + buffer.append(".").append(s); + last = buffer.toString(); + tmp.add(last); + } + objectCodes.addAll(tmp); + } + + if (log.isDebugEnabled()) { + log.debug("Detected requirements : " + objectCodes); + } + return objectCodes; + } + + public static String getMethodInvocationParameters(String code) { + int openIndex = code.indexOf("("); + int closeIndex = code.lastIndexOf(")"); + if (openIndex > -1 && closeIndex > -1) { + if (closeIndex == openIndex + 1) { + return ""; + } + // missing something + return code.substring(openIndex + 1, closeIndex - 1).trim(); + } + return null; + } + + public static String getPropertyNameFromMethod(String code) { + int openIndex = code.indexOf("("); + if (openIndex != -1) { + code = code.substring(0, openIndex); + } + int index = 3; + if (code.startsWith("is")) { + index = 2; + } + code = code.substring(index); + code = Introspector.decapitalize(code); + return code; + } + + public static void scanForExpressions(SimpleNode node, SimpleNode lastExpressionNode, Map<SimpleNode, List<SimpleNode>> store, List<SimpleNode> literals, Map<SimpleNode, List<SimpleNode>> casts) { + + String nodeExpression = node.getText().trim(); + if (log.isTraceEnabled()) { + log.trace("node " + node.getId() + " nbChilds : " + node.jjtGetNumChildren() + " : " + nodeExpression); + } + if (node.getId() == JavaParserTreeConstants.JJTLITERAL) { + // expression literal qu'on ne veut pas garder ? + if (log.isDebugEnabled()) { + log.debug("detected literal " + nodeExpression + " for last expression " + lastExpressionNode.getText()); + } + literals.add(lastExpressionNode); + return; + } + if (node.getId() == JavaParserTreeConstants.JJTCASTEXPRESSION) { + // expression literal qu'on ne veut pas garder ? + if (log.isDebugEnabled()) { + log.debug("detected cast " + nodeExpression + " for last expression " + lastExpressionNode.getText()); + } + List<SimpleNode> simpleNodeList = casts.get(lastExpressionNode); + if (simpleNodeList == null) { + simpleNodeList = new ArrayList<SimpleNode>(); + casts.put(lastExpressionNode, simpleNodeList); + } + simpleNodeList.add(node); + } + + if (node.getId() == JavaParserTreeConstants.JJTPRIMARYEXPRESSION) { + + if (store.get(node) == null) { + store.put(node, new ArrayList<SimpleNode>()); + } + if (lastExpressionNode == null) { + + // premiere entree dans la methode (detection d'une nouvelle expression) + // rien a faire + + + } else { + + // on vient d'un appel recursif, on ajoute le noeud courant a la liste des expression de l'expression parent + + List<SimpleNode> simpleNodeList = store.get(lastExpressionNode); + if (simpleNodeList == null) { + simpleNodeList = new ArrayList<SimpleNode>(); + store.put(node, simpleNodeList); + } + simpleNodeList.add(node); + } + + // on change la derniere expression rencontree + lastExpressionNode = node; + } + + // on parcours tous les fils du noeud courant + for (int i = 0, count = node.jjtGetNumChildren(); i < count; i++) { + scanForExpressions(node.getChild(i), lastExpressionNode, store, literals, casts); + } + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/PseudoClassDataBinding.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/PseudoClassDataBinding.java new file mode 100644 index 0000000..1d5fe9a --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/PseudoClassDataBinding.java @@ -0,0 +1,134 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.binding; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.parser.JavaParser; +import jaxx.compiler.java.parser.JavaParserTreeConstants; +import jaxx.compiler.java.parser.SimpleNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.StringReader; + +/** + * 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 PseudoClassDataBinding extends DataBinding { + + /** + * Logger + */ + protected static final Log log = LogFactory.getLog(PseudoClassDataBinding.class); + + protected final boolean invert; + + public static PseudoClassDataBinding newPseudoClassDataBinding(String pseudoClass, CompiledObject object, String propertyCode, String methodName, boolean invertTest) { + PseudoClassDataBinding binding = null; + if (pseudoClass.startsWith("{")) { + pseudoClass = pseudoClass.substring(1, pseudoClass.length() - 1).trim(); + pseudoClass = replaceObjectReferences(pseudoClass, object.getJavaCode()); + String id = object.getId() + ".style." + pseudoClass + "." + methodName; + + if (log.isDebugEnabled()) { + log.debug("will test if databinding : ["+ pseudoClass +"] " + id); + } + binding = new PseudoClassDataBinding(id, pseudoClass, propertyCode, invertTest); + } + return binding; + } + + protected PseudoClassDataBinding(String id, String source, String assignment, boolean invert) { + super(id, source, assignment, false); + this.invert = invert; + } + + /** + * Replaces all references to the variable "object" with the actual object ID. + * + * @param code ? + * @param id ? + * @return ? + * @throws CompilerException + * ? + */ + public static 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(); + } + + public static 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); + } + } + } + + @Override + protected String getInitDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + // nothing to init + return null; + } + + @Override + protected String getProcessDataBindingCode(JAXXCompiler compiler, DataSource dataSource, boolean isBinding) { + if (!isBinding) { + return null; + } + + String eol = JAXXCompiler.getLineSeparator(); + + StringBuilder buffer = new StringBuilder(); + + String realSource = invert ? invert(getSource()) : getSource(); + buffer.append("if (").append(realSource).append(") {").append(eol); + buffer.append(JavaFileGenerator.indent(getAssignment(), 4, false, eol)).append(eol); + buffer.append("}"); + return buffer.toString(); + } + + protected String invert(String javaCode) { + javaCode = javaCode.trim(); + return javaCode.startsWith("!") ? javaCode.substring(1) : "!(" + javaCode + ")"; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java new file mode 100644 index 0000000..594ac64 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/AbstractJAXXBindingWriter.java @@ -0,0 +1,97 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding.writers; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.binding.DataBinding; +import jaxx.compiler.binding.DataListener; +import jaxx.compiler.finalizers.DefaultFinalizer; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; +import jaxx.runtime.JAXXBinding; + +import java.util.List; + +/** + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Id$ + */ +public abstract class AbstractJAXXBindingWriter<B extends JAXXBinding> implements JAXXBindingWriter<B> { + + private final Class<B> type; + + protected boolean used; + + protected AbstractJAXXBindingWriter(Class<B> type) { + this.type = type; + } + + @Override + public boolean isUsed() { + return used; + } + + @Override + public Class<B> getType() { + return type; + } + + @Override + public void reset() { + used = false; + } + + protected abstract String getConstructorParams(DataBinding binding, + DataListener[] trackers); + + protected void writeInvocationMethod(DataBinding binding, + DataListener[] trackers, + JavaFileGenerator generator, + StringBuilder buffer, + List<JavaMethod> bMethods) { + used = true; + String eol = JAXXCompiler.getLineSeparator(); + buffer.append(DefaultFinalizer.METHOD_NAME_REGISTER_DATA_BINDING); + buffer.append("(new "); + buffer.append(getType().getSimpleName()); + buffer.append("("); + buffer.append(getConstructorParams(binding, trackers)); + buffer.append(") {"); + buffer.append(eol); + for (JavaMethod m : bMethods) { + buffer.append(eol); + String source = generator.generateMethod(m); + buffer.append(JavaFileGenerator.indent(source, 4, false, eol)); + buffer.append(eol); + } + buffer.append("});").append(eol); + + if (binding.getInitDataBinding() != null) { + buffer.append(binding.getInitDataBinding()); + } + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java new file mode 100644 index 0000000..b09803d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/DefaultJAXXBindingWriter.java @@ -0,0 +1,137 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding.writers; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.binding.DataBinding; +import jaxx.compiler.binding.DataListener; +import jaxx.compiler.finalizers.DefaultFinalizer; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; +import jaxx.runtime.binding.DefaultJAXXBinding; + +import java.util.List; + +import static java.lang.reflect.Modifier.PUBLIC; + +/** + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class DefaultJAXXBindingWriter extends AbstractJAXXBindingWriter<DefaultJAXXBinding> { + + public DefaultJAXXBindingWriter() { + super(DefaultJAXXBinding.class); + } + + @Override + public boolean accept(DataBinding binding) { + return true; + } + + @Override + public void write(DataBinding binding, + JavaFileGenerator generator, + StringBuilder buffer) { + DataListener[] trackers = binding.getTrackers(); + String eol = JAXXCompiler.getLineSeparator(); + + StringBuilder addBuffer = new StringBuilder(); + StringBuilder removeBuffer = new StringBuilder(); + + for (DataListener tracker : trackers) { + boolean needTest = tracker.getObjectCode() != null; + if (needTest) { + addBuffer.append("if ("); + addBuffer.append(tracker.getObjectCode()); + addBuffer.append(" != null) {"); + addBuffer.append(eol); + + removeBuffer.append("if ("); + removeBuffer.append(tracker.getObjectCode()); + removeBuffer.append(" != null) {"); + removeBuffer.append(eol); + } + int indentLevel = needTest ? 4 : 0; + addBuffer.append(JavaFileGenerator.indent( + tracker.getAddListenerCode(), indentLevel, false, eol)); + removeBuffer.append(JavaFileGenerator.indent( + tracker.getRemoveListenerCode(), indentLevel, false, eol)); + if (needTest) { + addBuffer.append(eol).append("}"); + removeBuffer.append(eol).append("}"); + } + addBuffer.append(eol); + removeBuffer.append(eol); + } + + List<JavaMethod> bMethods = binding.getMethods(); + bMethods.add(0, JavaElementFactory.newMethod( + PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_REMOVE_DATA_BINDING, + removeBuffer.toString(), + true) + ); + bMethods.add(0, JavaElementFactory.newMethod( + PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_PROCESS_DATA_BINDING, + binding.getProcessDataBinding(), + true) + ); + bMethods.add(0, JavaElementFactory.newMethod( + PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_APPLY_DATA_BINDING, + addBuffer.toString(), + true) + ); + + writeInvocationMethod(binding, trackers, generator, buffer, bMethods); + } + + @Override + protected String getConstructorParams(DataBinding binding, + DataListener[] trackers) { + + String params = "this, " + binding.getConstantId() + ", true"; + if (trackers.length > 1) { + //FIXME tchemit-2011-04-21 Must improve this : only need a complex binding + // when chaining properties : example getA().getB() but not getA() || getB() + // with a complex binding, we will need to reload de binding after each fire... + params += ", true"; + + } + return params; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/JAXXBindingWriter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/JAXXBindingWriter.java new file mode 100644 index 0000000..14e985d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/JAXXBindingWriter.java @@ -0,0 +1,87 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding.writers; + +import jaxx.compiler.binding.DataBinding; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.runtime.JAXXBinding; + +/** + * The contract of a writer of {@link JAXXBinding} creation code from a + * {@link DataBinding}. + * <p/> + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public interface JAXXBindingWriter<B extends JAXXBinding> { + + /** + * Test if a binding can be treated by the writer. + * + * @param binding the binding to test + * @return {@code true} if this writer can be used to generate binding creation code, {@code false} otherwise. + */ + boolean accept(DataBinding binding); + + /** + * Test if the writer was at least used once (says that the method + * {@link #write(DataBinding, JavaFileGenerator, StringBuilder)} was at least invoked once). + * + * @return {@code true} if this writer was used + */ + boolean isUsed(); + + /** @return the type of {@link JAXXBinding} to generate */ + Class<B> getType(); + + /** + * Generate the creation code of the given {@code binding} and push it in the given {@code buffer}. + * <p/> + * Note: after beean in this method, the {@link #isUsed()} should always return {@code true}. + * + * @param binding the binding to use + * @param generator common generator to build creation code + * @param buffer where to push creation code + */ + void write(DataBinding binding, + JavaFileGenerator generator, + StringBuilder buffer); + + /** + * Reset internal states. + * <p/> + * At the moment, there is only the {@code used} property which is + * internal and must be reset to {@code false} for each compiler in order + * to know if a type of writer is used for the file. + * + * @since 2.4 + */ + void reset(); +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java new file mode 100644 index 0000000..0003777 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/binding/writers/SimpleJAXXObjectBindingWriter.java @@ -0,0 +1,111 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding.writers; + +import jaxx.compiler.binding.DataBinding; +import jaxx.compiler.binding.DataListener; +import jaxx.compiler.binding.JavaParserUtil; +import jaxx.compiler.finalizers.DefaultFinalizer; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; +import jaxx.runtime.binding.SimpleJAXXObjectBinding; + +import java.lang.reflect.Modifier; +import java.util.List; + +/** + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class SimpleJAXXObjectBindingWriter extends AbstractJAXXBindingWriter<SimpleJAXXObjectBinding> { + + protected boolean used; + + public SimpleJAXXObjectBindingWriter() { + super(SimpleJAXXObjectBinding.class); + } + + @Override + public boolean accept(DataBinding binding) { + DataListener[] trackers = binding.getTrackers(); + if (trackers.length > 0) { + for (DataListener tracker : trackers) { + if (tracker.getObjectCode() != null) { + // tracker must be without any requirement + return false; + } + } + } + return true; + } + + @Override + protected String getConstructorParams(DataBinding binding, + DataListener[] trackers) { + + StringBuilder addBuffer = new StringBuilder(); + addBuffer.append("this, "); + addBuffer.append(binding.getConstantId()); + addBuffer.append(", true"); + + for (DataListener tracker : trackers) { + String symbol = tracker.getSymbol(); + String name = symbol.substring(symbol.indexOf(".") + 1); + if (JavaParserUtil.getMethodInvocationParameters(name) != null) { + // obtain the property name from the method name + name = JavaParserUtil.getPropertyNameFromMethod(name); + } + addBuffer.append(" ,\"").append(name).append("\""); + } + return addBuffer.toString(); + } + + @Override + public void write(DataBinding binding, + JavaFileGenerator generator, + StringBuilder buffer) { + DataListener[] trackers = binding.getTrackers(); + List<JavaMethod> bMethods = binding.getMethods(); + + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + DefaultFinalizer.METHOD_NAME_PROCESS_DATA_BINDING, + binding.getProcessDataBinding(), + true + ); + + bMethods.add(0, method); + + writeInvocationMethod(binding, trackers, generator, buffer, bMethods); + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java new file mode 100644 index 0000000..ec65c13 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/StylesheetHelper.java @@ -0,0 +1,703 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.css; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.binding.DataBinding; +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.binding.PseudoClassDataBinding; +import jaxx.compiler.css.parser.CSSParser; +import jaxx.compiler.css.parser.CSSParserConstants; +import jaxx.compiler.css.parser.CSSParserTreeConstants; +import jaxx.compiler.css.parser.SimpleNode; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.tags.DefaultObjectHandler; +import jaxx.compiler.tags.TagManager; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.css.Pseudoclasses; +import jaxx.runtime.css.Rule; +import jaxx.runtime.css.Selector; +import jaxx.runtime.css.Stylesheet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * A helper class to compute {@link Stylesheet}, {@link Rule} and {@link Selector} + * and extract all the compiler logic from this class. + * <p/> + * In that way we can make the compiler as a single module and a runtime as another module. + * + * @author tchemit <chemit@codelutin.com> + */ +public class StylesheetHelper { + + /** Logger */ + static private final Log log = LogFactory.getLog(StylesheetHelper.class); + + public static Stylesheet processStylesheet(String stylesheetText) throws CompilerException { + CSSParser p = new CSSParser(new StringReader(stylesheetText)); + SimpleNode node; + try { + node = p.Stylesheet(); + } catch (Error e) { + throw new CompilerException(e); + } + List<Rule> rules = new ArrayList<Rule>(); + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode ruleNode = node.getChild(i); + Rule rule = processRule(ruleNode); + rules.add(rule); + } + Stylesheet stylesheet; + stylesheet = new Stylesheet(rules.toArray(new Rule[rules.size()])); + return stylesheet; + } + + public static Rule processRule(SimpleNode ruleNode) { + if (ruleNode.getId() != CSSParserTreeConstants.JJTRULE) { + throw new IllegalArgumentException("argument node is not a Rule"); + } + SimpleNode selectorsNode = ruleNode.getChild(0); + assert selectorsNode.getId() == CSSParserTreeConstants.JJTSELECTORS : + "expected node to be of type Selectors"; + + List<Selector> selectors = new ArrayList<Selector>(); + for (int i = 0; i < selectorsNode.jjtGetNumChildren(); i++) { + SimpleNode selectorNode = selectorsNode.getChild(i); + selectors.add(processSelector(selectorNode)); + } + + Map<String, String> properties = new HashMap<String, String>(); + for (int i = 1; i < ruleNode.jjtGetNumChildren(); i++) { + SimpleNode declarationNode = ruleNode.getChild(i); + if (declarationNode.getId() == CSSParserTreeConstants.JJTDECLARATION) { + String key = declarationNode.getChild(0).getText(); + SimpleNode valueNode = declarationNode.getChild(1); + String value = valueNode.getText(); + if (valueNode.firstToken.kind == CSSParserConstants.STRING) { + value = value.substring(1, value.length() - 1); + } + properties.put(key, value); + } + } + Rule rule; + rule = new Rule(selectors.toArray( + new Selector[selectors.size()]), properties); + return rule; + } + + public static Selector processSelector(SimpleNode selector) { + if (selector.getId() != CSSParserTreeConstants.JJTSELECTOR) { + throw new IllegalArgumentException("argument node is not a Selector"); + } + String javaClassName = null; + String styleClass = null; + String pseudoClass = null; + String id = null; + + for (int i = 0; i < selector.jjtGetNumChildren(); i++) { + SimpleNode child = selector.getChild(i); + switch (child.getId()) { + case CSSParserTreeConstants.JJTJAVACLASS: + if (!child.getText().trim().equals("*")) { + javaClassName = child.getText(); + } + break; + case CSSParserTreeConstants.JJTCLASS: + styleClass = child.getText().substring(1); + break; + case CSSParserTreeConstants.JJTPSEUDOCLASS: + pseudoClass = child.getText().substring(1); + break; + case CSSParserTreeConstants.JJTID: + id = child.getText().substring(1); + break; + + default: + throw new IllegalStateException( + "unexpected child of Selector node, type=" + + child.getId()); + } + } + + return new Selector(javaClassName, styleClass, pseudoClass, id); + } + + public enum MouseEventEnum { + + mouseover("mouseEntered", "mouseExited"), + mouseout("mouseExited", "mouseReleased"), + mousedown("mousePressed", "mousePressed"), + mouseup("mouseReleased", "mousePressed"); + + final String addMethod; + + final String removeMethod; + +// ClassDescriptor mouseListenerDescriptor; +// ClassDescriptor mouseEventDescriptor; + + MouseEventEnum(String addMethod, String removeMethod) { + this.removeMethod = removeMethod; + this.addMethod = addMethod; + } + + public String getProperty(int i) { + return i == 0 ? addMethod : removeMethod; + } + } + + static ClassDescriptor mouseListenerDescriptor; + + static ClassDescriptor mouseEventDescriptor; + + public static ClassDescriptor getMouseEventDescriptor() { + if (mouseEventDescriptor == null) { + mouseEventDescriptor = + ClassDescriptorHelper.getClassDescriptor(MouseEvent.class); + } + return mouseEventDescriptor; + } + + public static ClassDescriptor getMouseListenerDescriptor() { + if (mouseListenerDescriptor == null) { + mouseListenerDescriptor = + ClassDescriptorHelper.getClassDescriptor(MouseListener.class); + } + return mouseListenerDescriptor; + } + + public static MethodDescriptor getAddMouseListenerMethod(CompiledObject object) { + try { + MethodDescriptor addMouseListener = + object.getObjectClass().getMethodDescriptor( + "addMouseListener", + getMouseListenerDescriptor() + ); + return addMouseListener; + } catch (NoSuchMethodException e) { + throw new CompilerException( + "could not find addMouseListener for object " + object); + } + } + + public static MethodDescriptor getMouseListenerMethod(CompiledObject object, String property) { + try { + MethodDescriptor methodDescriptor = + getMouseListenerDescriptor().getMethodDescriptor( + property, + getMouseEventDescriptor() + ); + return methodDescriptor; + } catch (NoSuchMethodException e) { + throw new CompilerException( + "could not find " + property + " for object " + object); + } + } + + public static void applyTo(CompiledObject object, + JAXXCompiler compiler, + Stylesheet stylesheet, + Stylesheet overrides) throws CompilerException { + Map<String, String> overriddenProperties; + if (overrides != null) { + overriddenProperties = getApplicableProperties(overrides, object); + //overriddenProperties = overrides.getApplicableProperties(s,object); + } else { + overriddenProperties = null; + } + + Map<String, String> properties = getApplicableProperties(stylesheet, + 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(stylesheet, 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 (appliesTo(selector, 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++); + } + } + } + + public static String unwrap(ClassDescriptor type, String valueCode) { + if (ClassDescriptorHelper.getClassDescriptor(boolean.class).equals(type)) { + return "((Boolean) " + valueCode + ").booleanValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(byte.class).equals(type)) { + return "((Byte) " + valueCode + ").byteValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(short.class).equals(type)) { + return "((Short) " + valueCode + ").shortValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(int.class).equals(type)) { + return "((Integer) " + valueCode + ").intValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(long.class).equals(type)) { + return "((Long) " + valueCode + ").longValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(float.class).equals(type)) { + return "((Float) " + valueCode + ").floatValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(double.class).equals(type)) { + return "((Double) " + valueCode + ").doubleValue()"; + } + if (ClassDescriptorHelper.getClassDescriptor(char.class).equals(type)) { + return "((Character) " + valueCode + ").charValue()"; + } + return valueCode; + } + + public enum PseudoClassEnum { + focused("{ object.hasFocus() }"), + unfocused("{ !object.hasFocus() }"), + enabled("{ object.isEnabled() }"), + disabled("{ !object.isEnabled() }"), + selected("{ object.isSelected() }"), + deselected("{ !object.isSelected() }"); + + final String code; + + PseudoClassEnum(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + } + + public static void applyPseudoClass(String pseudoClass, + Map<String, String> properties, + CompiledObject object, + JAXXCompiler compiler, + int priority) throws CompilerException { + if (pseudoClass.contains("[")) { + pseudoClass = pseudoClass.substring(0, pseudoClass.indexOf("[")); + } + StringBuilder buffer = new StringBuilder(); + + DefaultObjectHandler handler = + TagManager.getTagHandler(object.getObjectClass()); + boolean valueDeclared = false; + String eol = JAXXCompiler.getLineSeparator(); + DataBindingHelper bindingHelper = compiler.getBindingHelper(); + + String pseudoClassesPrefix = null; + String dataBindingPrefix = null; + + if (!properties.isEmpty()) { + pseudoClassesPrefix = compiler.getImportedType(Pseudoclasses.class); + dataBindingPrefix = compiler.getImportedType(jaxx.runtime.css.DataBinding.class); + } + + String outputClassName = + compiler.getImportedType(compiler.getOutputClassName()); + + for (Map.Entry<String, String> e : properties.entrySet()) { + String property = e.getKey(); + ClassDescriptor type = handler.getPropertyType(object, + property, + compiler + ); + if (log.isDebugEnabled()) { + log.debug("will test if databinding : [" + e.getValue() + + "] type=" + type); + } + String dataBindingCode = + DataBindingHelper.processDataBindings(e.getValue()); + String valueCode; + String simpleType = compiler.getImportedType(JAXXCompiler.getCanonicalName(type)); + + if (dataBindingCode != null) { + String code = object.getId() + "." + property + "." + priority; + valueCode = "new " + dataBindingPrefix + "(" + + TypeManager.getJavaCode(code) + ")"; + DataBinding binding = new DataBinding( + code, + dataBindingCode, + handler.getSetPropertyCode( + object.getJavaCode(), + property, + "(" + simpleType + ") " + dataBindingCode, +// "(" + JAXXCompiler.getCanonicalName(type) + ") " + dataBindingCode, + compiler + ), + false + ); + bindingHelper.registerDataBinding(binding); + } else { + try { + Class<?> typeClass = type != null ? + ClassDescriptorHelper.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("Object "); + valueDeclared = true; + } + + buffer.append("value = "); + buffer.append(pseudoClassesPrefix); + buffer.append(".applyProperty("); + buffer.append(outputClassName); + buffer.append(".this, "); + buffer.append(object.getJavaCode()); + buffer.append(", "); + buffer.append(TypeManager.getJavaCode(property)); + buffer.append(", "); + buffer.append(valueCode); + buffer.append(", "); + buffer.append(pseudoClassesPrefix); + buffer.append(".wrap("); + buffer.append(handler.getGetPropertyCode(object.getJavaCode(), property, compiler)); + buffer.append("), "); + buffer.append(priority); + buffer.append(");"); + buffer.append(eol); + + buffer.append("if (!(value instanceof "); + buffer.append(dataBindingPrefix); + buffer.append(")) {"); + buffer.append(eol); + + String unwrappedValue = unwrap(type, "value"); + buffer.append(" "); + buffer.append(handler.getSetPropertyCode(object.getJavaCode(), property, "(" + simpleType + ") " + unwrappedValue, compiler)); + buffer.append(eol); + buffer.append("}").append(eol); + } + + try { + PseudoClassEnum classEnum = PseudoClassEnum.valueOf(pseudoClass); + pseudoClass = classEnum.getCode(); + } catch (IllegalArgumentException e) { + // should never happens ? +// throw new RuntimeException("could not find " + PseudoClassEnum.class + " with pseudoClass " + pseudoClass, e); + } + + compilePseudoClass(pseudoClass, object, buffer.toString(), 0, "add", compiler, false); + + 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 simpleType = compiler.getImportedType(JAXXCompiler.getCanonicalName(type)); + if (log.isDebugEnabled()) { + log.debug("will test if databinding : [" + e.getValue() + "] type=" + type); + } + String dataBindingCode = DataBindingHelper.processDataBindings(e.getValue()); + String valueCode; + if (dataBindingCode != null) { + String code = object.getId() + "." + property + "." + priority; + valueCode = "new " + dataBindingPrefix + "(" + TypeManager.getJavaCode(code) + ")"; + DataBinding binding = new DataBinding( + code, + dataBindingCode, + handler.getSetPropertyCode( + object.getJavaCode(), + property, + "(" + simpleType + ") " + dataBindingCode, + compiler + ), + false + ); + bindingHelper.registerDataBinding(binding); + } else { + try { + Class<?> typeClass = + type != null ? + ClassDescriptorHelper.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("Object "); + valueDeclared = true; + } + buffer.append("value = ").append(pseudoClassesPrefix).append(".removeProperty("); + + buffer.append(outputClassName); + buffer.append(".this, "); + buffer.append(object.getJavaCode()); + buffer.append(", "); + buffer.append(TypeManager.getJavaCode(property)); + buffer.append(", "); + buffer.append(valueCode); + buffer.append(", ").append(pseudoClassesPrefix).append(".wrap("); + buffer.append(handler.getGetPropertyCode(object.getJavaCode(), + property, + compiler) + ); + buffer.append("), "); + buffer.append(priority); + buffer.append(");"); + buffer.append(eol); + + buffer.append("if (!(value instanceof "); + buffer.append(dataBindingPrefix); + buffer.append(")) {"); + buffer.append(eol); + +// String simpleType = importManager.getType(JAXXCompiler.getCanonicalName(type)); + String unwrappedValue = unwrap(type, "value"); + buffer.append(" "); + buffer.append(handler.getSetPropertyCode( + object.getJavaCode(), + property, + "(" + simpleType + ") " + unwrappedValue, + compiler) + ); + buffer.append(eol); + buffer.append("}").append(eol); + } + compilePseudoClass(pseudoClass, + object, + buffer.toString(), + 1, + "remove", + compiler, + true + ); + } + + + public static void compilePseudoClass(String pseudoClass, + CompiledObject object, + String propertyCode, + int pos, + String methodName, + JAXXCompiler compiler, + boolean invertTest) throws CompilerException { + + PseudoClassDataBinding binding = + PseudoClassDataBinding.newPseudoClassDataBinding( + pseudoClass, + object, + propertyCode, + methodName, + invertTest + ); + if (binding != null) { + compiler.getBindingHelper().registerDataBinding(binding); + return; + } + MouseEventEnum constant = MouseEventEnum.valueOf(pseudoClass); + String property = constant.getProperty(pos); + MethodDescriptor addMouseListener = getAddMouseListenerMethod(object); + MethodDescriptor methodDescriptor = + getMouseListenerMethod(object, property); + object.addEventHandler("style." + pseudoClass + "." + methodName, + addMouseListener, + methodDescriptor, + propertyCode, + compiler + ); + } + + public static Map<String, String> getApplicableProperties( + Stylesheet s, CompiledObject object) throws CompilerException { + DefaultObjectHandler handler = + TagManager.getTagHandler(object.getObjectClass()); + Map<String, String> result = null; + for (Rule rule : s.getRules()) { + int apply = appliesTo(rule, 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 static Rule[] getApplicablePseudoClasses( + Stylesheet s, CompiledObject object) throws CompilerException { + List<Rule> result = null; + for (Rule rule : s.getRules()) { + if (appliesTo(rule, object) == Selector.PSEUDOCLASS_APPLIES) { + if (result == null) { + result = new ArrayList<Rule>(); + } + result.add(rule); + } + } + return result != null ? result.toArray(new Rule[result.size()]) : null; + } + + public static Rule inlineAttribute(CompiledObject object, + String propertyName, + boolean dataBinding) { + Map<String, String> properties = new HashMap<String, String>(); + properties.put(propertyName, dataBinding ? + Rule.DATA_BINDING : + Rule.INLINE_ATTRIBUTE); + return new Rule(new Selector[]{ + new Selector(null, null, null, object.getId(), true)}, + properties + ); + } + + public static int appliesTo(Rule rule, + CompiledObject object) throws CompilerException { + int appliesTo = Selector.NEVER_APPLIES; + for (Selector selector : rule.getSelectors()) { + appliesTo = Math.max(appliesTo(selector, object), appliesTo); + if (appliesTo == Selector.ALWAYS_APPLIES || + appliesTo == Selector.ALWAYS_APPLIES_INHERIT_ONLY) { + break; + } + } + return appliesTo; + } + + public static int appliesTo(Selector selector, CompiledObject object) { + boolean inheritOnly = false; + CompiledObject parent = object; + String javaClassName = selector.getJavaClassName(); + String styleClass = selector.getStyleClass(); + String pseudoClass = selector.getPseudoClass(); + String id = selector.getId(); + + while (parent != null) { + boolean classMatch = javaClassName == null; + if (!classMatch) { + ClassDescriptor javaClass = parent.getObjectClass(); + do { + String name = javaClass.getName(); + if (name.equals(javaClassName) || + name.substring(name.lastIndexOf(".") + 1).equals(javaClassName)) { + classMatch = true; + break; + } + javaClass = javaClass.getSuperclass(); + } while (javaClass != null); + } + + boolean styleClassMatch = styleClass == null || + styleClass.equals(parent.getStyleClass()); + + String objectId = parent.getId(); + objectId = objectId.substring(objectId.lastIndexOf(".") + 1); + boolean idMatch = id == null || + (' ' + objectId + ' ').contains(' ' + id + ' '); + + if (classMatch && styleClassMatch && idMatch) { + if (pseudoClass != null) { + return inheritOnly ? + Selector.PSEUDOCLASS_APPLIES_INHERIT_ONLY : + Selector.PSEUDOCLASS_APPLIES; + } else { + return inheritOnly ? + Selector.ALWAYS_APPLIES_INHERIT_ONLY : + Selector.ALWAYS_APPLIES; + } + } + + parent = parent.getParent(); + inheritOnly = true; + } + return Selector.NEVER_APPLIES; + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jj b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jj new file mode 100644 index 0000000..2c1c09e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jj @@ -0,0 +1,587 @@ +/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. .\CSS.jj */ +/*@egen*//* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ + +// I would love to have used an existing CSS parser, but all of the ones I could +// find are licensed under the LGPL. As JAXX is BSD licensed and I'm not a big +// fan of the LGPL, unfortunately that won't work. +options { + STATIC = false; + JDK_VERSION = "1.4"; +} + +PARSER_BEGIN(CSSParser) +package jaxx.css; + +public class CSSParser/*@bgen(jjtree)*/implements CSSParserTreeConstants/*@egen*/ {/*@bgen(jjtree)*/ + protected JJTCSSParserState jjtree = new JJTCSSParserState(); + +/*@egen*/ + public SimpleNode popNode() { + if ( jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode)jjtree.popNode(); + else + return null; + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public static void main(String args[]) { + System.out.println("Reading from standard input..."); + CSSParser css = new CSSParser(System.in); + try { + SimpleNode n = css.Stylesheet(); + n.dump(""); + System.out.println("Thank you."); + } catch (Exception e) { + System.out.println("Oops."); + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } +} + +PARSER_END(CSSParser) + + +<DEFAULT, IN_RULE> SKIP : +{ + " " +| "\t" +| "\n" +| "\r" +| <"//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")> +| <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"> +} + +<*> TOKEN : /* LITERALS */ +{ + <DECIMAL_LITERAL: <INTEGER_LITERAL> ("." <INTEGER_LITERAL>)?> +| + <#INTEGER_LITERAL: (["0"-"9"])+> +} + +<DEFAULT, IN_RULE> TOKEN : /* IDENTIFIER */ +{ + <IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)*> +| + <#LETTER: ["_", "-", "a"-"z", "A"-"Z"]> +| + <#DIGIT: ["0"-"9"]> +} + +<IN_PSEUDOCLASS> TOKEN : /* PSEUDOCLASS_IDENTIFIER */ +{ + <PSEUDOCLASS_IDENTIFIER: <IDENTIFIER>> : DEFAULT +} + +<DEFAULT> TOKEN: /* COLON */ +{ + <PSEUDOCLASS_COLON: ":"> : IN_PSEUDOCLASS +} + +<IN_RULE> TOKEN: /* COLON_IN_RULE */ +{ + <COLON: ":"> +} + +<*> TOKEN: /* SEMICOLON */ +{ + <SEMICOLON: ";"> +} + +TOKEN : /* LEFT BRACE */ +{ + <LEFT_BRACE: "{"> : IN_RULE +} + +<IN_RULE> TOKEN : /* RIGHT BRACE */ +{ + <RIGHT_BRACE: "}"> : DEFAULT +} + +<IN_RULE> TOKEN : /* JAVA_CODE_RULE START */ +{ + <JAVA_CODE_START: <LEFT_BRACE>> : JAVA_CODE_RULE +} + +<JAVA_CODE_RULE> TOKEN : /* JAVA_CODE_RULE */ +{ + <JAVA_CODE: (~["}"])+ > +} + +<JAVA_CODE_RULE> TOKEN : /* JAVA_CODE_RULE END */ +{ + <JAVA_CODE_END: <RIGHT_BRACE>> : IN_RULE +} + + +<IN_PSEUDOCLASS> TOKEN : /* PROGRAMMATIC_PSEUDOCLASS */ +{ + <PROGRAMMATIC_PSEUDOCLASS: "{" (~["}"])+ "}"> : DEFAULT +} + +<IN_RULE> TOKEN : /* STRINGS */ +{ + <STRING: "\"" (~["\"", "\\", "\n", "\r"])* "\""> +} + +<IN_RULE> TOKEN : /* COLORS */ +{ + <HEXCOLOR: "#" <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> (<HEXDIGIT> <HEXDIGIT> <HEXDIGIT>)?> +| + <#HEXDIGIT: ["0"-"9", "a"-"f", "A"-"F"]> +} + + +<IN_RULE> TOKEN : /* EMS */ +{ + <EMS: <DECIMAL_LITERAL> "em"> +} + + +<IN_RULE> TOKEN : /* EXS */ +{ + <EXS: <DECIMAL_LITERAL> "ex"> +} + + +<IN_RULE> TOKEN : /* LENGTH */ +{ + <LENGTH: <DECIMAL_LITERAL> ("pt" | "mm" | "cm" | "pc" | "in")> +} + + +SimpleNode Stylesheet() : {/*@bgen(jjtree) Stylesheet */ + SimpleNode jjtn000 = new SimpleNode(JJTSTYLESHEET); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Stylesheet */ + try { +/*@egen*/ + (Rule())*/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ + { return jjtn000; }/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Rule() : {/*@bgen(jjtree) Rule */ + SimpleNode jjtn000 = new SimpleNode(JJTRULE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Rule */ + try { +/*@egen*/ + Selectors() + <LEFT_BRACE> Declaration() (";" (Declaration())?)* <RIGHT_BRACE>/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Selectors() : {/*@bgen(jjtree) Selectors */ + SimpleNode jjtn000 = new SimpleNode(JJTSELECTORS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Selectors */ + try { +/*@egen*/ + Selector() ("," Selector())*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Selector() : {/*@bgen(jjtree) Selector */ + SimpleNode jjtn000 = new SimpleNode(JJTSELECTOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Selector */ + try { +/*@egen*/ + JavaClass() (Id())? (Class())? (PseudoClass())? +| + Id() (Class())? (PseudoClass())? +| + Class() (PseudoClass())? +| + PseudoClass()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void JavaClass() : {/*@bgen(jjtree) JavaClass */ + SimpleNode jjtn000 = new SimpleNode(JJTJAVACLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) JavaClass */ + try { +/*@egen*/ + <IDENTIFIER> | "*"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Id() : {/*@bgen(jjtree) Id */ + SimpleNode jjtn000 = new SimpleNode(JJTID); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Id */ + try { +/*@egen*/ + "#" <IDENTIFIER>/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Class() : {/*@bgen(jjtree) Class */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Class */ + try { +/*@egen*/ + "." <IDENTIFIER>/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void PseudoClass() : {/*@bgen(jjtree) PseudoClass */ + SimpleNode jjtn000 = new SimpleNode(JJTPSEUDOCLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PseudoClass */ + try { +/*@egen*/ + <PSEUDOCLASS_COLON> (<PSEUDOCLASS_IDENTIFIER> | <PROGRAMMATIC_PSEUDOCLASS>) (AnimationProperties())?/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void AnimationProperties() : {/*@bgen(jjtree) AnimationProperties */ + SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTIES); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AnimationProperties */ + try { +/*@egen*/ + "[" AnimationProperty() ("," AnimationProperty())* "]"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void AnimationProperty() : {/*@bgen(jjtree) AnimationProperty */ + SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AnimationProperty */ + try { +/*@egen*/ + <IDENTIFIER> "=" <DECIMAL_LITERAL> (<IDENTIFIER>)?/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Declaration() : {/*@bgen(jjtree) Declaration */ + SimpleNode jjtn000 = new SimpleNode(JJTDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Declaration */ + try { +/*@egen*/ + Property() <COLON> Expression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Property() : {/*@bgen(jjtree) Property */ + SimpleNode jjtn000 = new SimpleNode(JJTPROPERTY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Property */ + try { +/*@egen*/ + <IDENTIFIER>/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Expression() : {/*@bgen(jjtree) Expression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Expression */ + try { +/*@egen*/ + (<DECIMAL_LITERAL> | <STRING> | <IDENTIFIER> | <HEXCOLOR> | <EMS> | <EXS> | <LENGTH> | + JavaCode())/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void JavaCode() : {/*@bgen(jjtree) JavaCode */ + SimpleNode jjtn000 = new SimpleNode(JJTJAVACODE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) JavaCode */ + try { +/*@egen*/ + <JAVA_CODE_START> <JAVA_CODE> <JAVA_CODE_END>/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void Identifier() : {/*@bgen(jjtree) Identifier */ + SimpleNode jjtn000 = new SimpleNode(JJTIDENTIFIER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Identifier */ + try { +/*@egen*/ + <IDENTIFIER>/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jjt b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jjt new file mode 100644 index 0000000..17aa4e1 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSS.jjt @@ -0,0 +1,256 @@ +/* + * Copyright 2006 Ethan Nicholas. All rights reserved. + * Use is subject to license terms. + */ + +// I would love to have used an existing CSS parser, but all of the ones I could +// find are licensed under the LGPL. As JAXX is BSD licensed and I'm not a big +// fan of the LGPL, unfortunately that won't work. +options { + STATIC = false; + JDK_VERSION = "1.4"; + NODE_SCOPE_HOOK = true; +} + +PARSER_BEGIN(CSSParser) +package jaxx.css; + +public class CSSParser { + public SimpleNode popNode() { + if ( jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode)jjtree.popNode(); + else + return null; + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public static void main(String args[]) { + System.out.println("Reading from standard input..."); + CSSParser css = new CSSParser(System.in); + try { + SimpleNode n = css.Stylesheet(); + n.dump(""); + System.out.println("Thank you."); + } catch (Exception e) { + System.out.println("Oops."); + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } +} + +PARSER_END(CSSParser) + + +<DEFAULT, IN_RULE> SKIP : +{ + " " +| "\t" +| "\n" +| "\r" +| <"//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")> +| <"/*" (~["*"])* "*" (~["/"] (~["*"])* "*")* "/"> +} + +<*> TOKEN : /* LITERALS */ +{ + <DECIMAL_LITERAL: <INTEGER_LITERAL> ("." <INTEGER_LITERAL>)?> +| + <#INTEGER_LITERAL: (["0"-"9"])+> +} + +<DEFAULT, IN_RULE> TOKEN : /* IDENTIFIER */ +{ + <IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)*> +| + <#LETTER: ["_", "-", "a"-"z", "A"-"Z"]> +| + <#DIGIT: ["0"-"9"]> +} + +<IN_PSEUDOCLASS> TOKEN : /* PSEUDOCLASS_IDENTIFIER */ +{ + <PSEUDOCLASS_IDENTIFIER: <IDENTIFIER>> : DEFAULT +} + +<DEFAULT> TOKEN: /* COLON */ +{ + <PSEUDOCLASS_COLON: ":"> : IN_PSEUDOCLASS +} + +<IN_RULE> TOKEN: /* COLON_IN_RULE */ +{ + <COLON: ":"> +} + +<*> TOKEN: /* SEMICOLON */ +{ + <SEMICOLON: ";"> +} + +TOKEN : /* LEFT BRACE */ +{ + <LEFT_BRACE: "{"> : IN_RULE +} + +<IN_RULE> TOKEN : /* RIGHT BRACE */ +{ + <RIGHT_BRACE: "}"> : DEFAULT +} + +<IN_RULE> TOKEN : /* JAVA_CODE_RULE START */ +{ + <JAVA_CODE_START: <LEFT_BRACE>> : JAVA_CODE_RULE +} + +<JAVA_CODE_RULE> TOKEN : /* JAVA_CODE_RULE */ +{ + <JAVA_CODE: (~["}"])+ > +} + +<JAVA_CODE_RULE> TOKEN : /* JAVA_CODE_RULE END */ +{ + <JAVA_CODE_END: <RIGHT_BRACE>> : IN_RULE +} + + +<IN_PSEUDOCLASS> TOKEN : /* PROGRAMMATIC_PSEUDOCLASS */ +{ + <PROGRAMMATIC_PSEUDOCLASS: "{" (~["}"])+ "}"> : DEFAULT +} + +<IN_RULE> TOKEN : /* STRINGS */ +{ + <STRING: "\"" (~["\"", "\\", "\n", "\r"])* "\""> +} + +<IN_RULE> TOKEN : /* COLORS */ +{ + <HEXCOLOR: "#" <HEXDIGIT> <HEXDIGIT> <HEXDIGIT> (<HEXDIGIT> <HEXDIGIT> <HEXDIGIT>)?> +| + <#HEXDIGIT: ["0"-"9", "a"-"f", "A"-"F"]> +} + + +<IN_RULE> TOKEN : /* EMS */ +{ + <EMS: <DECIMAL_LITERAL> "em"> +} + + +<IN_RULE> TOKEN : /* EXS */ +{ + <EXS: <DECIMAL_LITERAL> "ex"> +} + + +<IN_RULE> TOKEN : /* LENGTH */ +{ + <LENGTH: <DECIMAL_LITERAL> ("pt" | "mm" | "cm" | "pc" | "in")> +} + + +SimpleNode Stylesheet() : {} +{ + (Rule())* + { return jjtThis; } +} + + +void Rule() : {} +{ + Selectors() + <LEFT_BRACE> Declaration() (";" (Declaration())?)* <RIGHT_BRACE> +} + + +void Selectors() : {} +{ + Selector() ("," Selector())* +} + + +void Selector() : {} +{ + JavaClass() (Id())? (Class())? (PseudoClass())? +| + Id() (Class())? (PseudoClass())? +| + Class() (PseudoClass())? +| + PseudoClass() +} + + +void JavaClass() : {} +{ + <IDENTIFIER> | "*" +} + + +void Id() : {} +{ + "#" <IDENTIFIER> +} + + +void Class() : {} +{ + "." <IDENTIFIER> +} + + +void PseudoClass() : {} +{ + <PSEUDOCLASS_COLON> (<PSEUDOCLASS_IDENTIFIER> | <PROGRAMMATIC_PSEUDOCLASS>) (AnimationProperties())? +} + + +void AnimationProperties() : {} +{ + "[" AnimationProperty() ("," AnimationProperty())* "]" +} + + +void AnimationProperty() : {} +{ + <IDENTIFIER> "=" <DECIMAL_LITERAL> (<IDENTIFIER>)? +} + + +void Declaration() : {} +{ + Property() <COLON> Expression() +} + + +void Property() : {} +{ + <IDENTIFIER> +} + + +void Expression() : {} +{ + (<DECIMAL_LITERAL> | <STRING> | <IDENTIFIER> | <HEXCOLOR> | <EMS> | <EXS> | <LENGTH> | + JavaCode()) +} + + +void JavaCode() : {} +{ + <JAVA_CODE_START> <JAVA_CODE> <JAVA_CODE_END> +} + + +void Identifier() : {} +{ + <IDENTIFIER> +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParser.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParser.java new file mode 100644 index 0000000..d5e63ce --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParser.java @@ -0,0 +1,824 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParser.java */ + +package jaxx.compiler.css.parser; + +public class CSSParser/*@bgen(jjtree)*/ implements CSSParserTreeConstants, CSSParserConstants {/*@bgen(jjtree)*/ + protected JJTCSSParserState jjtree = new JJTCSSParserState(); + + public SimpleNode popNode() { + if (jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode) jjtree.popNode(); + else + return null; + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public static void main(String args[]) { + System.out.println("Reading from standard input..."); + CSSParser css = new CSSParser(System.in); + try { + SimpleNode n = css.Stylesheet(); + n.dump(""); + System.out.println("Thank you."); + } catch (Exception e) { + System.out.println("Oops."); + System.out.println(e.getMessage()); + e.printStackTrace(); + } + } + + final public SimpleNode Stylesheet() throws ParseException { + /*@bgen(jjtree) Stylesheet */ + SimpleNode jjtn000 = new SimpleNode(JJTSTYLESHEET); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + label_1: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + case PSEUDOCLASS_COLON: + case 29: + case 30: + case 31: + ; + break; + default: + jj_la1[0] = jj_gen; + break label_1; + } + Rule(); + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return jjtn000; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + throw new Error("Missing return statement in function"); + } + + final public void Rule() throws ParseException { + /*@bgen(jjtree) Rule */ + SimpleNode jjtn000 = new SimpleNode(JJTRULE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Selectors(); + jj_consume_token(LEFT_BRACE); + Declaration(); + label_2: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SEMICOLON: + ; + break; + default: + jj_la1[1] = jj_gen; + break label_2; + } + jj_consume_token(SEMICOLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + Declaration(); + break; + default: + jj_la1[2] = jj_gen; + ; + } + } + jj_consume_token(RIGHT_BRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Selectors() throws ParseException { + /*@bgen(jjtree) Selectors */ + SimpleNode jjtn000 = new SimpleNode(JJTSELECTORS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Selector(); + label_3: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 28: + ; + break; + default: + jj_la1[3] = jj_gen; + break label_3; + } + jj_consume_token(28); + Selector(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Selector() throws ParseException { + /*@bgen(jjtree) Selector */ + SimpleNode jjtn000 = new SimpleNode(JJTSELECTOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + case 29: + JavaClass(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 30: + Id(); + break; + default: + jj_la1[4] = jj_gen; + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 31: + Class(); + break; + default: + jj_la1[5] = jj_gen; + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[6] = jj_gen; + ; + } + break; + case 30: + Id(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 31: + Class(); + break; + default: + jj_la1[7] = jj_gen; + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[8] = jj_gen; + ; + } + break; + case 31: + Class(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[9] = jj_gen; + ; + } + break; + case PSEUDOCLASS_COLON: + PseudoClass(); + break; + default: + jj_la1[10] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void JavaClass() throws ParseException { + /*@bgen(jjtree) JavaClass */ + SimpleNode jjtn000 = new SimpleNode(JJTJAVACLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + case 29: + jj_consume_token(29); + break; + default: + jj_la1[11] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Id() throws ParseException { + /*@bgen(jjtree) Id */ + SimpleNode jjtn000 = new SimpleNode(JJTID); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(30); + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Class() throws ParseException { + /*@bgen(jjtree) Class */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(31); + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PseudoClass() throws ParseException { + /*@bgen(jjtree) PseudoClass */ + SimpleNode jjtn000 = new SimpleNode(JJTPSEUDOCLASS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(PSEUDOCLASS_COLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PSEUDOCLASS_IDENTIFIER: + jj_consume_token(PSEUDOCLASS_IDENTIFIER); + break; + case PROGRAMMATIC_PSEUDOCLASS: + jj_consume_token(PROGRAMMATIC_PSEUDOCLASS); + break; + default: + jj_la1[12] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 32: + AnimationProperties(); + break; + default: + jj_la1[13] = jj_gen; + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnimationProperties() throws ParseException { + /*@bgen(jjtree) AnimationProperties */ + SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTIES); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(32); + AnimationProperty(); + label_4: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 28: + ; + break; + default: + jj_la1[14] = jj_gen; + break label_4; + } + jj_consume_token(28); + AnimationProperty(); + } + jj_consume_token(33); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnimationProperty() throws ParseException { + /*@bgen(jjtree) AnimationProperty */ + SimpleNode jjtn000 = new SimpleNode(JJTANIMATIONPROPERTY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + jj_consume_token(34); + jj_consume_token(DECIMAL_LITERAL); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + default: + jj_la1[15] = jj_gen; + ; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Declaration() throws ParseException { + /*@bgen(jjtree) Declaration */ + SimpleNode jjtn000 = new SimpleNode(JJTDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Property(); + jj_consume_token(COLON); + Expression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Property() throws ParseException { + /*@bgen(jjtree) Property */ + SimpleNode jjtn000 = new SimpleNode(JJTPROPERTY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Expression() throws ParseException { + /*@bgen(jjtree) Expression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case DECIMAL_LITERAL: + jj_consume_token(DECIMAL_LITERAL); + break; + case STRING: + jj_consume_token(STRING); + break; + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + case HEXCOLOR: + jj_consume_token(HEXCOLOR); + break; + case EMS: + jj_consume_token(EMS); + break; + case EXS: + jj_consume_token(EXS); + break; + case LENGTH: + jj_consume_token(LENGTH); + break; + case JAVA_CODE_START: + JavaCode(); + break; + default: + jj_la1[16] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void JavaCode() throws ParseException { + /*@bgen(jjtree) JavaCode */ + SimpleNode jjtn000 = new SimpleNode(JJTJAVACODE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(JAVA_CODE_START); + jj_consume_token(JAVA_CODE); + jj_consume_token(JAVA_CODE_END); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Identifier() throws ParseException { + /*@bgen(jjtree) Identifier */ + SimpleNode jjtn000 = new SimpleNode(JJTIDENTIFIER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + public CSSParserTokenManager token_source; + SimpleCharStream jj_input_stream; + public Token token, jj_nt; + private int jj_ntk; + private int jj_gen; + final private int[] jj_la1 = new int[17]; + static private int[] jj_la1_0; + static private int[] jj_la1_1; + + static { + jj_la1_0(); + jj_la1_1(); + } + + private static void jj_la1_0() { + jj_la1_0 = new int[]{0xe0002200, 0x8000, 0x200, 0x10000000, 0x40000000, 0x80000000, 0x2000, 0x80000000, 0x2000, 0x2000, 0xe0002200, 0x20000200, 0x201000, 0x0, 0x10000000, 0x200, 0xec40280,}; + } + + private static void jj_la1_1() { + jj_la1_1 = new int[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,}; + } + + public CSSParser(java.io.InputStream stream) { + this(stream, null); + } + + public CSSParser(java.io.InputStream stream, String encoding) { + try { + jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source = new CSSParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public void ReInit(java.io.InputStream stream) { + ReInit(stream, null); + } + + public void ReInit(java.io.InputStream stream, String encoding) { + try { + jj_input_stream.ReInit(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public CSSParser(java.io.Reader stream) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + token_source = new CSSParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public void ReInit(java.io.Reader stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public CSSParser(CSSParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + public void ReInit(CSSParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + jj_gen = 0; + for (int i = 0; i < 17; i++) jj_la1[i] = -1; + } + + final private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + jj_gen++; + return token; + } + token = oldToken; + jj_kind = kind; + throw generateParseException(); + } + + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + jj_gen++; + return token; + } + + final public Token getToken(int index) { + Token t = token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + final private int jj_ntk() { + if ((jj_nt = token.next) == null) + return (jj_ntk = (token.next = token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + private java.util.Vector jj_expentries = new java.util.Vector(); + private int[] jj_expentry; + private int jj_kind = -1; + + public ParseException generateParseException() { + Token errortok = token.next; + int line = errortok.beginLine, column = errortok.beginColumn; + String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image; + return new ParseException("Parse error. Encountered: " + mess, line, column); + } + + final public void enable_tracing() { + } + + final public void disable_tracing() { + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserConstants.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserConstants.java new file mode 100644 index 0000000..9887e9c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserConstants.java @@ -0,0 +1,97 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParserConstants.java */ + +package jaxx.compiler.css.parser; + +public interface CSSParserConstants { + + int EOF = 0; + int DECIMAL_LITERAL = 7; + int INTEGER_LITERAL = 8; + int IDENTIFIER = 9; + int LETTER = 10; + int DIGIT = 11; + int PSEUDOCLASS_IDENTIFIER = 12; + int PSEUDOCLASS_COLON = 13; + int COLON = 14; + int SEMICOLON = 15; + int LEFT_BRACE = 16; + int RIGHT_BRACE = 17; + int JAVA_CODE_START = 18; + int JAVA_CODE = 19; + int JAVA_CODE_END = 20; + int PROGRAMMATIC_PSEUDOCLASS = 21; + int STRING = 22; + int HEXCOLOR = 23; + int HEXDIGIT = 24; + int EMS = 25; + int EXS = 26; + int LENGTH = 27; + + int DEFAULT = 0; + int IN_RULE = 1; + int JAVA_CODE_RULE = 2; + int IN_PSEUDOCLASS = 3; + + String[] tokenImage = { + "<EOF>", + "\" \"", + "\"\\t\"", + "\"\\n\"", + "\"\\r\"", + "<token of kind 5>", + "<token of kind 6>", + "<DECIMAL_LITERAL>", + "<INTEGER_LITERAL>", + "<IDENTIFIER>", + "<LETTER>", + "<DIGIT>", + "<PSEUDOCLASS_IDENTIFIER>", + "\":\"", + "\":\"", + "\";\"", + "\"{\"", + "\"}\"", + "<JAVA_CODE_START>", + "<JAVA_CODE>", + "<JAVA_CODE_END>", + "<PROGRAMMATIC_PSEUDOCLASS>", + "<STRING>", + "<HEXCOLOR>", + "<HEXDIGIT>", + "<EMS>", + "<EXS>", + "<LENGTH>", + "\",\"", + "\"*\"", + "\"#\"", + "\".\"", + "\"[\"", + "\"]\"", + "\"=\"", + }; + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTokenManager.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTokenManager.java new file mode 100644 index 0000000..5156e4d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTokenManager.java @@ -0,0 +1,1177 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. CSSParserTokenManager.java */ + +package jaxx.compiler.css.parser; + +public class CSSParserTokenManager implements CSSParserConstants { + public java.io.PrintStream debugStream = System.out; + + public void setDebugStream(java.io.PrintStream ds) { + debugStream = ds; + } + + private int jjStopStringLiteralDfa_0(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_0(int pos, long active0) { + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); + } + + private int jjStopAtPos(int pos, int kind) { + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; + } + + private int jjStartNfaWithStates_0(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_0(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_0() { + switch (curChar) { + case 35: + return jjStopAtPos(0, 30); + case 42: + return jjStopAtPos(0, 29); + case 44: + return jjStopAtPos(0, 28); + case 46: + return jjStopAtPos(0, 31); + case 58: + return jjStopAtPos(0, 13); + case 59: + return jjStopAtPos(0, 15); + case 61: + return jjStopAtPos(0, 34); + case 91: + return jjStopAtPos(0, 32); + case 93: + return jjStopAtPos(0, 33); + case 123: + return jjStopAtPos(0, 16); + default: + return jjMoveNfa_0(3, 0); + } + } + + private void jjCheckNAdd(int state) { + if (jjrounds[state] != jjround) { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } + } + + private void jjAddStates(int start, int end) { + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); + } + + private void jjCheckNAddTwoStates(int state1, int state2) { + jjCheckNAdd(state1); + jjCheckNAdd(state2); + } + + private void jjCheckNAddStates(int start, int end) { + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); + } + + private void jjCheckNAddStates(int start) { + jjCheckNAdd(jjnextStates[start]); + jjCheckNAdd(jjnextStates[start + 1]); + } + + static final long[] jjbitVec0 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL + }; + + private int jjMoveNfa_0(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 17; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ;) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + } else if (curChar == 47) + jjAddStates(0, 1); + else if (curChar == 45) { + if (kind > 9) + kind = 9; + jjCheckNAdd(4); + } + break; + case 0: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + break; + case 1: + if (curChar == 46) + jjCheckNAdd(2); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(2); + break; + case 4: + if ((0x3ff200000000000L & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(4); + break; + case 5: + if (curChar == 47) + jjAddStates(0, 1); + break; + case 6: + if (curChar == 47) + jjCheckNAddStates(2, 4); + break; + case 7: + if ((0xffffffffffffdbffL & l) != 0L) + jjCheckNAddStates(2, 4); + break; + case 8: + if ((0x2400L & l) != 0L && kind > 5) + kind = 5; + break; + case 9: + if (curChar == 10 && kind > 5) + kind = 5; + break; + case 10: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 11: + if (curChar == 42) + jjCheckNAddTwoStates(12, 13); + break; + case 12: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(12, 13); + break; + case 13: + if (curChar == 42) + jjAddStates(5, 6); + break; + case 14: + if ((0xffff7fffffffffffL & l) != 0L) + jjCheckNAddTwoStates(15, 13); + break; + case 15: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(15, 13); + break; + case 16: + if (curChar == 47 && kind > 6) + kind = 6; + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + case 4: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(4); + break; + case 7: + jjAddStates(2, 4); + break; + case 12: + jjCheckNAddTwoStates(12, 13); + break; + case 14: + case 15: + jjCheckNAddTwoStates(15, 13); + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 7: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(2, 4); + break; + case 12: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(12, 13); + break; + case 14: + case 15: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(15, 13); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 17 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return curPos; + } + } + } + + private int jjStopStringLiteralDfa_3(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_3(int pos, long active0) { + return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1); + } + + private int jjStartNfaWithStates_3(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_3(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_3() { + switch (curChar) { + case 59: + return jjStopAtPos(0, 15); + default: + return jjMoveNfa_3(3, 0); + } + } + + private int jjMoveNfa_3(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 8; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ;) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + } else if (curChar == 45) { + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + } + break; + case 0: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + break; + case 1: + if (curChar == 46) + jjCheckNAdd(2); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(2); + break; + case 4: + if ((0x3ff200000000000L & l) == 0L) + break; + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + break; + case 6: + jjAddStates(7, 8); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 3: + if ((0x7fffffe87fffffeL & l) != 0L) { + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + } else if (curChar == 123) + jjCheckNAdd(6); + break; + case 4: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 12) + kind = 12; + jjCheckNAdd(4); + break; + case 5: + if (curChar == 123) + jjCheckNAdd(6); + break; + case 6: + if ((0xdfffffffffffffffL & l) != 0L) + jjCheckNAddTwoStates(6, 7); + break; + case 7: + if (curChar == 125) + kind = 21; + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 6: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(7, 8); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 8 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return curPos; + } + } + } + + private int jjStopStringLiteralDfa_1(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_1(int pos, long active0) { + return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); + } + + private int jjStartNfaWithStates_1(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_1(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_1() { + switch (curChar) { + case 58: + return jjStopAtPos(0, 14); + case 59: + return jjStopAtPos(0, 15); + case 125: + return jjStopAtPos(0, 17); + default: + return jjMoveNfa_1(0, 0); + } + } + + private int jjMoveNfa_1(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 50; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ;) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 0: + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddStates(9, 22); + } else if (curChar == 47) + jjAddStates(23, 24); + else if (curChar == 35) + jjstateSet[jjnewStateCnt++] = 7; + else if (curChar == 34) + jjCheckNAddTwoStates(4, 5); + else if (curChar == 45) { + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + } + break; + case 1: + if ((0x3ff200000000000L & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + break; + case 3: + if (curChar == 34) + jjCheckNAddTwoStates(4, 5); + break; + case 4: + if ((0xfffffffbffffdbffL & l) != 0L) + jjCheckNAddTwoStates(4, 5); + break; + case 5: + if (curChar == 34 && kind > 22) + kind = 22; + break; + case 6: + if (curChar == 35) + jjstateSet[jjnewStateCnt++] = 7; + break; + case 7: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 8; + break; + case 8: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 9: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 23) + kind = 23; + jjstateSet[jjnewStateCnt++] = 10; + break; + case 10: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 11; + break; + case 11: + if ((0x3ff000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 12: + if ((0x3ff000000000000L & l) != 0L && kind > 23) + kind = 23; + break; + case 13: + if (curChar == 47) + jjAddStates(23, 24); + break; + case 14: + if (curChar == 47) + jjCheckNAddStates(25, 27); + break; + case 15: + if ((0xffffffffffffdbffL & l) != 0L) + jjCheckNAddStates(25, 27); + break; + case 16: + if ((0x2400L & l) != 0L && kind > 5) + kind = 5; + break; + case 17: + if (curChar == 10 && kind > 5) + kind = 5; + break; + case 18: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 17; + break; + case 19: + if (curChar == 42) + jjCheckNAddTwoStates(20, 21); + break; + case 20: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(20, 21); + break; + case 21: + if (curChar == 42) + jjAddStates(28, 29); + break; + case 22: + if ((0xffff7fffffffffffL & l) != 0L) + jjCheckNAddTwoStates(23, 21); + break; + case 23: + if ((0xfffffbffffffffffL & l) != 0L) + jjCheckNAddTwoStates(23, 21); + break; + case 24: + if (curChar == 47 && kind > 6) + kind = 6; + break; + case 25: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddStates(9, 22); + break; + case 26: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(26, 27); + break; + case 27: + if (curChar == 46) + jjCheckNAdd(28); + break; + case 28: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(28); + break; + case 29: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(30, 32); + break; + case 30: + if (curChar == 46) + jjCheckNAdd(31); + break; + case 31: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(31, 33); + break; + case 34: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(33, 35); + break; + case 35: + if (curChar == 46) + jjCheckNAdd(36); + break; + case 36: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(36, 38); + break; + case 39: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(36, 41); + break; + case 40: + if (curChar == 46) + jjCheckNAdd(41); + break; + case 41: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(42, 46); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 0: + if ((0x7fffffe87fffffeL & l) != 0L) { + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + } else if (curChar == 123) { + if (kind > 18) + kind = 18; + } + break; + case 1: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 9) + kind = 9; + jjCheckNAdd(1); + break; + case 2: + if (curChar == 123 && kind > 18) + kind = 18; + break; + case 4: + if ((0xffffffffefffffffL & l) != 0L) + jjAddStates(47, 48); + break; + case 7: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 8; + break; + case 8: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 9: + if ((0x7e0000007eL & l) == 0L) + break; + if (kind > 23) + kind = 23; + jjstateSet[jjnewStateCnt++] = 10; + break; + case 10: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 11; + break; + case 11: + if ((0x7e0000007eL & l) != 0L) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 12: + if ((0x7e0000007eL & l) != 0L && kind > 23) + kind = 23; + break; + case 15: + jjAddStates(25, 27); + break; + case 20: + jjCheckNAddTwoStates(20, 21); + break; + case 22: + case 23: + jjCheckNAddTwoStates(23, 21); + break; + case 32: + if (curChar == 109 && kind > 25) + kind = 25; + break; + case 33: + if (curChar == 101) + jjstateSet[jjnewStateCnt++] = 32; + break; + case 37: + if (curChar == 120 && kind > 26) + kind = 26; + break; + case 38: + if (curChar == 101) + jjstateSet[jjnewStateCnt++] = 37; + break; + case 42: + if (curChar == 109 && kind > 27) + kind = 27; + break; + case 43: + if (curChar == 109) + jjCheckNAdd(42); + break; + case 44: + if (curChar == 99) + jjCheckNAdd(42); + break; + case 45: + if (curChar == 110 && kind > 27) + kind = 27; + break; + case 46: + if (curChar == 105) + jjstateSet[jjnewStateCnt++] = 45; + break; + case 47: + if (curChar == 112) + jjAddStates(49, 50); + break; + case 48: + if (curChar == 116 && kind > 27) + kind = 27; + break; + case 49: + if (curChar == 99 && kind > 27) + kind = 27; + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(47, 48); + break; + case 15: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(25, 27); + break; + case 20: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(20, 21); + break; + case 22: + case 23: + if ((jjbitVec0[i2] & l2) != 0L) + jjCheckNAddTwoStates(23, 21); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 50 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return curPos; + } + } + } + + private int jjStopStringLiteralDfa_2(int pos, long active0) { + switch (pos) { + default: + return -1; + } + } + + private int jjStartNfa_2(int pos, long active0) { + return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1); + } + + private int jjStartNfaWithStates_2(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_2(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_2() { + switch (curChar) { + case 59: + return jjStartNfaWithStates_2(0, 15, 3); + default: + return jjMoveNfa_2(4, 0); + } + } + + private int jjMoveNfa_2(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 5; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ;) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + } + break; + case 0: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddTwoStates(0, 1); + break; + case 1: + if (curChar == 46) + jjCheckNAdd(2); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(2); + break; + case 3: + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + if ((0xdfffffffffffffffL & l) != 0L) { + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + } else if (curChar == 125) { + if (kind > 20) + kind = 20; + } + break; + case 3: + if ((0xdfffffffffffffffL & l) == 0L) + break; + kind = 19; + jjCheckNAdd(3); + break; + default: + break; + } + } while (i != startsAt); + } else { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 4: + case 3: + if ((jjbitVec0[i2] & l2) == 0L) + break; + if (kind > 19) + kind = 19; + jjCheckNAdd(3); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 5 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } + catch (java.io.IOException e) { + return curPos; + } + } + } + + static final int[] jjnextStates = { + 6, 11, 7, 8, 10, 14, 16, 6, 7, 26, 27, 29, 30, 33, 34, 35, + 38, 39, 40, 43, 44, 46, 47, 14, 19, 15, 16, 18, 22, 24, 29, 30, + 33, 34, 35, 38, 39, 40, 43, 44, 46, 47, 41, 43, 44, 46, 47, 4, + 5, 48, 49, + }; + public static final String[] jjstrLiteralImages = { + "", null, null, null, null, null, null, null, null, null, null, null, null, + "\72", "\72", "\73", "\173", "\175", null, null, null, null, null, null, null, null, + null, null, "\54", "\52", "\43", "\56", "\133", "\135", "\75",}; + public static final String[] lexStateNames = { + "DEFAULT", + "IN_RULE", + "JAVA_CODE_RULE", + "IN_PSEUDOCLASS", + }; + public static final int[] jjnewLexState = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 3, -1, -1, 1, 0, 2, -1, 1, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + static final long[] jjtoToken = { + 0x7fefff281L, + }; + static final long[] jjtoSkip = { + 0x7eL, + }; + protected SimpleCharStream input_stream; + private final int[] jjrounds = new int[50]; + private final int[] jjstateSet = new int[100]; + protected char curChar; + + public CSSParserTokenManager(SimpleCharStream stream) { + if (SimpleCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; + } + + public CSSParserTokenManager(SimpleCharStream stream, int lexState) { + this(stream); + SwitchTo(lexState); + } + + public void ReInit(SimpleCharStream stream) { + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); + } + + private void ReInitRounds() { + int i; + jjround = 0x80000001; + for (i = 50; i-- > 0;) + jjrounds[i] = 0x80000000; + } + + public void ReInit(SimpleCharStream stream, int lexState) { + ReInit(stream); + SwitchTo(lexState); + } + + public void SwitchTo(int lexState) { + if (lexState >= 4 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; + } + + protected Token jjFillToken() { + Token t = Token.newToken(jjmatchedKind); + t.kind = jjmatchedKind; + String im = jjstrLiteralImages[jjmatchedKind]; + t.image = (im == null) ? input_stream.GetImage() : im; + t.beginLine = input_stream.getBeginLine(); + t.beginColumn = input_stream.getBeginColumn(); + t.endLine = input_stream.getEndLine(); + t.endColumn = input_stream.getEndColumn(); + return t; + } + + int curLexState = 0; + int defaultLexState = 0; + int jjnewStateCnt; + int jjround; + int jjmatchedPos; + int jjmatchedKind; + + public Token getNextToken() { + int kind; + Token specialToken = null; + Token matchedToken; + int curPos = 0; + + EOFLoop: + for (; ;) { + try { + curChar = input_stream.BeginToken(); + } + catch (java.io.IOException e) { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + return matchedToken; + } + + switch (curLexState) { + case 0: + try { + input_stream.backup(0); + while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } + catch (java.io.IOException e1) { + continue EOFLoop; + } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + break; + case 1: + try { + input_stream.backup(0); + while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } + catch (java.io.IOException e1) { + continue EOFLoop; + } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + break; + case 2: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_2(); + break; + case 3: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_3(); + break; + } + if (jjmatchedKind != 0x7fffffff) { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) { + matchedToken = jjFillToken(); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } else { + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { + input_stream.readChar(); + input_stream.backup(1); + } + catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTreeConstants.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTreeConstants.java new file mode 100644 index 0000000..6a0965d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/CSSParserTreeConstants.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. .\CSSParserTreeConstants.java */ + + +package jaxx.compiler.css.parser; + +public interface CSSParserTreeConstants { + int JJTSTYLESHEET = 0; + int JJTRULE = 1; + int JJTSELECTORS = 2; + int JJTSELECTOR = 3; + int JJTJAVACLASS = 4; + int JJTID = 5; + int JJTCLASS = 6; + int JJTPSEUDOCLASS = 7; + int JJTANIMATIONPROPERTIES = 8; + int JJTANIMATIONPROPERTY = 9; + int JJTDECLARATION = 10; + int JJTPROPERTY = 11; + int JJTEXPRESSION = 12; + int JJTJAVACODE = 13; + int JJTIDENTIFIER = 14; + + + String[] jjtNodeName = { + "Stylesheet", + "Rule", + "Selectors", + "Selector", + "JavaClass", + "Id", + "Class", + "PseudoClass", + "AnimationProperties", + "AnimationProperty", + "Declaration", + "Property", + "Expression", + "JavaCode", + "Identifier", + }; +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/JJTCSSParserState.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/JJTCSSParserState.java new file mode 100644 index 0000000..6fbb540 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/JJTCSSParserState.java @@ -0,0 +1,148 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. .\JJTCSSParserState.java */ + + +package jaxx.compiler.css.parser; + +class JJTCSSParserState { + private java.util.Stack<Node> nodes; + private java.util.Stack<Integer> marks; + + private int sp; // number of nodes on stack + private int mk; // current mark + private boolean node_created; + + JJTCSSParserState() { + nodes = new java.util.Stack<Node>(); + marks = new java.util.Stack<Integer>(); + sp = 0; + mk = 0; + } + + /* Determines whether the current node was actually closed and + pushed. This should only be called in the final user action of a + node scope. */ + boolean nodeCreated() { + return node_created; + } + + /* Call this to reinitialize the node stack. It is called +automatically by the parser's ReInit() method. */ + void reset() { + nodes.removeAllElements(); + marks.removeAllElements(); + sp = 0; + mk = 0; + } + + /* Returns the root node of the AST. It only makes sense to call +this after a successful parse. */ + Node rootNode() { + return nodes.elementAt(0); + } + + /* Pushes a node on to the stack. */ + void pushNode(Node n) { + nodes.push(n); + ++sp; + } + + /* Returns the node on the top of the stack, and remove it from the + stack. */ + Node popNode() { + if (--sp < mk) { + mk = marks.pop(); + } + return nodes.pop(); + } + + /* Returns the node currently on the top of the stack. */ + Node peekNode() { + return nodes.peek(); + } + + /* Returns the number of children on the stack in the current node + scope. */ + int nodeArity() { + return sp - mk; + } + + + void clearNodeScope(Node n) { + while (sp > mk) { + popNode(); + } + mk = marks.pop(); + } + + + void openNodeScope(Node n) { + marks.push(mk); + mk = sp; + n.jjtOpen(); + } + + + /* A definite node is constructed from a specified number of +children. That number of nodes are popped from the stack and +made the children of the definite node. Then the definite node +is pushed on to the stack. */ + void closeNodeScope(Node n, int num) { + mk = marks.pop(); + while (num-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, num); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } + + + /* A conditional node is constructed if its condition is true. All +the nodes that have been pushed since the node was opened are +made children of the the conditional node, which is then pushed +on to the stack. If the condition is false the node is not +constructed and they are left on the stack. */ + void closeNodeScope(Node n, boolean condition) { + if (condition) { + int a = nodeArity(); + mk = marks.pop(); + while (a-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, a); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } else { + mk = marks.pop(); + node_created = false; + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Node.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Node.java new file mode 100644 index 0000000..516c4f8 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Node.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. Node.java */ + + +package jaxx.compiler.css.parser; + +/* All AST nodes must implement this interface. It provides basic + machinery for constructing the parent and child relationships + between nodes. */ + +public interface Node { + + /** + * This method is called after the node has been made the current + * node. It indicates that child nodes can now be added to it. + */ + public void jjtOpen(); + + /** + * This method is called after all the child nodes have been + * added. + */ + public void jjtClose(); + + /** + * This pair of methods are used to inform the node of its + * parent. + * + * @param n node + */ + public void jjtSetParent(Node n); + + public Node jjtGetParent(); + + /** + * This method tells the node to add its argument to the node's + * list of children. + * + * @param n node + * @param i pos + */ + public void jjtAddChild(Node n, int i); + + /** + * @param i pos + * @return a child node. The children are numbered + * from zero, left to right. + */ + public Node jjtGetChild(int i); + + /** @return the number of children the node has. */ + public int jjtGetNumChildren(); +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/ParseException.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/ParseException.java new file mode 100644 index 0000000..ba9a90e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/ParseException.java @@ -0,0 +1,45 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ + +package jaxx.compiler.css.parser; + +public class ParseException extends jaxx.compiler.java.parser.ParseException { + private static final long serialVersionUID = 229575674880359031L; + + public ParseException() { + super(); + } + + + public ParseException(String message) { + super(message); + } + + + public ParseException(String message, int line, int column) { + super(message, line, column); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleCharStream.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleCharStream.java new file mode 100644 index 0000000..988847c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleCharStream.java @@ -0,0 +1,423 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */ + +package jaxx.compiler.css.parser; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (without unicode processing). + */ + +public class SimpleCharStream { + public static final boolean staticFlag = false; + int bufsize; + int available; + int tokenBegin; + public int bufpos = -1; + protected int bufline[]; + protected int bufcolumn[]; + + protected int column = 0; + protected int line = 1; + + protected boolean prevCharIsCR = false; + protected boolean prevCharIsLF = false; + + protected java.io.Reader inputStream; + + protected char[] buffer; + protected int maxNextCharInd = 0; + protected int inBuf = 0; + protected int tabSize = 8; + + protected void setTabSize(int i) { + tabSize = i; + } + + protected int getTabSize(int i) { + return tabSize; + } + + + protected void ExpandBuff(boolean wrapAround) { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try { + if (wrapAround) { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, + bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos += (bufsize - tokenBegin)); + } else { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos -= tokenBegin); + } + } + catch (Throwable t) { + throw new Error(t.getMessage()); + } + + + bufsize += 2048; + available = bufsize; + tokenBegin = 0; + } + + protected void FillBuff() throws java.io.IOException { + if (maxNextCharInd == available) { + if (available == bufsize) { + if (tokenBegin > 2048) { + bufpos = maxNextCharInd = 0; + available = tokenBegin; + } else if (tokenBegin < 0) + bufpos = maxNextCharInd = 0; + else + ExpandBuff(false); + } else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + int i; + try { + if ((i = inputStream.read(buffer, maxNextCharInd, + available - maxNextCharInd)) == -1) { + inputStream.close(); + throw new java.io.IOException(); + } else + maxNextCharInd += i; + } + catch (java.io.IOException e) { + --bufpos; + backup(0); + if (tokenBegin == -1) + tokenBegin = bufpos; + throw e; + } + } + + public char BeginToken() throws java.io.IOException { + tokenBegin = -1; + char c = readChar(); + tokenBegin = bufpos; + + return c; + } + + protected void UpdateLineColumn(char c) { + column++; + + if (prevCharIsLF) { + prevCharIsLF = false; + line += (column = 1); + } else if (prevCharIsCR) { + prevCharIsCR = false; + if (c == '\n') { + prevCharIsLF = true; + } else + line += (column = 1); + } + + switch (c) { + case '\r': + prevCharIsCR = true; + break; + case '\n': + prevCharIsLF = true; + break; + case '\t': + column--; + column += (tabSize - (column % tabSize)); + break; + default: + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + + public char readChar() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + if (++bufpos >= maxNextCharInd) + FillBuff(); + + char c = buffer[bufpos]; + + UpdateLineColumn(c); + return (c); + } + + /** + * @return ??? + * @see #getEndColumn + * @deprecated + */ + + public int getColumn() { + return bufcolumn[bufpos]; + } + + /** + * @return ??? + * @see #getEndLine + * @deprecated + */ + + public int getLine() { + return bufline[bufpos]; + } + + public int getEndColumn() { + return bufcolumn[bufpos]; + } + + public int getEndLine() { + return bufline[bufpos]; + } + + public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + public int getBeginLine() { + return bufline[tokenBegin]; + } + + public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.Reader dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + bufpos = -1; + } + + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public void ReInit(java.io.Reader dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, 1, 1, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public String GetImage() { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + public char[] GetSuffix(int len) { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + public void Done() { + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + * + * @param newLine ? + * @param newCol ? + */ + public void adjustBeginLineColumn(int newLine, int newCol) { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) { + len = bufpos - tokenBegin + inBuf + 1; + } else { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k; + int nextColDiff, columnDiff = 0; + + while (i < len && + bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleNode.java new file mode 100644 index 0000000..f300c62 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/SimpleNode.java @@ -0,0 +1,147 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ + + +package jaxx.compiler.css.parser; + +public class SimpleNode implements Node { + protected Node parent; + protected Node[] children; + protected int id; + protected CSSParser parser; + public Token firstToken; + public Token lastToken; + + + public SimpleNode(int i) { + id = i; + } + + public SimpleNode(CSSParser p, int i) { + this(i); + parser = p; + } + + + public int getId() { + return id; + } + + public void jjtOpen() { + } + + public void jjtClose() { + } + + public void jjtSetParent(Node n) { + parent = n; + } + + public Node jjtGetParent() { + return parent; + } + + public SimpleNode getParent() { + return (SimpleNode) parent; + } + + public void jjtAddChild(Node n, int i) { + if (children == null) { + children = new Node[i + 1]; + } else if (i >= children.length) { + Node c[] = new Node[i + 1]; + System.arraycopy(children, 0, c, 0, children.length); + children = c; + } + children[i] = n; + } + + public Node jjtGetChild(int i) { + return children[i]; + } + + public SimpleNode getChild(int i) { + return (SimpleNode) children[i]; + } + + public int jjtGetNumChildren() { + return children == null ? 0 : children.length; + } + + /* You can override these two methods in subclasses of SimpleNode to +customize the way the node appears when the tree is dumped. If +your output uses more than one line you should override +toString(String), otherwise overriding toString() is probably all +you need to do. */ + + @Override + public String toString() { + return getClass().getName() + "[" + getText() + "]"; + } + + public String toString(String prefix) { + return prefix + toString(); + } + + /* Override this method if you want to customize how the node dumps + out its children. */ + + public void dump(String prefix) { + System.out.println(toString(prefix)); + if (children != null) { + for (Node aChildren : children) { + SimpleNode n = (SimpleNode) aChildren; + if (n != null) { + n.dump(prefix + " "); + } + } + } + } + + private void appendSpecialTokens(StringBuilder s, Token st) { + if (st != null) { + appendSpecialTokens(s, st.specialToken); + s.append(st.image); + } + } + + + /** @return the text of the tokens comprising this node. */ + public String getText() { + StringBuilder text = new StringBuilder(); + Token t = firstToken; + while (t != null) { + appendSpecialTokens(text, t.specialToken); + text.append(t.image); + if (t == lastToken) + break; + t = t.next; + } + + return text.toString(); + } +} + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Token.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Token.java new file mode 100644 index 0000000..0eac39a --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/Token.java @@ -0,0 +1,101 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ + +package jaxx.compiler.css.parser; + +/** Describes the input token stream. */ + +public class Token { + + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** + * beginLine and beginColumn describe the position of the first character + * of this token; endLine and endColumn describe the position of the + * last character of this token. + */ + public int beginLine, beginColumn, endLine, endColumn; + + /** The string image of the token. */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** Returns the image. */ + public String toString() { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simlpy add something like : + * <p/> + * case MyParserConstants.ID : return new IDToken(); + * <p/> + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use it in your lexical actions. + * + * @param ofKind kind of token + * @return the new token + */ + public static Token newToken(int ofKind) { + switch (ofKind) { + default: + return new Token(); + } + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/TokenMgrError.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/TokenMgrError.java new file mode 100644 index 0000000..79fe183 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/css/parser/TokenMgrError.java @@ -0,0 +1,151 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ + +package jaxx.compiler.css.parser; + +public class TokenMgrError extends Error { + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** Lexical error occured. */ + static final int LEXICAL_ERROR = 0; + + /** An attempt wass made to create a second instance of a static token manager. */ + static final int STATIC_LEXER_ERROR = 1; + + /** Tried to change to an invalid lexical state. */ + static final int INVALID_LEXICAL_STATE = 2; + + /** Detected (and bailed out of) an infinite loop in the token manager. */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + private static final long serialVersionUID = -4308847190164230336L; + + /** + * Replaces unprintable characters by their espaced (or unicode escaped) + * equivalents in the given string + * + * @param str text to espace + * @return the espaced text + */ + protected static String addEscapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case 0: + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u").append(s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + } + } + return retval.toString(); + } + + /** + * @param EOFSeen : indicates if EOF caused the lexicl error + * @param lexState : lexical state in which this error occured + * @param errorLine : line number when the error occured + * @param errorColumn : column number when the error occured + * @param errorAfter : prefix that was seen before this error occured + * @param curChar : the offending character + * Note: You can customize the lexical error message by modifying this method. + * @return a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return "Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? "<EOF> " : "\"" + addEscapes(String.valueOf(curChar)) + "\"" + " (" + (int) curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""; + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * <p/> + * "Internal Error : Please file a bug report .... " + * <p/> + * from this method for such cases in the release version of your parser. + */ + @Override + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + public TokenMgrError() { + } + + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java new file mode 100644 index 0000000..82e4996 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/BoxedCompiledObjectDecorator.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.decorators; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompiledObject.ChildRef; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaFile; +import jaxx.runtime.SwingUtil; + +/** + * A decorator to surround a compiled object (should be a component at least) + * with a JXLayer. + * + * @author tchemit <chemit@codelutin.com> + * @plexus.component role-hint="boxed" role="jaxx.compiler.CompiledObjectDecorator" + * @since 1.2 + */ +public class BoxedCompiledObjectDecorator extends DefaultCompiledObjectDecorator { + + @Override + public String getName() { + return "boxed"; + } + + @Override + public void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException { + CompiledObject parent = object.getParent(); + if (parent == null) { + parent = root; + } + for (ChildRef child : parent.getChilds()) { + if (child.getChild() == object) { + String javaCode = child.getChildJavaCode(); + String type = compiler.getImportedType(SwingUtil.class); + child.setChildJavaCode( + type + + ".boxComponentWithJxLayer(" + javaCode + ")"); + break; + } + } + super.finalizeCompiler(compiler, + root, + object, + javaFile, + packageName, + className, + fullClassName + ); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java new file mode 100644 index 0000000..7d420bb --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/DefaultCompiledObjectDecorator.java @@ -0,0 +1,364 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.decorators; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompiledObjectDecorator; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaField; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.java.JavaMethod; +import jaxx.compiler.script.ScriptInitializer; +import jaxx.compiler.types.TypeManager; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Modifier; +import java.util.Map.Entry; + +/** + * The default decorator to use on all compiled objects. + * + * @author tchemit <chemit@codelutin.com> + * @plexus.component role-hint="default" role="jaxx.compiler.CompiledObjectDecorator" + * @since 1.2 + */ +public class DefaultCompiledObjectDecorator implements CompiledObjectDecorator { + + + /** Logger */ + protected static final Log log = + LogFactory.getLog(DefaultCompiledObjectDecorator.class); + + @Override + public String getName() { + return "default"; + } + + @Override + public void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException{ + + if (object instanceof ScriptInitializer) { + + // nothing to finalize + return; + } + + String fqn = JAXXCompiler.getCanonicalName(object); + + String id = object.getId(); + + if (log.isDebugEnabled()) { + log.debug("finalize " + id); + } + + boolean override = object.isOverride(); + + if (override) { + + if (object.isOverrideType()) { + + // add a specialized getter, only if type has changed + + String methodName = object.getGetterName(); + + String type = object.getSimpleType(); + String body = "return (" + type + ") super." + methodName + "();"; + + if (log.isDebugEnabled()) { + log.debug("Add specialized getter " + methodName + " : " + body); + } + JavaMethod getter = JavaElementFactory.newMethod( + Modifier.PUBLIC, + fqn, + methodName, + body, + true + ); + javaFile.addMethod(getter); + } + } else { + + int access = id.startsWith("$") ? Modifier.PRIVATE : + Modifier.PROTECTED; + if (root.equals(object)) { + + // add the generic type if required + String type = className + root.getGenericTypes(); + + JavaField field = JavaElementFactory.newField(access, + type, + id, + false, + "this" + ); + + javaFile.addSimpleField(field); + } else { + + JavaField field = JavaElementFactory.newField(access, + fqn, + id, + override + ); + javaFile.addField(field, object.isJavaBean()); + } + } + + if (compiler.inlineCreation(object) || root.equals(object)) { + + // nothing more to do here + return; + } + + String code = getCreationCode(compiler, object); + + // tchemit 20100519 Do not add the method only if overriden and code is null + + if (code != null) { + + JavaMethod javaMethod = JavaElementFactory.newMethod( + Modifier.PROTECTED, + JAXXCompilerFinalizer.TYPE_VOID, + object.getCreationMethodName(), + code, + override + ); + javaFile.addMethod(javaMethod); + } + } + + @Override + public String getCreationCode(JAXXCompiler compiler, + CompiledObject object) throws CompilerException { + if (object instanceof ScriptInitializer) { + throw new IllegalStateException( + "A script initializer can not come in getCreationcode method!"); + } + String eol = JAXXCompiler.getLineSeparator(); + + StringBuilder result = new StringBuilder(); + StringBuilder init = new StringBuilder(); + + if (compiler.getRootObject().equals(object) || + compiler.inlineCreation(object)) { + result.append("// inline creation of ").append(object.getId()); + } + + if (object.isJavaBean() && object.getJavaBeanInitCode() != null) { + init.append(object.getJavaBeanInitCode()); + } else if (object.getInitializer() != null) { + init.append(object.getInitializer()); + } + + boolean addToObjectMap = true; + String id = TypeManager.getJavaCode(object.getId()); + String constructorParams = object.getConstructorParams(); + + if (object.isOverride()) { + + if (init.length() == 0 && constructorParams == null) { + + // no init code is given, no need to add to objectMap + addToObjectMap = false; + } + } + + if (addToObjectMap && init.length() == 0) { + + // on special init, use constructor + String canonicalName = JAXXCompiler.getCanonicalName(object); + String impl = compiler.getImportedType(canonicalName); + + init.append("new ").append(impl).append("("); + + if (constructorParams != null) { + init.append(constructorParams); + } + init.append(")"); + } + + String superCall = "super." + object.getCreationMethodName() + "();"; + + if (addToObjectMap) { + result.append(eol); + result.append("$objectMap.put("); + result.append(id); + result.append(", "); + result.append(object.getId()).append(" = "); + result.append(init); + result.append(");"); + result.append(eol); + } else { + if (object.isOverride()) { + + // when override has no special init code, just use the super method + + result.append(superCall); + + } + } + + String initCode = object.getInitializationCode(compiler); + if (StringUtils.isNotEmpty(initCode)) { + result.append(eol).append(initCode); + } + + // add client properties + addClientProperties(object, result, eol); + + String code = result.toString(); + + if (!compiler.inlineCreation(object) && + object.isOverride() && + superCall.equals(code.trim())) { + + // special case : when override but do nothing more + // method creation can be skipped + return null; + } + return code; + } + + @Override + public String createCompleteSetupMethod(JAXXCompiler compiler, + CompiledObject object, + JavaFile javaFile) { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + if (object.getId().startsWith("$")) { + String additionCode = object.getAdditionCode(); + //TC-20091025 only generate the code if not empty + if (!additionCode.isEmpty()) { + code.append("// inline complete setup of "); + code.append(object.getId()); + code.append(eol); + code.append(additionCode); + } + } else { + //TODO-TC-20091202 should always create the method to make api more consistent ? + //TODO-TC-20091202 While generating, we deal with this case, it seems not sa natural + //TODO-TC-20091202 to NOT having the setup method on each public property ? +// code.append(object.getAdditionMethodName()).append("();").append(eol); +// if (!additionCode.isEmpty()) { +// additionCode = "if (!allComponentsCreated) {" + eol + " return;" + eol + "}" + eol + additionCode; +// } +// javaFile.addMethod(JavaFileGenerator.newMethod(Modifier.PROTECTED, "void", object.getAdditionMethodName(), additionCode, false)); + String additionCode = object.getAdditionCode(); + if (additionCode.length() > 0) { + code.append(object.getAdditionMethodName()).append("();").append(eol); + additionCode = "if (!allComponentsCreated) {" + eol + + " return;" + eol + "}" + eol + additionCode; + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PROTECTED, + JAXXCompilerFinalizer.TYPE_VOID, + object.getAdditionMethodName(), + additionCode, + false) + ); + } + } + String result = code.toString(); + return result; + } + + @Override + public boolean createInitializer(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + StringBuilder code, + boolean lastWasMethodCall) { + String eol = JAXXCompiler.getLineSeparator(); + + if (object instanceof ScriptInitializer) { + + // initializer has special direct treatment : can not be in a method + // just push code to compiler + code.append(object.getInitializationCode(compiler)); + + // nothing to initialize of a script + return lastWasMethodCall; + } + + if (root.equals(object)) { + String rootCode = root.getInitializationCode(compiler); + if (rootCode != null && rootCode.length() > 0) { + code.append("// inline creation of "); + code.append(object.getId()); + code.append(eol); + code.append(rootCode); + //TC-20091025 generate client properties at creation time (not at setup time) + // in some case can save to create a setup method (when there is only client properties + // to store) + addClientProperties(object, code, eol); + code.append(eol); + } + } else { + if (!object.isOverride()) { + if (compiler.inlineCreation(object)) { + if (lastWasMethodCall) { + lastWasMethodCall = false; + } + code.append(getCreationCode(compiler, object)); + } else { + code.append(object.getCreationMethodName()).append("();"); + code.append(eol); + lastWasMethodCall = true; + } + } + } + return lastWasMethodCall; + } + + protected void addClientProperties(CompiledObject object, + StringBuilder code, + String eol) { + //TC-20090327 generate client properties + if (object.hasClientProperties()) { + // generate putClientProperty invocations + for (Entry<String, String> entry : + object.getClientProperties().entrySet()) { + code.append(object.getJavaCode()); + code.append(".putClientProperty(\""); + code.append(entry.getKey()); + code.append("\", "); + code.append(entry.getValue()); + code.append(");"); + code.append(eol); + } + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java new file mode 100644 index 0000000..83f3d0d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/decorators/HelpRootCompiledObjectDecorator.java @@ -0,0 +1,226 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.decorators; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompiledObjectDecorator; +import jaxx.compiler.CompilerConfiguration; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.runtime.swing.help.JAXXHelpUI; + +import java.awt.Component; +import java.lang.reflect.Modifier; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import static jaxx.compiler.java.JavaElementFactory.newArgument; + +/** + * A decorator to place on a root compiled object to process javaHelp on the file. + * + * @author tchemit <chemit@codelutin.com> + * @plexus.component role-hint="help" role="jaxx.compiler.CompiledObjectDecorator" + * @since 1.2 + */ +public class HelpRootCompiledObjectDecorator extends DefaultCompiledObjectDecorator { + + /** the list of discovered helpId */ + protected static Set<String> helpIds = new HashSet<String>(); + + @Override + public String getName() { + return "help"; + } + + protected String getBrokerFQN(JAXXCompiler compiler) { + String helpBrokerFQN = compiler.getConfiguration().getHelpBrokerFQN(); + return helpBrokerFQN; + } + + protected String getHelpId(CompiledObject o) { + String helpID = null; + if (o.hasClientProperties()) { + helpID = o.getClientProperty("help"); + } + return helpID; + } + + @Override + public void finalizeCompiler(JAXXCompiler compiler, + CompiledObject root, + CompiledObject object, + JavaFile javaFile, + String packageName, + String className, + String fullClassName) throws ClassNotFoundException { + super.finalizeCompiler(compiler, + root, + object, + javaFile, + packageName, + className, + fullClassName) + ; + CompilerConfiguration options = compiler.getConfiguration(); + + if (options.isGenerateHelp()) { + + // add JAXXHelpUI interface + Class<?> validatorInterface = JAXXHelpUI.class; + String helpBrokerFQN = getBrokerFQN(compiler); + + boolean needInterface = isNeedInterface(compiler, + validatorInterface); + + if (needInterface) { + + // only add the contract if needed + + if (log.isDebugEnabled()) { + log.debug("Add " + validatorInterface + " on " + + javaFile.getName() + " : parent " + + JAXXCompiler.getCanonicalName( + compiler.getRootObject())); + } + + javaFile.addInterface(validatorInterface.getName() + + "<" + helpBrokerFQN + ">"); + } + + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + "registerHelpId", + "broker.installUI(component, helpId);", + true, + newArgument(helpBrokerFQN, "broker"), + newArgument(Component.class.getName(), "component"), + newArgument(JAXXCompilerFinalizer.TYPE_STRING, "helpId")) + ); + + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + "showHelp", + "getBroker().showHelp(this, helpId);", + true, + newArgument(JAXXCompilerFinalizer.TYPE_STRING, "helpId")) + ); + + StringBuilder buffer = new StringBuilder(); + + String eol = JAXXCompiler.getLineSeparator(); + +// if (options.isGenerateHelp()) { + + // add code to init javax help system + Iterator<CompiledObject> itr = compiler.getObjectCreationOrder(); + + for (; itr.hasNext();) { + CompiledObject o = itr.next(); + String helpID = getHelpId(o); + if (helpID != null) { + buffer.append(eol); + // detects a helpId to register + buffer.append("registerHelpId(_broker, "); + buffer.append(o.getJavaCode()); + buffer.append(", "); + buffer.append(helpID); + buffer.append(");"); + //keep the helpID for helpSet generation + helpIds.add(helpID); + } + } +// } + if (buffer.length() > 0) { + + String type = compiler.getImportedType(helpBrokerFQN); + StringBuilder extraCode = new StringBuilder(type); + extraCode.append(" _broker = getBroker();"); + + buffer.append(eol).append("_broker.prepareUI(this);"); + buffer.append(eol); + + // add the calls + compiler.appendLateInitializer("// help broker setup" + eol); + compiler.appendLateInitializer(extraCode.toString()); + compiler.appendLateInitializer(buffer.toString()); + } + } + } + + /** + * Detects if the given {@code compiler} need the validatorInterface. + * <p/> + * We need to test it deeply since the interface is added by the decorator + * and is not present on the symbol table of compiled objects. + * + * @param compiler the compiler to test + * @param validatorInterface the validator interface to seek for + * @return {@code true} if we need to add the interface, {@code false} otherwise + * @throws ClassNotFoundException if could not find a class + * @since 2.4 + */ + protected boolean isNeedInterface(JAXXCompiler compiler, + Class<?> validatorInterface) throws ClassNotFoundException { + if (compiler.isSuperClassAware(validatorInterface)) { + + // parent has already the interface + return false; + } + CompiledObject root = compiler.getRootObject(); + ClassDescriptor rootObjectClass = root.getObjectClass(); + String superClassName = JAXXCompiler.getCanonicalName(rootObjectClass); + JAXXCompiler parentCompiler = compiler.getEngine().getJAXXCompiler(superClassName); + if (parentCompiler == null) { + + // parent was not compiled + return true; + } + + CompiledObjectDecorator decorator = parentCompiler.getRootObject().getDecorator(); + + if (decorator != null && decorator instanceof HelpRootCompiledObjectDecorator) { + + // parent is already with help, no need of the interface + return false; + } + + boolean superClassResult = isNeedInterface(parentCompiler, validatorInterface); + + // ok must add the interface + return superClassResult; + } + + public static Set<String> getHelpIds() { + return new HashSet<String>(helpIds); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/AbstractFinalizer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/AbstractFinalizer.java new file mode 100644 index 0000000..1a40efb --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/AbstractFinalizer.java @@ -0,0 +1,90 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.finalizers; + +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaField; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.java.JavaMethod; + +/** + * Base implementation of a {@link JAXXCompilerFinalizer}. + * <p/> + * Contains commons methods and constants. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4 + */ +public abstract class AbstractFinalizer implements JAXXCompilerFinalizer { + + /** + * Clones the given {@code field} and adds it to the {@code file} as a + * property via the method {@link JavaFile#addField(JavaField)}. + * + * @param file the file where to add the cloned field + * @param field the field to clone + * @since 2.4 + */ + protected void addField(JavaFile file, JavaField field) { + + JavaField clonedField = JavaElementFactory.cloneField(field); + file.addField(clonedField); + } + + /** + * Clones the given {@code method} and adds it to the {@code file} as a + * simple method using the method {@link JavaFile#addMethod(JavaMethod)}. + * + * @param file the file where to add the cloned field + * @param field the field to clone + * @since 2.4 + */ + protected void addSimpleField(JavaFile file, JavaField field) { + + JavaField clonedField = JavaElementFactory.cloneField(field); + file.addSimpleField(clonedField); + } + + /** + * Clones the given {@code field} and adds it to the {@code file} as a + * simple field using the method {@link JavaFile#addSimpleField(JavaField)}. + * + * @param file the file where to add the cloned method + * @param method the method to clone + * @param types optional types to use to simplify the body of the method + * @since 2.4 + */ + protected void addMethod(JavaFile file, JavaMethod method, String... types) { + + JavaMethod clonedMethod = JavaElementFactory.cloneMethod(method); + if (types.length > 0) { + String body = clonedMethod.getBody(); + String simplifiedBody = file.simplifyCode(body, types); + clonedMethod.setBody(simplifiedBody); + } + file.addMethod(clonedMethod); + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java new file mode 100644 index 0000000..614e859 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/DefaultFinalizer.java @@ -0,0 +1,1301 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.finalizers; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompiledObjectDecorator; +import jaxx.compiler.CompilerException; +import jaxx.compiler.EventHandler; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.binding.DataBinding; +import jaxx.compiler.binding.writers.DefaultJAXXBindingWriter; +import jaxx.compiler.binding.writers.JAXXBindingWriter; +import jaxx.compiler.binding.writers.SimpleJAXXObjectBindingWriter; +import jaxx.compiler.java.JavaArgument; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaField; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.java.JavaMethod; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.Base64Coder; +import jaxx.runtime.JAXXBinding; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.SwingUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Container; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import static java.lang.reflect.Modifier.FINAL; +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; +import static java.lang.reflect.Modifier.isProtected; +import static java.lang.reflect.Modifier.isPublic; +import static jaxx.compiler.java.JavaElementFactory.newArgument; +import static jaxx.compiler.java.JavaElementFactory.newField; +import static jaxx.compiler.java.JavaElementFactory.newMethod; + +/** + * This class is a refactoring of the {@link JAXXCompiler}. + * <p/> + * We delegate now the generation of a {@link JAXXObject} to this class, the + * {@link JAXXCompiler} now only deals with the compilation of files. + * + * @author tchemit <chemit@codelutin.com> + * @plexus.component role-hint="default" role="jaxx.compiler.finalizers.JAXXCompilerFinalizer" + */ +public class DefaultFinalizer extends AbstractFinalizer { + + /** Logger. */ + protected static final Log log = LogFactory.getLog(DefaultFinalizer.class); + + private static final String PARAMETER_NAME_$BINDING = "$binding"; + + public static final String FIELD_NAME_$BINDING_SOURCES = "$bindingSources"; + + public static final String FIELD_NAME_$OBJECT_MAP = "$objectMap"; + + public static final String FIELD_NAME_$ACTIVE_BINDINGS = "$activeBindings"; + + public static final String FIELD_NAME_ALL_COMPONENTS_CREATED = "allComponentsCreated"; + + public static final String FIELD_NAME_CONTEXT_INITIALIZED = "contextInitialized"; + + public static final String FIELD_NAME_$PREVIOUS_VALUES = "$previousValues"; + + public static final String FIELD_NAME_$BINDINGS = "$bindings"; + + public static final String FIELD_NAME_$PROPERTY_CHANGE_SUPPORT = "$propertyChangeSupport"; + + public static final String FIELD_NAME_DELEGATE_CONTEXT = "delegateContext"; + + public static final String FIELD_NAME_SERIAL_VERSION_UID = "serialVersionUID"; + + public static final String FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR = "$jaxxObjectDescriptor"; + + public static final String METHOD_NAME_$GET_JAXXOBJECT_DESCRIPTOR = "$getJAXXObjectDescriptor"; + + public static final String METHOD_NAME_$REGISTER_DEFAULT_BINDINGS = "$registerDefaultBindings"; + + public static final String METHOD_NAME_REGISTER_DATA_BINDING = "registerDataBinding"; + + public static final String METHOD_NAME_REMOVE_DATA_BINDING = "removeDataBinding"; + + public static final String METHOD_NAME_APPLY_DATA_BINDING = "applyDataBinding"; + + public static final String METHOD_NAME_PROCESS_DATA_BINDING = "processDataBinding"; + + public static final String METHOD_NAME_FIRE_PROPERTY_CHANGE = "firePropertyChange"; + + public static final String METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT = "$getPropertyChangeSupport"; + + public static final String METHOD_NAME_$INITIALIZE = "$initialize"; + + public static final String METHOD_NAME_$COMPLETE_SETUP = "$completeSetup"; + + public static final String METHOD_NAME_$AFTER_COMPLETE_SETUP = "$afterCompleteSetup"; + + /** serialVersionUID field */ + + protected static final JavaField SERIAL_VERSION_UID_FIELD = newField( + PRIVATE | STATIC | FINAL, + "long", + FIELD_NAME_SERIAL_VERSION_UID, + false, + "1L" + ); + + /** + * + */ + protected static final JavaField ACTIVE_BINDINGS_FIELD = newField( + PROTECTED, + List.class.getName() + "<" + TYPE_OBJECT + ">", + FIELD_NAME_$ACTIVE_BINDINGS, + false, + "new %s<" + TYPE_OBJECT + ">()", + ArrayList.class.getName() + ); + + /** + * + */ + protected static final JavaField BINDING_SOURCES_FIELD = newField( + PROTECTED, + Map.class.getName() + "<" + TYPE_STRING + ", " + TYPE_OBJECT + ">", + FIELD_NAME_$BINDING_SOURCES, + false, + "new %s<" + TYPE_STRING + ", " + TYPE_OBJECT + ">()", + HashMap.class.getName() + ); + + /** + * + */ + protected static final JavaField OBJECT_MAP_FIELD = newField( + PROTECTED, + Map.class.getName() + "<" + TYPE_STRING + ", " + TYPE_OBJECT + ">", + FIELD_NAME_$OBJECT_MAP, + true, + "new %s<" + TYPE_STRING + ", " + TYPE_OBJECT + ">()", + HashMap.class.getName() + ); + + /** + * + */ + protected static final JavaField ALL_COMPONENTS_CREATED_FIELD = newField( + PRIVATE, + TYPE_BOOLEAN, + FIELD_NAME_ALL_COMPONENTS_CREATED, + false + ); + + /** + * + */ + protected static final JavaField CONTEXT_INITIALIZED = newField( + PRIVATE, + TYPE_BOOLEAN, + FIELD_NAME_CONTEXT_INITIALIZED, + false, + "true" + ); + + /** + * + */ + protected static final JavaField PREVIOUS_VALUES_FIELD = newField( + PROTECTED, + Map.class.getName() + "<?,?>", FIELD_NAME_$PREVIOUS_VALUES, + false, + "new %s<" + TYPE_OBJECT + ", " + TYPE_OBJECT + ">()", + HashMap.class.getName() + ); + + /** + * + */ + protected static final JavaField BINDINGS_FIELD = newField( + PROTECTED | FINAL, + Map.class.getName() + "<" + TYPE_STRING + ", " + JAXXBinding.class.getName() + ">", + FIELD_NAME_$BINDINGS, + false, + "new %s<" + TYPE_STRING + ", %s>()", + TreeMap.class.getName(), + JAXXBinding.class.getName() + ); + + /** + * + */ + protected static final JavaField PROPERTY_CHANGE_SUPPORT_FIELD = newField( + PROTECTED, + PropertyChangeSupport.class.getName(), + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT, + false + ); + + /** + * + */ + protected static final JavaMethod GET_CONTEXT_VALUE_METHOD = newMethod( + PUBLIC, + "<T> T", + "getContextValue", + "return " + FIELD_NAME_DELEGATE_CONTEXT + ".getContextValue(clazz, null);", + true, + newArgument("Class<T>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_CONTEXT_VALUE_NAMED_METHOD = newMethod( + PUBLIC, + "<T> T", + "getContextValue", + "return " + FIELD_NAME_DELEGATE_CONTEXT + ".getContextValue(clazz, name);", + true, + newArgument("Class<T>", "clazz"), newArgument(TYPE_STRING, "name") + ); + + /** + * + */ + protected static final JavaMethod SET_CONTEXT_VALUE_NAMED_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "setContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".setContextValue(o, name);", + true, + newArgument("T", "o"), newArgument(TYPE_STRING, "name")); + + /** + * + */ + protected static final JavaMethod SET_CONTEXT_VALUE_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "setContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".setContextValue(o, null);", + true, + newArgument("T", "o") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_CONTEXT_VALUE_NAMED_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "removeContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".removeContextValue(clazz, name);", + true, + newArgument("Class<T>", "clazz"), + newArgument(TYPE_STRING, "name") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_CONTEXT_VALUE_METHOD = newMethod( + PUBLIC, + "<T> " + TYPE_VOID, + "removeContextValue", + FIELD_NAME_DELEGATE_CONTEXT + ".removeContextValue(clazz, null);", + true, + newArgument("Class<T>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_PARENT_CONTAINER_MORE_METHOD = newMethod( + PUBLIC, + "<O extends Container> O", + "getParentContainer", + "return %s.getParentContainer(source, clazz);", + true, + newArgument(TYPE_OBJECT, "source"), + newArgument("Class<O>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_PARENT_CONTAINER_METHOD = newMethod( + PUBLIC, + "<O extends Container> O", + "getParentContainer", + "return %s.getParentContainer(this, clazz);", + true, + newArgument("Class<O>", "clazz") + ); + + /** + * + */ + protected static final JavaMethod GET_OBJECT_BY_ID_METHOD = newMethod( + PUBLIC, TYPE_OBJECT, "getObjectById", + "return " + FIELD_NAME_$OBJECT_MAP + ".get(id);", + true, + newArgument(TYPE_STRING, "id") + ); + + /** + * + */ + protected static final JavaMethod GET_JAXX_OBJECT_DESCRIPTOR_METHOD = newMethod( + PUBLIC | STATIC, + JAXXObjectDescriptor.class.getName(), + METHOD_NAME_$GET_JAXXOBJECT_DESCRIPTOR, + "return %s.decodeCompressedJAXXObjectDescriptor(" + + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR + ");", + false + ); + + /** + * + */ + protected static final JavaMethod PROCESS_DATA_BINDING_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_PROCESS_DATA_BINDING, + METHOD_NAME_PROCESS_DATA_BINDING + "(" + PARAMETER_NAME_$BINDING + ", false);", + true, + newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) + ); + + /** + * + */ + protected static final JavaMethod REGISTER_DATA_BINDING_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_REGISTER_DATA_BINDING, + FIELD_NAME_$BINDINGS + ".put(binding.getId(), binding);", + true, + newArgument(JAXXBinding.class.getName(), "binding") + ); + + /** + * + */ + protected static final JavaMethod GET_DATA_BINDINGS_METHOD = newMethod( + PUBLIC, + JAXXBinding.class.getName() + "[]", + "getDataBindings", + "return " + FIELD_NAME_$BINDINGS + ".values().toArray(new %s[" + FIELD_NAME_$BINDINGS + ".size()]);", + true + ); + + /** + * + */ + protected static final JavaMethod GET_DATA_BINDING_METHOD = newMethod( + PUBLIC, + JAXXBinding.class.getName(), + "getDataBinding", + "return " + FIELD_NAME_$BINDINGS + ".get(bindingId);", + true, + newArgument(TYPE_STRING, "bindingId") + ); + + + /** + * + */ + protected static final JavaMethod FIRE_PROPERTY_CHANGE_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_FIRE_PROPERTY_CHANGE, + "super." + METHOD_NAME_FIRE_PROPERTY_CHANGE + "(propertyName, oldValue, newValue);", + true, + newArgument(TYPE_STRING, "propertyName"), + newArgument(TYPE_OBJECT, "oldValue"), + newArgument(TYPE_OBJECT, "newValue") + ); + + /** + * + */ + protected static final JavaMethod FIRE_PROPERTY_CHANGE_NAMED_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_FIRE_PROPERTY_CHANGE, + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "()." + METHOD_NAME_FIRE_PROPERTY_CHANGE + "(propertyName, oldValue, newValue);", + true, + newArgument(TYPE_STRING, "propertyName"), + newArgument(TYPE_OBJECT, "oldValue"), + newArgument(TYPE_OBJECT, "newValue") + ); + + /** + * + */ + protected static final JavaMethod GET_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( + 0, + PropertyChangeSupport.class.getName(), + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT, + "if (" + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + " == null)\n" + + " " + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + " = new PropertyChangeSupport(this);\n" + + "return " + FIELD_NAME_$PROPERTY_CHANGE_SUPPORT + ";", + false + ); + + /** + * + */ + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "addPropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().addPropertyChangeListener(listener);", + true, + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + /** + * + */ + protected static final JavaMethod ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "addPropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().addPropertyChangeListener(property, listener);", + true, + newArgument(TYPE_STRING, "property"), + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "removePropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().removePropertyChangeListener(listener);", + true, + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + /** + * + */ + protected static final JavaMethod REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD = newMethod( + PUBLIC, + TYPE_VOID, + "removePropertyChangeListener", + METHOD_NAME_$GET_PROPERTY_CHANGE_SUPPORT + "().removePropertyChangeListener(property, listener);", + true, + newArgument(TYPE_STRING, "property"), + newArgument(PropertyChangeListener.class.getName(), "listener") + ); + + private static final String PARAMETER_NAME_PARENT_CONTEXT = "parentContext"; + + + @Override + public boolean accept(JAXXCompiler compiler) { + + // alwyas use the default finalizer + return true; + } + + @Override + public void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + + String fullClassName = packageName != null ? + packageName + "." + className : className; + if (root == null) { + throw new CompilerException("root tag can not be null"); + } + ClassDescriptor superclass = root.getObjectClass(); + boolean superclassIsJAXXObject = + compiler.isSuperClassAware(JAXXObject.class); + javaFile.setModifiers(PUBLIC); + javaFile.setName(fullClassName); + javaFile.setSimpleName(className); + + javaFile.setSuperClass(JAXXCompiler.getCanonicalName(superclass)); + javaFile.setSuperclassIsJAXXObject(superclassIsJAXXObject); + + javaFile.addInterface(compiler.getExtraInterfaces()); + javaFile.setAbstractClass(compiler.isAbstractClass()); + javaFile.setGenericType(compiler.getGenericType()); + javaFile.setSuperGenericType(compiler.getSuperGenericType()); + + if (!superclassIsJAXXObject) { + javaFile.addInterface(JAXXObject.class.getName()); + } + } + + @Override + public void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + + // add logger support if required + addLoggerSupport(compiler, javaFile, className); + + // add JAXXObject support if required + addJAXXObjectSupport(compiler, root, javaFile); + + addSimpleField(javaFile, SERIAL_VERSION_UID_FIELD); + addSimpleField(javaFile, ALL_COMPONENTS_CREATED_FIELD); + + addJAXXObjectDescriptorField(compiler, javaFile); + addMethod(javaFile, + GET_JAXX_OBJECT_DESCRIPTOR_METHOD, + JAXXUtil.class.getName() + ); + + addPreviousValuesField(compiler, javaFile, root); + +// addConstructors(compiler, javaFile, className); + + DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); + + addInitializerMethod(compiler, javaFile, bindings.length); + + javaFile.addBodyCode(compiler.getBodyCode().toString()); + + addDataBindings(compiler, javaFile, bindings); + + addCompleteSetupMethod(compiler, javaFile); + + addEventHandlers(compiler, javaFile); + } + + protected void addDataBindings(JAXXCompiler compiler, + JavaFile javaFile, + DataBinding[] bindings) { + + if (bindings.length < 1) { + // no data bindings + return; + } + + // create the $registerDefaultBindings method + + for (JAXXBindingWriter<?> writer : bindingWriters) { + writer.reset(); + } + addRegisteredDefaultBindingsMethod(compiler, javaFile); + + // add import on each type of JAXXBinding used + + for (JAXXBindingWriter<?> writer : bindingWriters) { + if (writer.isUsed()) { + compiler.getJavaFile().addImport(writer.getType()); + } + } + + // for each binding declare the constant Id + + for (DataBinding binding : bindings) { + + String constantId = binding.getConstantId(); + + // add the data binding constant Id + + compiler.addSimpleField(newField( + (constantId.startsWith("BINDING_$") ? PRIVATE : PUBLIC) | FINAL | STATIC, + TYPE_STRING, + constantId, + false, + TypeManager.getJavaCode(binding.getRealId())) + ); + } + } + + protected void addConstructors(JAXXCompiler compiler, + JavaFile javaFile, + String className) { + + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + + //TC 20090228 - only generate constructors if not done in scripts + boolean constructorDetected = false; + MethodDescriptor[] methods = compiler.getScriptMethods(); + for (MethodDescriptor m : methods) { + try { + m.getReturnType(); + if (className.equals(m.getName())) { + constructorDetected = true; + break; + } + } catch (Exception e) { + log.warn("could not find return type " + m); + } + } + if (!constructorDetected) { + + //creates default constructors + + JavaMethod constructor = createConstructor(compiler, + className, + superclassIsJAXXObject + ); + javaFile.addMethod(constructor); + constructor = createConstructorWithInitialContext( + compiler, + className, + superclassIsJAXXObject + ); + javaFile.addMethod(constructor); + } + } + + protected void addJAXXObjectSupport(JAXXCompiler compiler, + CompiledObject root, + JavaFile javaFile) { + + String jaxxContextImplementorClass = + compiler.getConfiguration().getJaxxContextClass().getName(); + + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + + if (superclassIsJAXXObject) { + + //FIXME tchemit 2011-01-30 : We should not add it (if user want to use it in script it must add the correct import + // Will be removed in version 3.0 with strict imports features + javaFile.addImport(JAXXContext.class); + + } else { + + // add JAXXObject support + addField(javaFile, OBJECT_MAP_FIELD); + addSimpleField(javaFile, BINDING_SOURCES_FIELD); + addSimpleField(javaFile, ACTIVE_BINDINGS_FIELD); + addSimpleField(javaFile, BINDINGS_FIELD); + javaFile.addMethod(GET_OBJECT_BY_ID_METHOD); + addMethod(javaFile, REGISTER_DATA_BINDING_METHOD); + addMethod(javaFile, GET_DATA_BINDINGS_METHOD, JAXXBinding.class.getSimpleName()); + addMethod(javaFile, GET_DATA_BINDING_METHOD, JAXXBinding.class.getSimpleName()); + + javaFile.addMethod(createApplyDataBindingMethod()); + javaFile.addMethod(createProcessDataBindingMethod()); + javaFile.addMethod(createRemoveDataBindingMethod()); + + // JAXXContext + + String type = + javaFile.getImportedType(jaxxContextImplementorClass); + + javaFile.addField(newField( + PROTECTED | FINAL, + JAXXContext.class.getName(), + FIELD_NAME_DELEGATE_CONTEXT, + true, + "new " + type + "()") + ); + + javaFile.addImport(Container.class); + + 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); + addMethod(javaFile, GET_PARENT_CONTAINER_METHOD, SwingUtil.class.getName()); + addMethod(javaFile, GET_PARENT_CONTAINER_MORE_METHOD, SwingUtil.class.getName()); +// javaFile.addMethod(GET_PARENT_CONTAINER_METHOD); +// javaFile.addMethod(GET_PARENT_CONTAINER_MORE_METHOD); + + // PropertyChangeSupport + addPropertyChangeSupport(root, javaFile); + + // DataBinding + javaFile.addMethod(PROCESS_DATA_BINDING_METHOD); + } + } + + protected void addLoggerSupport(JAXXCompiler compiler, JavaFile javaFile, String className) { + if (compiler.getConfiguration().isAddLogger()) { + +// javaFile.addImport(LogFactory.class); + + javaFile.addSimpleField(newField( + PRIVATE | STATIC | FINAL, + Log.class.getName(), + "log", + false, + "%s.getLog(" + className + ".class)", + LogFactory.class.getName() + ) + ); + } + } + + protected final JAXXBindingWriter<?>[] bindingWriters = new + JAXXBindingWriter[]{new SimpleJAXXObjectBindingWriter(), + new DefaultJAXXBindingWriter() + }; + + /*---------------------------------------------------------------------------------*/ + /*-- Create fields ----------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + protected JavaField addJAXXObjectDescriptorField(JAXXCompiler compiler, + JavaFile javaFile) { + JavaField field; + 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) { + field = newField(PRIVATE | STATIC | FINAL, + TYPE_STRING, + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, + false, + TypeManager.getJavaCode(data) + ); + + } else { + StringBuilder initializer = new StringBuilder(); + for (int i = 0; i < data.length(); i += sizeLimit) { + String name = FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR + i; + javaFile.addField(newField( + PRIVATE | STATIC, + TYPE_STRING, + name, + false, + TypeManager.getJavaCode(data.substring(i, Math.min(i + sizeLimit, data.length())))) + ); + if (initializer.length() > 0) { + initializer.append(" + "); + } + initializer.append(TYPE_STRING + ".valueOf("); + initializer.append(name); + initializer.append(")"); + } + field = newField(PRIVATE | STATIC | FINAL, + TYPE_STRING, + FIELD_NAME_$JAXX_OBJECT_DESCRIPTOR, + false, + initializer.toString() + ); + } + } catch (IOException e) { + throw new RuntimeException("Internal error: can't-happen error", e); + } + javaFile.addSimpleField(field); + return field; + } + + protected void addPreviousValuesField(JAXXCompiler compiler, + JavaFile javaFile, CompiledObject root) { + + boolean superclassIsJAXXObject = javaFile.isSuperclassIsJAXXObject(); + + if (compiler.getStylesheet() != null) { + boolean needField = true; + if (superclassIsJAXXObject) { + // check alreay exists on parent + ClassDescriptor superclass = root.getObjectClass(); + if (log.isDebugEnabled()) { + log.debug("superclass : " + superclass); + } + JAXXCompiler parentCompiler = + compiler.getEngine().getJAXXCompiler( + superclass.getName() + ); + + if (parentCompiler != null) { + needField = parentCompiler.getStylesheet() == null; + } else { + try { + superclass.getDeclaredFieldDescriptor( + PREVIOUS_VALUES_FIELD.getName()); + needField = false; + } catch (NoSuchFieldException ex) { + // field not found + } + } + if (needField && log.isDebugEnabled()) { + log.debug("no " + PREVIOUS_VALUES_FIELD.getName() + + " field in super class"); + } + } + if (needField) { + addSimpleField(javaFile, PREVIOUS_VALUES_FIELD); + } + } + } + + /*---------------------------------------------------------------------------------*/ + /*-- Create methods ---------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + protected void addPropertyChangeSupport(CompiledObject root, + JavaFile javaFile) { + ClassDescriptor currentClass = root.getObjectClass(); + MethodDescriptor firePropertyChange = null; + while (firePropertyChange == null && currentClass != null) { + try { + firePropertyChange = currentClass.getDeclaredMethodDescriptor( + METHOD_NAME_FIRE_PROPERTY_CHANGE, + ClassDescriptorHelper.getClassDescriptor(String.class), + ClassDescriptorHelper.getClassDescriptor(Object.class), + ClassDescriptorHelper.getClassDescriptor(Object.class) + ); + + } catch (NoSuchMethodException e) { + currentClass = currentClass.getSuperclass(); + } + } + + int modifiers = firePropertyChange != null ? + firePropertyChange.getModifiers() : 0; + if (isPublic(modifiers)) { + // we have all the support we need + return; + } + if (isProtected(modifiers)) { + + // there is property change support but the firePropertyChange method is protected + javaFile.addMethod(FIRE_PROPERTY_CHANGE_METHOD); + } else { + + addField(javaFile, PROPERTY_CHANGE_SUPPORT_FIELD); + addMethod(javaFile, GET_PROPERTY_CHANGE_SUPPORT_METHOD, + PropertyChangeSupport.class.getName()); + addMethod(javaFile, ADD_PROPERTY_CHANGE_SUPPORT_METHOD); + addMethod(javaFile, ADD_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + addMethod(javaFile, REMOVE_PROPERTY_CHANGE_SUPPORT_METHOD); + addMethod(javaFile, REMOVE_PROPERTY_CHANGE_SUPPORT_NAMED_METHOD); + addMethod(javaFile, FIRE_PROPERTY_CHANGE_NAMED_METHOD); + } + } + + protected JavaMethod addRegisteredDefaultBindingsMethod(JAXXCompiler compiler, + JavaFile javaFile) { + DataBinding[] bindings = compiler.getBindingHelper().getDataBindings(); + StringBuilder initCode = new StringBuilder(); + + String eol = JAXXCompiler.getLineSeparator(); + JavaFileGenerator generator = new JavaFileGenerator(eol, true); + //TODO use optimized writer for simple cases + + initCode.append("// register "); + initCode.append(bindings.length); + initCode.append(" data bindings"); + initCode.append(eol); + + for (DataBinding binding : bindings) { + + for (JAXXBindingWriter<?> writer : bindingWriters) { + if (writer.accept(binding)) { + writer.write(binding, generator, initCode); + break; + } + } + } + JavaMethod method = newMethod(PRIVATE, + TYPE_VOID, + METHOD_NAME_$REGISTER_DEFAULT_BINDINGS, + initCode.toString(), + false + ); + javaFile.addMethod(method); + return method; + } + + protected void addEventHandlers(JAXXCompiler compiler, + 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" + ); + } + + ClassDescriptor eventType = + listenerMethod.getParameterTypes()[0]; + + JavaArgument argument = + JavaElementFactory.newArgument( + JAXXCompiler.getCanonicalName(eventType), + "event" + ); + + String body = JavaFileGenerator.addDebugLoggerInvocation(compiler, "event"); + body += handler.getJavaCode(); + javaFile.addMethod(JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + methodName, + body, + false, + argument) + ); + } + } + } + } + + protected JavaMethod createConstructor(JAXXCompiler compiler, + String className, + boolean superclassIsJAXXObject) throws CompilerException { + StringBuilder code = new StringBuilder(); + String constructorParams = compiler.getRootObject().getConstructorParams(); + String eol = JAXXCompiler.getLineSeparator(); + if (constructorParams != null) { + code.append(" super("); + code.append(constructorParams); + code.append(");"); + code.append(eol); + } else { +// if (superclassIsJAXXObject) { +// code.append(" super();").append(eol); +// } + } + code.append(METHOD_NAME_$INITIALIZE + "();"); + code.append(eol); + return JavaElementFactory.newMethod(PUBLIC, + null, + className, + code.toString(), + false + ); + } + + protected JavaMethod createConstructorWithInitialContext(JAXXCompiler compiler, + String className, + boolean superclassIsJAXXObject) throws CompilerException { + StringBuilder code = new StringBuilder(); + String constructorParams = compiler.getRootObject().getConstructorParams(); + String eol = JAXXCompiler.getLineSeparator(); + String realConstructorParams = ""; + if (superclassIsJAXXObject) { + realConstructorParams = PARAMETER_NAME_PARENT_CONTEXT; + } + if (constructorParams != null) { + + if (superclassIsJAXXObject) { + realConstructorParams += " ,"; + } + realConstructorParams += constructorParams; + } + + realConstructorParams = realConstructorParams.trim(); + + if (StringUtils.isNotEmpty(realConstructorParams)) { + + // add a super invocation + code.append(" super("); + code.append(realConstructorParams); + code.append(");"); + code.append(eol); + } + + +// if (constructorParams != null) { +// if (superclassIsJAXXObject) { +// //TODO-TC20091127 This MUST be a convention in JAXX : all specialized constructor must a second +// //TODO constructor with extra first parameter as parentContext +// constructorParams = PARAMETER_NAME_PARENT_CONTEXT + ", " + constructorParams; +// } +// code.append(" super("); +// code.append(constructorParams); +// code.append(");"); +// code.append(eol); +// } else { +// if (superclassIsJAXXObject) { +// code.append(" super(" + PARAMETER_NAME_PARENT_CONTEXT); +// code.append(");"); +// code.append(eol); +// } +// } + if (!superclassIsJAXXObject) { + String prefix = compiler.getImportedType(JAXXUtil.class); + code.append(prefix); + code.append(".initContext(this, " + PARAMETER_NAME_PARENT_CONTEXT + ");"); + code.append(eol); + } + code.append(METHOD_NAME_$INITIALIZE + "();"); + code.append(eol); + JavaArgument argument = JavaElementFactory.newArgument( + JAXXContext.class.getName(), + PARAMETER_NAME_PARENT_CONTEXT + ); + return JavaElementFactory.newMethod(PUBLIC, + null, + className, + code.toString(), + false, + argument + ); + } + + public JavaMethod addInitializerMethod(JAXXCompiler compiler, + JavaFile javaFile, + int nbBindings) throws CompilerException { + + boolean overrideContextInitialized = + compiler.containsScriptField(FIELD_NAME_CONTEXT_INITIALIZED); + + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder code = new StringBuilder(); + CompiledObject root = compiler.getRootObject(); + code.append("if (" + FIELD_NAME_ALL_COMPONENTS_CREATED); + if (overrideContextInitialized) { + code.append("|| !" + FIELD_NAME_CONTEXT_INITIALIZED); + } + code.append(") {"); + code.append(eol); + code.append(" return;").append(eol); + code.append("}").append(eol); + code.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + + code.append(FIELD_NAME_$OBJECT_MAP + ".put("); + String rootId = root.getId(); + code.append(TypeManager.getJavaCode(rootId)); +// code.append(", this);"); + code.append(", ").append(rootId).append(");").append(eol); + + Iterator<CompiledObject> i = compiler.getObjectCreationOrder(); + boolean lastWasMethodCall = false; + //TODO-TC20091025 should do init of root first ? +// root.getDecorator().createInitializer(compiler, root, root, code, lastWasMethodCall); + while (i.hasNext()) { + CompiledObject object = i.next(); + if (object == root) { + continue; + } + CompiledObjectDecorator decorator = object.getDecorator(); + lastWasMethodCall = decorator.createInitializer(compiler, + root, + object, + code, + lastWasMethodCall + ); + } + root.getDecorator().createInitializer(compiler, + root, + root, + code, + lastWasMethodCall + ); + if (compiler.getInitializer().length() > 0) { + code.append(compiler.getInitializer()); + } + // register bindings before anything else + if (nbBindings > 0) { + // ajout invocation a la methode d'enregistrement des bindings + code.append("// registers "); + code.append(nbBindings); + code.append(" data bindings"); + code.append(eol); + code.append(METHOD_NAME_$REGISTER_DEFAULT_BINDINGS + "();"); + code.append(eol); + } + code.append(METHOD_NAME_$COMPLETE_SETUP + "();"); + code.append(eol); + JavaMethod method = JavaElementFactory.newMethod(PRIVATE, + TYPE_VOID, + METHOD_NAME_$INITIALIZE, + code.toString(), + false + ); + javaFile.addMethod(method); + return method; + } + + protected JavaMethod addCompleteSetupMethod(JAXXCompiler compiler, + JavaFile javaFile) { + StringBuilder code = new StringBuilder(); + code.append(FIELD_NAME_ALL_COMPONENTS_CREATED + " = true;"); + String eol = JAXXCompiler.getLineSeparator(); + code.append(eol); + code.append(JavaFileGenerator.addDebugLoggerInvocation(compiler, "this")); + for (CompiledObject object : compiler.getObjects().values()) { + CompiledObjectDecorator decorator = object.getDecorator(); + code.append(decorator.createCompleteSetupMethod(compiler, + object, + javaFile) + ); + } + String simpleBindingsCode = createInitBindingsCode(compiler); + if (simpleBindingsCode != null && !simpleBindingsCode.isEmpty()) { + code.append(simpleBindingsCode).append(eol); + } + + if (compiler.getLateInitializer().length() > 0) { + code.append("// late initializer").append(eol); + code.append(compiler.getLateInitializer()).append(eol); + } + //TC-20090313 add an extra method after complete setup + MethodDescriptor method = + compiler.getScriptMethod(METHOD_NAME_$AFTER_COMPLETE_SETUP); + if (method != null) { + code.append(METHOD_NAME_$AFTER_COMPLETE_SETUP + "();").append(eol); + } + JavaMethod javaMethod = JavaElementFactory.newMethod(PRIVATE, + TYPE_VOID, + METHOD_NAME_$COMPLETE_SETUP, + code.toString(), + false + ); + javaFile.addMethod(javaMethod); + return javaMethod; + } + + protected String createInitBindingsCode(JAXXCompiler compiler) { + String eol = JAXXCompiler.getLineSeparator(); + DataBinding[] bindings; + + StringBuilder result = new StringBuilder(); + + bindings = compiler.getBindingHelper().getDataBindings(); + if (bindings.length > 0) { + + result.append(eol); + result.append("// apply "); + result.append(bindings.length); + result.append(" data bindings"); + result.append(eol); + result.append(JAXXUtil.class.getSimpleName()); + result.append("." + METHOD_NAME_APPLY_DATA_BINDING + "(this, " + FIELD_NAME_$BINDINGS + ".keySet());"); + result.append(eol); + + } + bindings = compiler.getBindingHelper().getSimpleBindings(); + if (bindings.length > 0) { + + StringBuilder initCode = new StringBuilder(); + + for (DataBinding binding : bindings) { + + String binding1 = binding.getInitDataBinding(); + if (binding1 != null && !binding1.trim().isEmpty()) { + initCode.append(binding1); + } + } + + if (initCode.length() > 0) { + + result.append(eol); + result.append("// apply "); + result.append(bindings.length); + result.append(" property setters"); + result.append(eol); + result.append(initCode.toString().trim()); + + } + } + return result.toString(); + } + + protected JavaMethod createApplyDataBindingMethod() { + StringBuilder buffer = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + buffer.append("if (" + FIELD_NAME_ALL_COMPONENTS_CREATED + " && " + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); + buffer.append(eol); + buffer.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_APPLY_DATA_BINDING + "();"); + buffer.append(eol); + buffer.append("}"); + buffer.append(eol); + buffer.append(METHOD_NAME_PROCESS_DATA_BINDING + "(" + PARAMETER_NAME_$BINDING + ");"); + return JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_APPLY_DATA_BINDING, + buffer.toString(), + true, + JavaElementFactory.newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) + ); + } + + protected JavaMethod createRemoveDataBindingMethod() { + StringBuilder buffer = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + buffer.append("if (" + FIELD_NAME_ALL_COMPONENTS_CREATED + " && " + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); + buffer.append(eol); + buffer.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_REMOVE_DATA_BINDING + "();"); + buffer.append(eol); + buffer.append("}"); + return JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_REMOVE_DATA_BINDING, + buffer.toString(), + true, + JavaElementFactory.newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING) + ); + } + + protected JavaMethod createProcessDataBindingMethod() { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + // 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 + + code.append(" if (!$force && " + FIELD_NAME_$ACTIVE_BINDINGS + ".contains(" + PARAMETER_NAME_$BINDING + ")) { "); + code.append(eol); + code.append(" return;"); + code.append(eol); + code.append("}").append(eol); + code.append(FIELD_NAME_$ACTIVE_BINDINGS + ".add(" + PARAMETER_NAME_$BINDING + ");"); + code.append(eol); + code.append("try {").append(eol); + code.append(" if (" + FIELD_NAME_ALL_COMPONENTS_CREATED + " && " + FIELD_NAME_$BINDINGS + ".containsKey(" + PARAMETER_NAME_$BINDING + ")) {"); + code.append(eol); + code.append(" getDataBinding(" + PARAMETER_NAME_$BINDING + ")." + METHOD_NAME_PROCESS_DATA_BINDING + "();"); + code.append(eol); + code.append(" }").append(eol); + code.append("} finally {").append(eol); + code.append(" " + FIELD_NAME_$ACTIVE_BINDINGS + ".remove(" + PARAMETER_NAME_$BINDING + ");"); + code.append(eol); + code.append("}").append(eol); + return JavaElementFactory.newMethod( + PUBLIC, + TYPE_VOID, + METHOD_NAME_PROCESS_DATA_BINDING, + code.toString(), + true, + newArgument(TYPE_STRING, PARAMETER_NAME_$BINDING), + newArgument(TYPE_BOOLEAN, "$force") + ); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java new file mode 100644 index 0000000..e7a5897 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/JAXXCompilerFinalizer.java @@ -0,0 +1,90 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.finalizers; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaFile; + +/** + * Contract of any object to interact with a {@link JAXXCompiler} before the + * generation pass. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public interface JAXXCompilerFinalizer { + + String TYPE_STRING = "String"; + + String TYPE_VOID = "void"; + + String TYPE_BOOLEAN = "boolean"; + + String TYPE_OBJECT = "Object"; + + /** + * Test if the finalizer must be apply on the given {@code compiler}. + * + * @param compiler the compiler + * @return {@code true} if the finalizer must be apply of compiler + */ + boolean accept(JAXXCompiler compiler); + + /** + * Finalize compiler for a given compiler on the finalizer pass before any + * generation. + * + * @param root the root object + * @param compiler the current compiler + * @param javaFile the java file to generate + * @param packageName the package name of the file to generate + * @param className the class name of the file to generate + * @throws Exception if any pb + */ + void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws Exception; + + /** + * Prepare java file after any compiler finalizer pass, says the last + * action before generation. + * + * @param root the root object + * @param compiler the current compiler + * @param javaFile the java file to generate + * @param packageName the package name of the file to generate + * @param className the class name of the file to generate + * @throws Exception if any pb + */ + void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws Exception; +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/SwingFinalizer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/SwingFinalizer.java new file mode 100644 index 0000000..9b8f30d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/SwingFinalizer.java @@ -0,0 +1,93 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.finalizers; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.runtime.swing.Application; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.SwingUtilities; +import java.lang.reflect.Modifier; + +/** + * @author tchemit <chemit@codelutin.com> + * @plexus.component role-hint="swing" role="jaxx.compiler.finalizers.JAXXCompilerFinalizer" + */ +public class SwingFinalizer extends AbstractFinalizer { + + /** Logger. */ + protected static final Log log = LogFactory.getLog(DefaultFinalizer.class); + + @Override + public boolean accept(JAXXCompiler compiler) { + + ClassDescriptor descriptor = + ClassDescriptorHelper.getClassDescriptor(Application.class); + CompiledObject root = compiler.getRootObject(); + boolean accept = descriptor.isAssignableFrom(root.getObjectClass()); + return accept; + } + + @Override + public void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) { + } + + @Override + public void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + + if (compiler.isMainDeclared()) { + + // main method was already defined, can not generate this method. + return; + } + + javaFile.addImport(SwingUtilities.class); + String code = "SwingUtilities.invokeLater(new Runnable() { " + + "public void run() { new " + className + + "().setVisible(true); } });"; + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC | Modifier.STATIC, + TYPE_VOID, + "main", + code, + false, + JavaElementFactory.newArgument("String[]", "arg"))); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/ValidatorFinalizer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/ValidatorFinalizer.java new file mode 100644 index 0000000..8324df6 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/finalizers/ValidatorFinalizer.java @@ -0,0 +1,266 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.finalizers; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompiledObject.ChildRef; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaElement; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaField; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.tags.validator.BeanValidatorHandler; +import jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.JAXXValidator; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.validator.swing.SwingValidator; +import jaxx.runtime.validator.swing.SwingValidatorUtil; +import jaxx.runtime.validator.swing.meta.Validator; +import jaxx.runtime.validator.swing.meta.ValidatorField; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * To finalize validators fields. + * + * @author tchemit <chemit@codelutin.com> + * @plexus.component role-hint="validators" role="jaxx.compiler.finalizers.JAXXCompilerFinalizer" + */ +public class ValidatorFinalizer extends AbstractFinalizer { + + /** Logger. */ + static Log log = LogFactory.getLog(ValidatorFinalizer.class); + + protected static final JavaField VALIDATOR_IDS_FIELD = + JavaElementFactory.newField( + Modifier.PROTECTED, + List.class.getName() + "<String>", + "validatorIds", + true, + "new %s<String>()", + ArrayList.class.getName() + ); + + @Override + public boolean accept(JAXXCompiler compiler) { + + //use this finalizer if compiler is validation aware + boolean accept = BeanValidatorHandler.hasValidator(compiler); + return accept; + } + + @Override + public void finalizeCompiler(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) { + + for (CompiledObject object : compiler.getObjects().values()) { + List<ChildRef> childs = object.getChilds(); + if (childs == null || childs.isEmpty()) { + continue; + } + for (ChildRef child : childs) { + String javaCode = child.getChildJavaCode(); + + // some validators are defined on this object + boolean found = + BeanValidatorHandler.isComponentUsedByValidator( + compiler, + child.getChild().getId() + ); + + if (found) { +// compiler.setNeedSwingUtil(true); + String type = + compiler.getImportedType(SwingUtil.class); + // box the child component in a JxLayer + child.setChildJavaCode( + type + + ".boxComponentWithJxLayer(" + javaCode + ")"); + } + } + } + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder builder = new StringBuilder(); + // register validators + List<CompiledBeanValidator> validators = + BeanValidatorHandler.getValidators(compiler); +// javaFile.addImport(Validator.class); +// javaFile.addImport(ValidatorField.class); +// javaFile.addImport(SwingValidatorUtil.class); + String validatorUtilPrefix = + compiler.getImportedType(SwingValidatorUtil.class) + + "."; + + compiler.getJavaFile().addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + TYPE_VOID, + "registerValidatorFields", + validatorUtilPrefix + "detectValidatorFields(this);", + true) + ); + builder.append("// register "); + builder.append(validators.size()); + builder.append(" validator(s)"); + builder.append(eol); + + builder.append("validatorIds = "); + builder.append(validatorUtilPrefix).append("detectValidators(this);"); + builder.append(eol); + + builder.append(validatorUtilPrefix).append("installUI(this);"); + builder.append(eol); + compiler.appendLateInitializer(builder.toString()); + + for (CompiledBeanValidator validator : validators) { + + registerValidator(validator, compiler, javaFile); + } + } + + @Override + public void prepareJavaFile(CompiledObject root, + JAXXCompiler compiler, + JavaFile javaFile, + String packageName, + String className) throws ClassNotFoundException { + Class<?> validatorClass = SwingValidator.class; + + Class<?> validatorInterface = JAXXValidator.class; + + boolean parentIsValidator = + compiler.isSuperClassAware(validatorInterface); + + if (parentIsValidator) { + + // nothing to generate (use the parent directly) + return; + } + + // add JAXXValidator interface + javaFile.addInterface(JAXXCompiler.getCanonicalName(validatorInterface)); + + // implements JAXXValidator + addField(javaFile, VALIDATOR_IDS_FIELD); + + String type = compiler.getImportedType(validatorClass); + + String initializer = "return (" + type + + "<?>) (validatorIds.contains(validatorId) ? " + + "getObjectById(validatorId) : null);"; + + + javaFile.addMethod(JavaElementFactory.newMethod( + Modifier.PUBLIC, + type + "<?>", + "getValidator", + initializer, + true, + JavaElementFactory.newArgument(TYPE_STRING, "validatorId")) + ); + } + + public void registerValidator(CompiledBeanValidator validator, + JAXXCompiler compiler, + JavaFile javaFile) { + + JavaField validatorField = javaFile.getField(validator.getId()); + + String validatorId = TypeManager.getJavaCode(validator.getId()); + + String type = compiler.getImportedType(Validator.class); + String fieldType = compiler.getImportedType(ValidatorField.class); + + String validatorAnnotation = type + + "( validatorId = " + validatorId + ")"; + validatorField.addAnnotation(validatorAnnotation); + Map<String, String> fields = validator.getFields(); + + for (Map.Entry<String, String> entry : fields.entrySet()) { + String propertyName = entry.getKey(); + String component = entry.getValue(); + + if (!validator.checkBeanProperty(compiler, propertyName)) { + // property not find on bean + continue; + } + + String keyCode = TypeManager.getJavaCode(propertyName); + String editorCode = TypeManager.getJavaCode(component); + JavaElement editor = javaFile.getField(component); + if (editor == null) { + if (log.isDebugEnabled()) { + String message = "Could not find editor [" + component + + "] for property [" + propertyName + + "] for file " + javaFile.getName(); + log.debug(message); + } + + // find in the compiler the object + CompiledObject compiledObject = + compiler.getCompiledObject(component); + + if (compiledObject == null) { + + // this is an error, editor is unknown (this case should + // never happen) + + String errorMessage = + "Could not find editor [" + component + + "] for property [" + propertyName + + "] for file " + javaFile.getName(); + + throw new CompilerException(errorMessage); + } + + // now must add a getter in the javaFile + String fqn = JAXXCompiler.getCanonicalName(compiledObject); + + editor = javaFile.addGetterMethod(component, + Modifier.PUBLIC, + fqn, + true, + true + ); + } + + String annotation = fieldType + + "( validatorId = " + validatorId + "," + + " propertyName = " + keyCode + "," + + " editorName = " + editorCode + "" + ")"; + editor.addAnnotation(annotation); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaArgument.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaArgument.java new file mode 100644 index 0000000..6cde917 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaArgument.java @@ -0,0 +1,86 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.java; + +/** + * Represents an argument to a <code>JavaMethod</code>. + * + * @see JavaMethod + */ +public class JavaArgument extends JavaElement { + + private String type; + + private boolean isFinal; + + /** + * Creates a new <code>JavaArgument</code> with the specified name and type. For example, the method <code>main()</code> + * might have a <code>JavaArgument</code> with a name of <code>"arg"</code> and a type of <code>"java.lang.String[]"</code>. + * + * @param type the argument's type, as it would appear in Java source code + * @param name the argument's name + */ + JavaArgument(String type, String name) { + this(type, name, false); + } + + /** + * Creates a new <code>JavaArgument</code> with the specified name, type, and finality. For example, the method <code>main()</code> + * might have a <code>JavaArgument</code> with a name of <code>"arg"</code> and a type of <code>"java.lang.String[]"</code>. The + * <code>isFinal</code> parameter allows the presence of the <code>final</code> keyword on the argument to be controlled. + * + * @param type the argument's type, as it would appear in Java source code + * @param name the argument's name + * @param isFinal <code>true</code> if the argument should be marked final + */ + JavaArgument(String type, String name, boolean isFinal) { + super(0, name); + this.type = type; + this.isFinal = isFinal; + } + + /** + * Returns the argument's type as it would be represented in Java source code. + * + * @return the argument's type + */ + public String getType() { + return type; + } + + /** + * Returns <code>true</code> if the <code>final</code> keyword should appear before the argument. + * + * @return <code>true</code> if the argument is final + */ + public boolean isFinal() { + return isFinal; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaConstructor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaConstructor.java new file mode 100644 index 0000000..1ae02aa --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaConstructor.java @@ -0,0 +1,98 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.java; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; + +/** + * To mirror a {@link Constructor}. + * <p/> + * In a constructor we need to keep all parameters types as fqn since when + * a jaxx object inheritates from anohter one, it is painfull (even impossible?) + * to find out from a simple name his fqn. + * <p/> + * So when using constructor, always keep fqn types. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4 + */ +public class JavaConstructor extends JavaElement { + + /** arguments of the method (can be empty) */ + private JavaArgument[] arguments; + + /** exceptions thrown by the method (can be empty) */ + private String[] exceptions; + + /** body of the method (can be empty) */ + private String body; + + /** + * 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 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 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 + */ + JavaConstructor(int modifiers, + String name, + JavaArgument[] arguments, + String[] exceptions, + String bodyCode) { + super(modifiers, name); + this.arguments = arguments; + this.exceptions = exceptions; + body = bodyCode == null ? "" : bodyCode; + } + + /** + * 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; + } + + public String getBody() { + return body; + } + +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElement.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElement.java new file mode 100644 index 0000000..48eaced --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElement.java @@ -0,0 +1,133 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.java; + +import org.apache.commons.collections.CollectionUtils; + +import java.lang.reflect.Modifier; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Base Java element + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public abstract class JavaElement { + + // private String lineSeparator; + private String name; + + private int modifiers; + + /** + * List of annoations. + * + * @since 2.3 + */ + private Set<String> annotations; + + public JavaElement(int modifiers, String name) { + this.modifiers = modifiers; + this.name = name; + } + + public final int getModifiers() { + return modifiers; + } + + public final void setModifiers(int modifiers) { + this.modifiers = modifiers; + } + + public final String getName() { + return name; + } + + public final void setName(String name) { + this.name = name; + } + + public final String getModifiersText() { + if (modifiers == 0) { + return ""; + } else { + return Modifier.toString(modifiers) + ' '; + } + } + + public Set<String> getAnnotations() { + if (annotations == null) { + annotations = new HashSet<String>(); + } + return annotations; + } + + public boolean hasAnnotations() { + return CollectionUtils.isNotEmpty(annotations); + } + + public void addAnnotation(String annotation) { + getAnnotations().add(annotation); + } + + public static final Comparator<JavaElement> JavaElementComparator = new Comparator<JavaElement>() { + + final Pattern NAME_PATTERN = Pattern.compile("(.+)([0-9]+)"); + + @Override + public int compare(JavaElement o1, JavaElement o2) { + + String n1 = o1.getName(); + String n2 = o2.getName(); + + //FIXME-tchemit-2012-07-02 (see http://nuiton.org/issues/2154) +// Matcher matcher1 = NAME_PATTERN.matcher(n1); +// Matcher matcher2 = NAME_PATTERN.matcher(n2); +// if (matcher1.matches() && matcher2.matches()) { +// // les deux noms finissent par un nombre +// String p1 = matcher1.group(1); +// String p2 = matcher1.group(2); +// int i = p1.compareTo(p2); +// if (i != 0) { +// // on est sur des noms de prefix différents, donc pas de tri sur les suffixes +// return i; +// } +// // les deux noms doivent être triés sur les suffixes entiers +// int i1 = Integer.valueOf(matcher1.group(2)); +// int i2 = Integer.valueOf(matcher2.group(2)); +// return i1 - i2; +// } + + // les deux noms sont simplement comparé en alpha + return n1.compareTo(n2); + } + }; +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElementFactory.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElementFactory.java new file mode 100644 index 0000000..7934cce --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaElementFactory.java @@ -0,0 +1,186 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.java; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; + +/** + * Factory of any element in a {@link JavaFile}. + * <p/> + * Always pass by this factory to have common behaviour (imports,...) + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4 + */ +public class JavaElementFactory { + + /** Logger. */ + static private final Log log = LogFactory.getLog(JavaElementFactory.class); + + public static JavaFile newFile(int modifiers, String className) { + JavaFile file = new JavaFile(modifiers, className); + return file; + } + + public static JavaArgument newArgument(String type, + String name) { + JavaArgument argument = newArgument(type, name, false); + return argument; + } + + public static JavaArgument newArgument(String type, + String name, + boolean isFinal) { + JavaArgument argument = new JavaArgument(type, name, isFinal); + return argument; + } + + public static JavaField newField(int modifiers, + String returnType, + String name, + boolean override) { + return newField(modifiers, returnType, name, override, null); + } + + public static JavaField newField(int modifiers, + String returnType, + String name, + boolean override, + String initializer, + String... initializerTypes) { + return new JavaField(modifiers, + returnType, + name, + override, + initializer, + initializerTypes + ); + } + + public static JavaConstructor newConstructor(int modifiers, + String name, + String body, + String[] exceptions, + JavaArgument... arguments) { + return new JavaConstructor(modifiers, + name, + arguments, + exceptions, + body + ); + } + + public static JavaConstructor newConstructor(int modifiers, + String name, + String body, + JavaArgument... arguments) { + return newConstructor(modifiers, + name, + body, + StringUtil.EMPTY_STRING_ARRAY, + arguments + ); + } + + public static JavaMethod newMethod(int modifiers, + String returnType, + String name, + String body, + boolean override, + String[] exceptions, + JavaArgument... arguments) { + if (log.isDebugEnabled()) { + log.debug(name + " returns : " + returnType); + } + return new JavaMethod(modifiers, + returnType, + name, + arguments, + exceptions, + body, + override + ); + } + + public static JavaMethod newMethod(int modifiers, + String returnType, + String name, + String body, + boolean override, + JavaArgument... arguments) { + return newMethod(modifiers, + returnType, + name, + body, + override, + StringUtil.EMPTY_STRING_ARRAY, + arguments + ); + } + + public static JavaField cloneField(JavaField field) { + return newField( + field.getModifiers(), + field.getType(), + field.getName(), + field.isOverride(), + field.getInitializer(), + field.getInitializerTypes()); + } + + public static JavaMethod cloneMethod(JavaMethod method) { + + String[] incomingExceptions = method.getExceptions(); + String[] exceptions = new String[incomingExceptions.length]; + System.arraycopy(incomingExceptions, 0, exceptions, 0, exceptions.length); + + JavaArgument[] oldArguments = method.getArguments(); + int nbArguments = oldArguments.length; + JavaArgument[] arguments = new JavaArgument[nbArguments]; + for (int i = 0; i < nbArguments; i++) { + JavaArgument argument = oldArguments[i]; + arguments[i] = cloneArgument(argument); + } + return newMethod( + method.getModifiers(), + method.getReturnType(), + method.getName(), + method.getBody(), + method.isOverride(), + exceptions, + arguments); + } + + public static JavaArgument cloneArgument(JavaArgument argument) { + JavaArgument result = newArgument( + argument.getType(), + argument.getName(), + argument.isFinal() + ); + return result; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaField.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaField.java new file mode 100644 index 0000000..2c17241 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaField.java @@ -0,0 +1,299 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.java; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; + +/** + * 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 extends JavaElement implements Comparable<JavaField> { + + /** type of field (fqn) */ + private String type; + + /** initializer of field (can be null) */ + private String initializer; + + /** + * Types to apply to the initializer to try use simple type names. + * + * @since 2.4 + */ + private String[] initializerTypes; + + + /** flag to known where a field overrides a super-field */ + private boolean override; + + /** + * Constructs a new <code>JavaField</code>. The <code>modifiers</code> parameter is a bit mask of the + * constants from {@link 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 + * @param override flag to add @Override annotation on getter and setter + */ + JavaField(int modifiers, + String type, + String name, + boolean override) { + this(modifiers, type, name, override, 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 override {@code true} if method should be marked as overriden + * @param initializer the initial value of the field, as it would appear in Java source code + * @param initializerTypes initializer types to use + */ + JavaField(int modifiers, + String type, + String name, + boolean override, + String initializer, + String... initializerTypes) { + super(modifiers, name); + this.type = type; + this.initializer = initializer; + this.initializerTypes = initializerTypes; + this.override = override; + } + + /** + * Returns the field's type, as it would be represented in Java source code. + * + * @return the field's type + */ + public String getType() { + return type; + } + + public boolean isOverride() { + return override; + } + + public String getInitializer() { + return initializer; + } + + public String[] getInitializerTypes() { + return initializerTypes; + } + + public boolean hasInitializerTypes() { + return initializerTypes != null && initializerTypes.length > 0; + } + + @Override + public int compareTo(JavaField o) { + return JavaElementComparator.compare(this, o); + } + + @Override + public String toString() { + return super.toString() + " " + getName() + ", type:" + + getType() + ", modifiers:" + Modifier.toString(getModifiers()); + } + + public void setType(String type) { + this.type = type; + } + + public void setInitializer(String initializer) { + this.initializer = initializer; + } + + public enum FieldOrder { + + staticsBean(Modifier.STATIC | Modifier.PUBLIC, + "Constants for all javaBean properties") { + @Override + public boolean accept(JavaField field) { + return field.getName().startsWith("PROPERTY_"); + } + }, + + staticsPublicBindings(Modifier.STATIC | Modifier.PUBLIC, + "Constants for all public bindings") { + @Override + public boolean accept(JavaField field) { + return field.getName().startsWith("BINDING_") && + Modifier.isPublic(field.getModifiers()); + } + }, + + staticsPrivateBindings(Modifier.STATIC | Modifier.PRIVATE, + "Constants for all none public bindings") { + @Override + public boolean accept(JavaField field) { + return field.getName().startsWith("BINDING_$") && + Modifier.isPrivate(field.getModifiers()); + } + }, + + staticsOthers(Modifier.STATIC, "Other static fields"), + + internalFields(Modifier.PROTECTED | Modifier.PRIVATE, + "Internal states") { + + private final List<String> fields = Arrays.asList( + "delegateContext", + "$previousValues", + "$bindingSources", + "$objectMap", + "$activeBindings", + "$bindings", + "$propertyChangeSupport", + "allComponentsCreated", + "contextInitialized"); + + @Override + public boolean accept(JavaField field) { + return fields.contains(field.getName()); + } + }, + publicFields(Modifier.PUBLIC, "Public components"), + protectedFields(Modifier.PROTECTED, "Protected components"), + privateFields(Modifier.PRIVATE, "Private components"), + otherFields(0, "Other fields") { + @Override + public boolean accept(JavaField field) { + return true; + } + }; + + private final String header; + + private int modifier; + + FieldOrder(int modifier, String header) { + this.header = JavaFileGenerator.getHeader(header); + this.modifier = modifier; + } + + public String getHeader() { + return header; + } + + public boolean accept(JavaField field) { + return true; + } + + public boolean accept(int mod) { + return (mod & modifier) != 0; + } + + public boolean accept(int mod, JavaField method) { + return accept(mod) && accept(method); + } + + public static FieldOrder valueOf(JavaField method, int scope) { + for (FieldOrder o : values()) { + if (o.accept(scope, method)) { + return o; + } + } + throw new IllegalArgumentException( + "could not find a " + FieldOrder.class + + " for method " + method); + } + } + + public static EnumMap<FieldOrder, List<JavaField>> getSortedFields(List<JavaField> fields) { + + EnumMap<FieldOrder, List<JavaField>> result = + new EnumMap<FieldOrder, List<JavaField>>(FieldOrder.class); + for (FieldOrder fieldOrder : FieldOrder.values()) { + result.put(fieldOrder, new ArrayList<JavaField>()); + } + + EnumSet<FieldOrder> allConstants = EnumSet.allOf(FieldOrder.class); + List<JavaField> allFields = new ArrayList<JavaField>(fields); + int[] scopes = new int[]{Modifier.STATIC, + Modifier.PUBLIC, + Modifier.PROTECTED, + Modifier.PRIVATE + }; + for (int scope : scopes) { + EnumSet<FieldOrder> constants = + getFieldOrderScope(allConstants, scope); + + Iterator<JavaField> itMethods = allFields.iterator(); + while (itMethods.hasNext()) { + JavaField method = itMethods.next(); + for (FieldOrder constant : constants) { + if (constant.accept(method.getModifiers(), method)) { + result.get(constant).add(method); + itMethods.remove(); + break; + } + } + } + constants.clear(); + } + + if (!allFields.isEmpty()) { + + // probably package locale fields + result.get(FieldOrder.otherFields).addAll(allFields); + } + + for (FieldOrder fieldOrder : FieldOrder.values()) { + // sort fields + Collections.sort(result.get(fieldOrder)); + } + return result; + } + + public static EnumSet<FieldOrder> getFieldOrderScope(EnumSet<FieldOrder> allConstants, int scope) { + EnumSet<FieldOrder> constants = EnumSet.noneOf(FieldOrder.class); + for (FieldOrder order : allConstants) { + if (order.accept(scope)) { + constants.add(order); + } + } + return constants; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFile.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFile.java new file mode 100644 index 0000000..3f0a30e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFile.java @@ -0,0 +1,498 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.java; + +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.types.TypeManager; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.java.extension.ImportsManager; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 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 extends JavaElement { + + /** Logger. */ + static Log log = LogFactory.getLog(JavaFile.class); + + 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 = %2$s;\nfirePropertyChange(%3$s, oldValue, %2$s);"; + + private Set<String> imports = new HashSet<String>(); + + private List<JavaField> fields = new ArrayList<JavaField>(); + + private List<JavaMethod> methods = new ArrayList<JavaMethod>(); + + private List<JavaConstructor> constructors = new ArrayList<JavaConstructor>(); + + private List<JavaFile> innerClasses = new ArrayList<JavaFile>(); + + private String superClass; + + private List<String> interfaces; + + private StringBuilder rawBodyCode = new StringBuilder(); + + private boolean superclassIsJAXXObject; + + private boolean abstractClass; + + private String genericType; + + private String superGenericType; + + private final ImportsManager importManager; + + private String simpleName; + + JavaFile(int modifiers, String className) { + super(modifiers, className); + importManager = new ImportsManager(); + // add the fqn before all in the import manager to deal with alias classes + importManager.addImport(className); + } + + /** @deprecated since 2.4, never be used */ + @Deprecated + JavaFile() { + this(0, ""); + } + + /** + * @param modifiers + * @param className + * @param superClass + * @deprecated since 2.4, never be used + */ + @Deprecated + JavaFile(int modifiers, String className, String superClass) { + this(modifiers, className, superClass, null); + } + + /** + * @param modifiers + * @param className + * @param superClass + * @param interfaces + * @deprecated since 2.4, never be used + */ + @Deprecated + JavaFile(int modifiers, + String className, + String superClass, + List<String> interfaces) { + this(modifiers, className); + setSuperClass(superClass); + if (CollectionUtils.isNotEmpty(interfaces)) { + addInterface(interfaces.toArray(new String[interfaces.size()])); + } + } + + public String getPackageName() { + String name = getName(); + + String packageName; + if (name.contains(".")) { + packageName = name.substring(0, name.lastIndexOf(".")); + } else { + packageName = null; + } + return packageName; + } + + public ImportsManager getImportManager() { + return importManager; + } + + public String getImportedType(Class<?> type) { + return getImportManager().getType(type); + } + + public String getImportedType(String type) { + return getImportManager().getType(type); + } + + public String[] getImports() { + List<String> result = new ArrayList<String>(imports); + Collections.sort(result); + return result.toArray(new String[result.size()]); + } + + public List<String> getImportsList() { + List<String> result = new ArrayList<String>(imports); + Collections.sort(result); + return result; + } + + public String getSuperClass() { + return superClass; + } + + public List<String> getInterfaces() { + if (interfaces == null) { + interfaces = new ArrayList<String>(); + } + return interfaces; + } + + public List<JavaMethod> getMethods() { + return methods; + } + + public List<JavaField> getFields() { + return fields; + } + + public boolean isAbstractClass() { + return abstractClass; + } + + public String getGenericType() { + return genericType; + } + + public List<JavaFile> getInnerClasses() { + return innerClasses; + } + + public StringBuilder getRawBodyCode() { + return rawBodyCode; + } + + public String getSuperGenericType() { + return superGenericType; + } + + public boolean isSuperclassIsJAXXObject() { + return superclassIsJAXXObject; + } + + public String getSimpleName() { + return simpleName; + } + + public JavaField getField(String componentId) { + for (JavaField field : fields) { + if (componentId.equals(field.getName())) { + return field; + } + } + return null; + } + + public void addImport(String importString) { + try { + importManager.addImport(importString); + } catch (Exception e) { + log.error("Could not determine simple name of import " + importString); + } + } + + public void addImport(Class<?> importString) { + addImport(importString.getName()); + } + + public void setImports(Collection<String> imports) { + this.imports = new HashSet<String>(imports); + } + + public void setGenericType(String genericType) { + this.genericType = genericType; + } + + public void setSuperClass(String superClass) { + this.superClass = superClass; + } + + public void addInterface(String... canonicalNames) { + if (canonicalNames == null) { + return; + } + for (String canonicalName : canonicalNames) { + if (interfaces == null || !interfaces.contains(canonicalName)) { + getInterfaces().add(canonicalName); + } + } + } + + public void setInterfaces(List<String> interfaces) { + List<String> simpleInterfaces = new ArrayList<String>(); + for (String anInterface : interfaces) { + try { + String type = importManager.getType(anInterface); + anInterface = type; + } catch (Exception e) { + log.error("Could not determine simple name of interface " + + anInterface); + } + simpleInterfaces.add(anInterface); + } + this.interfaces = simpleInterfaces; + } + + public void addConstructor(JavaConstructor constructor) { + constructors.add(constructor); + } + + public void addMethod(JavaMethod method) { + String returnType = method.getReturnType(); + try { + String type = importManager.getReturnType(returnType); + method.setReturnType(type); + } catch (Exception e) { + log.error("Could not determine simple name of return type " + + returnType + " for method " + method.getName()); + } + for (JavaArgument argument : method.getArguments()) { + String argumentType = argument.getType(); + try { + String type = importManager.getType(argumentType); + argument.setType(type); + } catch (Exception e) { + log.error("Could not determine simple name of argument type " + + argumentType + " of argument " + argument.getName() + + " for method " + method.getName()); + } + } + + String[] exceptions = method.getExceptions(); + for (int i = 0, length = exceptions.length; i < length; i++) { + String exception = exceptions[i]; + try { + String exceptionSimple = importManager.getType(exception); + exceptions[i] = exceptionSimple; + } catch (Exception e) { + log.error("Could not determine simple name of exception " + + exception + " for method " + method.getName()); + } + + } + + // this is a mreal method + methods.add(method); + } + + public void addField(JavaField field) { + + addField(field, false); + } + + public JavaMethod addGetterMethod(String id, + int modifiers, + String type, + boolean overridde, + boolean useOverride) { + + String capitalizedName = StringUtils.capitalize(id); + String methodName = "get" + capitalizedName; + String bodyCode; + if (useOverride) { + bodyCode = "super." + methodName + "()"; + } else { + bodyCode = id; + } + String content = String.format(GETTER_PATTERN, bodyCode); + JavaMethod method = JavaElementFactory.newMethod(modifiers, + type, + methodName, + content, + overridde + ); + addMethod(method); + return method; + } + + public void addField(JavaField field, boolean javaBean) { + addSimpleField(field); + String id = field.getName(); + String capitalizedName = StringUtils.capitalize(id); + + // add accessor method + int modifiers = Modifier.isProtected(field.getModifiers()) ? + Modifier.PUBLIC : Modifier.PROTECTED; + + addGetterMethod(id, + modifiers, + field.getType(), + field.isOverride(), + false + ); + + if (javaBean) { + // add full javabean support accessor + mutator + constant with + // name of property to make it easier to use + // compute the property constant + String constantId = TypeManager.convertVariableNameToConstantName( + "property" + capitalizedName); + addSimpleField(JavaElementFactory.newField( + Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL, + JAXXCompilerFinalizer.TYPE_STRING, + constantId, false, "\"" + id + "\"") + ); + + if (Boolean.class.getSimpleName().equals(field.getType())) { + String content = String.format(BOOLEAN_GETTER_PATTERN, id); + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + field.getType(), + "is" + capitalizedName, + content, + field.isOverride() + ); + addMethod(method); + } + String content = String.format(SETTER_PATTERN, + field.getType(), + id, + constantId + ); + JavaArgument arg = JavaElementFactory.newArgument(field.getType(), + id); + JavaMethod method = JavaElementFactory.newMethod( + Modifier.PUBLIC, + JAXXCompilerFinalizer.TYPE_VOID, + "set" + capitalizedName, + content, + field.isOverride(), + arg); + addMethod(method); + } + } + + public void addSimpleField(JavaField field) { + if (log.isDebugEnabled()) { + log.debug("[" + getName() + "] Add field " + field.getName()); + } + String fieldType = field.getType(); + try { + String type = importManager.getType(fieldType); + field.setType(type); + } catch (Exception e) { + log.error("Could not determine simple name of field [" + + field.getName() + "] type " + fieldType); + } + if (field.hasInitializerTypes()) { + String code = simplifyCode(field.getInitializer(), + field.getInitializerTypes()); + if (log.isDebugEnabled()) { + log.debug("Use simplify text : " + code); + } + field.setInitializer(code); + } + fields.add(field); + } + + public void setSuperclassIsJAXXObject(boolean superclassIsJAXXObject) { + this.superclassIsJAXXObject = superclassIsJAXXObject; + } + + public void setAbstractClass(boolean abstractClass) { + this.abstractClass = abstractClass; + } + + public void setSuperGenericType(String superGenericType) { + this.superGenericType = superGenericType; + } + + public void addBodyCode(String bodyCode) { + rawBodyCode.append(bodyCode); + } + + /** + * Try to use a simple type fro the given {@code type} and apply it on the + * given {@code pattern}. + * <p/> + * Example : + * <pre> + * type = java.io.File, pattern = new %s(""); + * returns : new File("") or new java.io.File("") if importManager can + * not import java.io.File + * </pre> + * + * @param types the types to simplify + * @param pattern the pattern where to apply simple types + * @return the input pattern with most simplest types + * @since 2.4 + */ + public String simplifyCode(String pattern, + String... types) { + String[] simpleTypes = new String[types.length]; + for (int i = 0; i < types.length; i++) { + String type = types[i]; + String simpleType = importManager.getType(type); + simpleTypes[i] = simpleType; + } + String format = String.format(pattern, (Object[]) simpleTypes); + return format; + } + + public void clear() { + importManager.clearImports(); + if (interfaces != null) { + interfaces.clear(); + interfaces = null; + } + if (methods != null) { + methods.clear(); + methods = null; + } + if (constructors != null) { + constructors.clear(); + constructors = null; + } + if (fields != null) { + fields.clear(); + fields = null; + } + if (imports != null) { + imports.clear(); + } + } + + public List<JavaConstructor> getConstructors() { + return constructors; + } + + public void setSimpleName(String simpleName) { + this.simpleName = simpleName; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFileGenerator.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFileGenerator.java new file mode 100644 index 0000000..4e55680 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaFileGenerator.java @@ -0,0 +1,456 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.java; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaMethod.MethodOrder; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map.Entry; + +/** + * Java file generator. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class JavaFileGenerator { + + /** Logger. */ + static private final Log log = LogFactory.getLog(JavaFileGenerator.class); + + public static String getHeader(String header) { + String all = "/*-----------------------------------------------------------------------*/"; + int size = header.length(); + if (size % 2 == 0) { + size++; + header = header + " "; + } + int semi = (all.length() - size) / 2 - 5; + char[] prefix = new char[semi]; + Arrays.fill(prefix, '-'); + + String eol = JAXXCompiler.getLineSeparator(); + + return all + eol + "/*--" + new String(prefix) + + " " + header + " " + new String(prefix) + "--*/" + eol + all + + eol; + } + + /** End of line */ + protected final String eol; + + /** verbose flag when generates */ + protected final boolean verbose; + + /** current prefix indent size */ + protected int indentationLevel; + + public JavaFileGenerator(String eol, boolean verbose) { + this.eol = eol; + this.verbose = verbose && log.isDebugEnabled(); + } + + public static String addDebugLoggerInvocation(JAXXCompiler compiler, + String call) { + String eol = JAXXCompiler.getLineSeparator(); + StringBuilder builder = new StringBuilder(); + if (!compiler.getConfiguration().isAddLogger()) { + return ""; + } else { + builder.append("if (log.isDebugEnabled()) {"); + builder.append(eol); + builder.append(" log.debug(").append(call).append(");"); + builder.append(eol); + builder.append("}"); + builder.append(eol); + } + return builder.toString(); + } + + public String generateImport(String anImport) { + return "import " + anImport + ';' + eol; + } + + public void generateFile(JavaFile f, PrintWriter result) { + String name = f.getName(); + if (verbose) { + log.info(name); + } + indentationLevel = 0; + String packageName = f.getPackageName(); +// if (name.contains(".")) { + if (packageName != null) { +// packageName = name.substring(0, name.lastIndexOf(".")); + result.append("package "); + result.append(packageName); + result.append(";"); + result.append(eol).append(eol); + } + + generateImports(f, result); + + result.append(generateClass(f)); + } + + public void generateImports(JavaFile f, PrintWriter result) { + + List<String> imports = f.getImportsList(); + + boolean addImports = CollectionUtils.isNotEmpty(imports); + for (String anImport : imports) { + result.append(generateImport(anImport)); + } + + if (addImports) { + result.append(eol); + } + } + + public String generateClass(JavaFile f) { + if (verbose) { + log.info(f.getName()); + } + + StringBuilder result = new StringBuilder(); + String genericType = f.getGenericType(); + + result.append(f.getModifiersText()); + if (f.isAbstractClass()) { + result.append("abstract "); + } + result.append("class "); + result.append(f.getName().substring(f.getName().lastIndexOf(".") + 1)); + if (genericType != null) { + result.append('<').append(genericType).append('>'); + } + result.append(" extends "); + result.append(f.getSuperClass()); + if (f.getSuperGenericType() != null) { + result.append('<').append(f.getSuperGenericType()).append('>'); + } + List<String> interfaces = f.getInterfaces(); + + if (interfaces != null && !interfaces.isEmpty()) { + result.append(" implements ").append(interfaces.get(0)); + for (int i = 1; i < interfaces.size(); i++) { + result.append(", ").append(interfaces.get(i)); + } + } + result.append(" {").append(eol); + + // generate fields + + List<JavaField> fields = f.getFields(); + + if (!fields.isEmpty()) { + + EnumMap<JavaField.FieldOrder, List<JavaField>> map = + JavaField.getSortedFields(fields); + for (Entry<JavaField.FieldOrder, List<JavaField>> entry : + map.entrySet()) { + + List<JavaField> list = entry.getValue(); + + // sort fields + Collections.sort(list); + + if (!list.isEmpty()) { + + // add field group header + result.append(eol); + result.append( + addIndentation(entry.getKey().getHeader(), 4, eol)); + result.append(eol); + result.append(eol); + + // add all fields of group + for (JavaField method : list) { + String txt = generateField(method); + result.append(addIndentation(txt, 4, eol)).append(eol); + } + } + list.clear(); + } + map.clear(); + result.append(eol); + } + + // generate raw body + + StringBuilder rawBodyCode = f.getRawBodyCode(); + + if (rawBodyCode.length() > 0) { + result.append(addIndentation( + getHeader("Raw body code from script"), 4, eol)); + result.append(eol); + String s = rawBodyCode.toString(); + if (!s.startsWith(eol)) { + result.append(eol); + } + result.append(addIndentation(s, 4, eol)).append(eol).append(eol); + } + + // generate inner classes + + List<JavaFile> innerClasses = f.getInnerClasses(); + for (JavaFile innerClass : innerClasses) { + indentationLevel += 4; + try { + String txt = generateClass(innerClass); + result.append(addIndentation(txt, 4, eol)); + result.append(eol); + result.append(eol); + } finally { + indentationLevel -= 4; + } + } + + + // add constructors : + + result.append(addIndentation(MethodOrder.constructors.getHeader(), 4, eol)); + result.append(eol); + result.append(eol); + + // add all constructors + for (JavaConstructor method : f.getConstructors()) { + String txt = generateConstructor(method); + result.append(addIndentation(txt, 4, eol)); + result.append(eol); + result.append(eol); + } + + // generate methods + EnumMap<MethodOrder, List<JavaMethod>> map = + JavaMethod.getSortedMethods(f.getMethods()); + + for (Entry<MethodOrder, List<JavaMethod>> entry : map.entrySet()) { + List<JavaMethod> list = entry.getValue(); + if (!list.isEmpty()) { + + // sort methods + Collections.sort(list); + + // add method group header + result.append(addIndentation(entry.getKey().getHeader(), 4, eol)); + result.append(eol); + result.append(eol); + + // add all methods of group + for (JavaMethod method : list) { + String txt = generateMethod(method); + result.append(addIndentation(txt, 4, eol)); + result.append(eol); + result.append(eol); + } + } + list.clear(); + } + map.clear(); + result.append("}"); + return result.toString(); + } + + public String generateField(JavaField f) { + if (verbose) { + if (log.isDebugEnabled()) { + log.debug(f.getName()); + } + } + StringBuilder result = new StringBuilder(); + generateAnnotations(f, result, eol); + result.append(f.getModifiersText()); + result.append(f.getType()).append(' ').append(f.getName()); + if (f.getInitializer() != null) { + result.append(" = ").append(f.getInitializer()); + } + result.append(';').append(eol); + return result.toString(); + } + + protected void generateAnnotations(JavaElement element, + StringBuilder result, + String separator) { + if (element.hasAnnotations()) { + for (String annotation : element.getAnnotations()) { + if (!annotation.startsWith("@")) { + result.append("@"); + } + result.append(annotation).append(separator); + } + } + } + + public String generateConstructor(JavaConstructor m) { + if (verbose) { + log.info(m.getName()); + } + + StringBuilder result = new StringBuilder(); + + generateAnnotations(m, result, eol); + result.append(m.getModifiersText()); + result.append(m.getName()); + result.append('('); + JavaArgument[] arguments = m.getArguments(); + + // adding arguments + + if (arguments != null && arguments.length > 0) { + result.append(generateArgument(arguments[0])); + for (int i = 1; i < arguments.length; i++) { + result.append(", ").append(generateArgument(arguments[i])); + } + } + result.append(")"); + + // adding exceptions + + String[] exceptions = m.getExceptions(); + if (exceptions != null && exceptions.length > 0) { + result.append(" throws ").append(exceptions[0]); + for (int i = 1; i < exceptions.length; i++) { + result.append(", ").append(exceptions[i]); + } + } + result.append(" {"); + result.append(eol); + + // adding body + + String body = m.getBody(); + + if (body != null) { + String formattedBodyCode = addIndentation(body.trim(), 4, eol); + if (formattedBodyCode.length() > 0) { + result.append(formattedBodyCode).append(eol); + } + } + result.append("}"); + return result.toString(); + + } + + public String generateMethod(JavaMethod m) { + if (verbose) { + log.info(m.getName()); + } + + StringBuilder result = new StringBuilder(); + if (m.isOverride()) { + m.addAnnotation(Override.class.getSimpleName()); + } + generateAnnotations(m, result, eol); + result.append(m.getModifiersText()); + if (m.getReturnType() != null) { + result.append(m.getReturnType()); + result.append(' '); + } + result.append(m.getName()); + result.append('('); + JavaArgument[] arguments = m.getArguments(); + + // adding arguments + + if (arguments != null && arguments.length > 0) { + result.append(generateArgument(arguments[0])); + for (int i = 1; i < arguments.length; i++) { + result.append(", ").append(generateArgument(arguments[i])); + } + } + result.append(")"); + + // adding exceptions + + String[] exceptions = m.getExceptions(); + if (exceptions != null && exceptions.length > 0) { + result.append(" throws ").append(exceptions[0]); + for (int i = 1; i < exceptions.length; i++) { + result.append(", ").append(exceptions[i]); + } + } + result.append(" {"); + result.append(eol); + + // adding body + + String body = m.getBody(); + + if (body != null) { + String formattedBodyCode = addIndentation(body.trim(), 4, eol); + if (formattedBodyCode.length() > 0) { + result.append(formattedBodyCode).append(eol); + } + } + result.append("}"); + return result.toString(); + + } + + public String generateArgument(JavaArgument argument) { + String result = argument.getType() + ' ' + argument.getName(); + return argument.isFinal() ? "final " + result : result; + } + + public String addIndentation(String source, + int indentation, + String lineSeparator) { + return indent(source, + indentationLevel + indentation, + false, + lineSeparator + ); + } + + public static String indent(String source, + int indentation, + boolean trim, + String lineSeparator) { + if (trim) { + source = source.trim(); + } + char[] spaces = new char[indentation]; + Arrays.fill(spaces, ' '); + StringBuilder result = new StringBuilder(); + String[] lines = source.split(lineSeparator + "|\n"); + for (int i = 0; i < lines.length; i++) { + if (i > 0) { + result.append(lineSeparator); + } + result.append(spaces); + result.append(trim ? lines[i].trim() : lines[i]); + } + return result.toString(); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaMethod.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaMethod.java new file mode 100644 index 0000000..f547d56 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/JavaMethod.java @@ -0,0 +1,354 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.java; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; + +/** + * 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 extends JavaElement implements Comparable<JavaMethod> { + + /** return type of the method (null for constructors) */ + private String returnType; + + /** arguments of the method (can be empty) */ + private JavaArgument[] arguments; + + /** exceptions thrown by the method (can be empty) */ + private String[] exceptions; + + /** body of the method (can be empty) */ + private String body; + + /** flag to known if the method overrids a super-method */ + private boolean override; + + /** + * 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 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 + * @param override flag with {@code true} value when the method overrides (or implements) a super class method + */ + JavaMethod(int modifiers, + String returnType, + String name, + JavaArgument[] arguments, + String[] exceptions, + String bodyCode, + boolean override) { + super(modifiers, name); + this.returnType = returnType; + this.override = override; + this.arguments = arguments; + this.exceptions = exceptions; + body = bodyCode == null ? "" : bodyCode; + } + + /** + * 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 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; + } + + public boolean isOverride() { + return override; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + @Override + public int compareTo(JavaMethod o) { + return JavaElementComparator.compare(this, o); + } + + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + public enum MethodOrder { + + statics(Modifier.STATIC, "Statics methods"), + + constructors(Modifier.PUBLIC, "Constructors") { + @Override + public boolean accept(JavaMethod method) { + return method.returnType == null; + } + }, + JAXXObject(Modifier.PUBLIC, "JAXXObject implementation") { + + private final List<String> methods = Arrays.asList( + "applyDataBinding", + "firePropertyChange", + "getObjectById", + "get$objectMap", + "processDataBinding", + "removeDataBinding", + "registerDataBinding", + "getDataBindings", + "getDataBinding"); + + @Override + public boolean accept(JavaMethod method) { + return methods.contains(method.getName()); + } + }, + JAXXContext(Modifier.PUBLIC, "JAXXContext implementation") { + + private final List<String> methods = Arrays.asList( + "getContextValue", + "getDelegateContext", + "getParentContainer", + "removeContextValue", + "setContextValue"); + + @Override + public boolean accept(JavaMethod method) { + return methods.contains(method.getName()); + } + }, + JAXXValidation(Modifier.PUBLIC, "JAXXValidator implementation") { + + private final List<String> methods = + Arrays.asList("getValidator", "getValidatorIds", "registerValidatorFields"); + + @Override + public boolean accept(JavaMethod method) { + boolean contains = methods.contains(method.getName()); + if (contains && method.getName().equals("getValidator")) { + // only accept the method getValidator(String) and not anything else... + // since user can have a validator field which is a validator, but not part of the + // JAXXValidatator contract + return method.getArguments().length==1; + } + return contains; + } + }, + events(Modifier.PUBLIC, "Event methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("do") && + method.getName().contains("__"); + } + }, + publicGetters(Modifier.PUBLIC, "Public acessor methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("get") || + method.getName().startsWith("is"); + } + }, + publicSetters(Modifier.PUBLIC, "Public mutator methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("set"); + } + }, + otherPublic(Modifier.PUBLIC, "Other methods") { + @Override + public boolean accept(int mod) { + return super.accept(mod) && !Modifier.isStatic(mod); + } + }, + protectedGetters(Modifier.PROTECTED, "Protected acessors methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("get") || + method.getName().startsWith("is"); + } + }, + createMethod(Modifier.PROTECTED | Modifier.PRIVATE, + "Components creation methods") { + @Override + public boolean accept(JavaMethod method) { + return method.getName().startsWith("create") || + method.getName().startsWith("add"); + } + }, + internalMethod(Modifier.PRIVATE, "Internal jaxx methods") { + private final List<String> methods = Arrays.asList( + "$completeSetup", + "$registerDefaultBindings", + "$initialize"); + + @Override + public boolean accept(JavaMethod method) { + return methods.contains(method.getName()); + } + }, + protecteds(Modifier.PROTECTED, "Other protected methods") { + }, + packageLocal(0, "Package methods") { + @Override + public boolean accept(int mod) { + return !Modifier.isStatic(mod) && + !Modifier.isPublic(mod) && + !Modifier.isProtected(mod); + } + }, + privates(Modifier.PRIVATE, "Other private methods"); + + private final String header; + + private int modifier; + + MethodOrder(int modifier, String header) { + this.header = JavaFileGenerator.getHeader(header); + this.modifier = modifier; + } + + public String getHeader() { + return header; + } + + public boolean accept(JavaMethod method) { + return true; + } + + public boolean accept(int mod) { + return (mod & modifier) != 0; + } + + public boolean accept(int mod, JavaMethod method) { + return accept(mod) && accept(method); + } + + public static MethodOrder valueOf(JavaMethod method, int scope) { + for (MethodOrder o : values()) { + if (o.accept(scope, method)) { + return o; + } + } + throw new IllegalArgumentException( + "could not find a " + MethodOrder.class + + " for method " + method); + } + } + + public static EnumMap<MethodOrder, List<JavaMethod>> getSortedMethods(List<JavaMethod> methods) { + + EnumMap<MethodOrder, List<JavaMethod>> result = + new EnumMap<MethodOrder, List<JavaMethod>>(MethodOrder.class); + for (MethodOrder methodOrder : MethodOrder.values()) { + result.put(methodOrder, new ArrayList<JavaMethod>()); + } + + EnumSet<MethodOrder> allConstants = EnumSet.allOf(MethodOrder.class); + List<JavaMethod> allMethods = new ArrayList<JavaMethod>(methods); + int[] scopes = new int[]{Modifier.STATIC, + Modifier.PUBLIC, + Modifier.PROTECTED, + Modifier.PRIVATE + }; + for (int scope : scopes) { + EnumSet<MethodOrder> constants = + getMethodOrderScope(allConstants, scope); + + Iterator<JavaMethod> itMethods = allMethods.iterator(); + while (itMethods.hasNext()) { + JavaMethod method = itMethods.next(); + for (MethodOrder constant : constants) { + if (constant.accept(method.getModifiers(), method)) { + result.get(constant).add(method); + itMethods.remove(); + break; + } + } + } + constants.clear(); + } + + if (!allMethods.isEmpty()) { + throw new IllegalArgumentException( + "could not find a " + MethodOrder.class + + " for method " + allMethods); + } + + for (MethodOrder methodOrder : MethodOrder.values()) { + // sort methods + Collections.sort(result.get(methodOrder)); + } + return result; + } + + public static EnumSet<MethodOrder> getMethodOrderScope(EnumSet<MethodOrder> allConstants, int scope) { + EnumSet<MethodOrder> constants = EnumSet.noneOf(MethodOrder.class); + for (MethodOrder order : allConstants) { + if (order.accept(scope)) { + constants.add(order); + } + } + return constants; + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JJTJavaParserState.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JJTJavaParserState.java new file mode 100644 index 0000000..da7ce85 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JJTJavaParserState.java @@ -0,0 +1,148 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. .\JJTJavaParserState.java */ + + +package jaxx.compiler.java.parser; + +class JJTJavaParserState { + private java.util.Stack<Node> nodes; + private java.util.Stack<Integer> marks; + + private int sp; // number of nodes on stack + private int mk; // current mark + private boolean node_created; + + JJTJavaParserState() { + nodes = new java.util.Stack<Node>(); + marks = new java.util.Stack<Integer>(); + sp = 0; + mk = 0; + } + + /* Determines whether the current node was actually closed and + pushed. This should only be called in the final user action of a + node scope. */ + boolean nodeCreated() { + return node_created; + } + + /* Call this to reinitialize the node stack. It is called +automatically by the parser's ReInit() method. */ + void reset() { + nodes.removeAllElements(); + marks.removeAllElements(); + sp = 0; + mk = 0; + } + + /* Returns the root node of the AST. It only makes sense to call +this after a successful parse. */ + Node rootNode() { + return nodes.elementAt(0); + } + + /* Pushes a node on to the stack. */ + void pushNode(Node n) { + nodes.push(n); + ++sp; + } + + /* Returns the node on the top of the stack, and remove it from the + stack. */ + Node popNode() { + if (--sp < mk) { + mk = marks.pop(); + } + return nodes.pop(); + } + + /* Returns the node currently on the top of the stack. */ + Node peekNode() { + return nodes.peek(); + } + + /* Returns the number of children on the stack in the current node + scope. */ + int nodeArity() { + return sp - mk; + } + + + void clearNodeScope(Node n) { + while (sp > mk) { + popNode(); + } + mk = marks.pop(); + } + + + void openNodeScope(Node n) { + marks.push(mk); + mk = sp; + n.jjtOpen(); + } + + + /* A definite node is constructed from a specified number of +children. That number of nodes are popped from the stack and +made the children of the definite node. Then the definite node +is pushed on to the stack. */ + void closeNodeScope(Node n, int num) { + mk = marks.pop(); + while (num-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, num); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } + + + /* A conditional node is constructed if its condition is true. All +the nodes that have been pushed since the node was opened are +made children of the the conditional node, which is then pushed +on to the stack. If the condition is false the node is not +constructed and they are left on the stack. */ + void closeNodeScope(Node n, boolean condition) { + if (condition) { + int a = nodeArity(); + mk = marks.pop(); + while (a-- > 0) { + Node c = popNode(); + c.jjtSetParent(n); + n.jjtAddChild(c, a); + } + n.jjtClose(); + pushNode(n); + node_created = true; + } else { + mk = marks.pop(); + node_created = false; + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jj b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jj new file mode 100644 index 0000000..96d01d3 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jj @@ -0,0 +1,5125 @@ +/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. ./Java1.5.jj */ +/*@egen*/ +/* + * Copyright \u00a9 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * California 95054, U.S.A. All rights reserved. Sun Microsystems, Inc. has + * intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, + * these intellectual property rights may include one or more of the U.S. + * patents listed at http://www.sun.com/patents and one or more additional + * patents or pending patent applications in the U.S. and in other countries. + * U.S. Government Rights - Commercial software. Government users are subject + * to the Sun Microsystems, Inc. standard license agreement and applicable + * provisions of the FAR and its supplements. Use is subject to license terms. + * Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered + * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. This + * product is covered and controlled by U.S. Export Control laws and may be + * subject to the export or import laws in other countries. Nuclear, missile, + * chemical biological weapons or nuclear maritime end uses or end users, + * whether direct or indirect, are strictly prohibited. Export or reexport + * to countries subject to U.S. embargo or to entities identified on U.S. + * export exclusion lists, including, but not limited to, the denied persons + * and specially designated nationals lists is strictly prohibited. + */ + +// Slightly modified version of javacc's reference 1.5 grammar, tweaked for +// usage with JAXX. There are two main areas of changes: several new +// nonterminals were added to make identifying certain constructs easier, +// and the Line nonterminal was added to support JAXX's script tags. +// Several of the new changes are inefficient and require excess lookahead, +// but at this point I'd rather have inefficiency than risk breaking it during +// attempted optimizations. + +options { + JAVA_UNICODE_ESCAPE = true; + ERROR_REPORTING = false; + STATIC = false; + JDK_VERSION = "1.4"; +} + +PARSER_BEGIN(JavaParser) +package jaxx.parser; + +import java.io.*; + +/** + * Grammar to parse Java version 1.5 + * @author Sreenivasa Viswanadha - Simplified and enhanced for 1.5 + */ +public class JavaParser/*@bgen(jjtree)*/implements JavaParserTreeConstants/*@egen*/ +{/*@bgen(jjtree)*/ + protected JJTJavaParserState jjtree = new JJTJavaParserState(); + +/*@egen*/ + /** + * Class to hold modifiers. + */ + static public final class ModifierSet + { + /* Definitions of the bits in the modifiers field. */ + public static final int PUBLIC = 0x0001; + public static final int PROTECTED = 0x0002; + public static final int PRIVATE = 0x0004; + public static final int ABSTRACT = 0x0008; + public static final int STATIC = 0x0010; + public static final int FINAL = 0x0020; + public static final int SYNCHRONIZED = 0x0040; + public static final int NATIVE = 0x0080; + public static final int TRANSIENT = 0x0100; + public static final int VOLATILE = 0x0200; + public static final int STRICTFP = 0x1000; + + /** A set of accessors that indicate whether the specified modifier + is in the set. */ + + public boolean isPublic(int modifiers) + { + return (modifiers & PUBLIC) != 0; + } + + public boolean isProtected(int modifiers) + { + return (modifiers & PROTECTED) != 0; + } + + public boolean isPrivate(int modifiers) + { + return (modifiers & PRIVATE) != 0; + } + + public boolean isStatic(int modifiers) + { + return (modifiers & STATIC) != 0; + } + + public boolean isAbstract(int modifiers) + { + return (modifiers & ABSTRACT) != 0; + } + + public boolean isFinal(int modifiers) + { + return (modifiers & FINAL) != 0; + } + + public boolean isNative(int modifiers) + { + return (modifiers & NATIVE) != 0; + } + + public boolean isStrictfp(int modifiers) + { + return (modifiers & STRICTFP) != 0; + } + + public boolean isSynchronized(int modifiers) + { + return (modifiers & SYNCHRONIZED) != 0; + } + + public boolean isTransient(int modifiers) + { + return (modifiers & TRANSIENT) != 0; + } + + public boolean isVolatile(int modifiers) + { + return (modifiers & VOLATILE) != 0; + } + + /** + * Removes the given modifier. + */ + static int removeModifier(int modifiers, int mod) + { + return modifiers & ~mod; + } + } + + public JavaParser(String fileName) + { + this(System.in); + try { ReInit(new FileInputStream(new File(fileName))); } + catch(Exception e) { e.printStackTrace(); } + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public SimpleNode popNode() + { + if ( jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode)jjtree.popNode(); + else + return null; + } + public static void main(String args[]) { + JavaParser parser; + if (args.length == 0) { + System.out.println("Java Parser Version 1.1: Reading from standard input . . ."); + parser = new JavaParser(System.in); + } else if (args.length == 1) { + System.out.println("Java Parser Version 1.1: Reading from file " + args[0] + " . . ."); + try { + parser = new JavaParser(new java.io.FileInputStream(args[0])); + } catch (java.io.FileNotFoundException e) { + System.out.println("Java Parser Version 1.1: File " + args[0] + " not found."); + return; + } + } else { + System.out.println("Java Parser Version 1.1: Usage is one of:"); + System.out.println(" java JavaParser < inputfile"); + System.out.println("OR"); + System.out.println(" java JavaParser inputfile"); + return; + } + try { + parser.CompilationUnit(); + System.out.println("Java Parser Version 1.1: Java program parsed successfully."); + } catch (ParseException e) { + System.out.println(e.getMessage()); + System.out.println("Java Parser Version 1.1: Encountered errors during parse."); + } + } + +} + +PARSER_END(JavaParser) + +/* COMMENTS */ + +MORE : +{ + <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT +| + "/*" : IN_MULTI_LINE_COMMENT +} + +SPECIAL_TOKEN: +{ + <WHITE_SPACE: ([" ", "\n", "\r", "\t", "\f"])+> +} + +SPECIAL_TOKEN : +{ + <SINGLE_LINE_COMMENT: "//" (~["\n", "\r"])* ("\n" | "\r" | "\r\n")?> +} + +<IN_FORMAL_COMMENT> +SPECIAL_TOKEN : +{ + <FORMAL_COMMENT: "*/" > : DEFAULT +} + +<IN_MULTI_LINE_COMMENT> +SPECIAL_TOKEN : +{ + <MULTI_LINE_COMMENT: "*/" > : DEFAULT +} + +<IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT> +MORE : +{ + < ~[] > +} + +/* RESERVED WORDS AND LITERALS */ + +TOKEN : +{ + < ABSTRACT: "abstract" > +| < ASSERT: "assert" > +| < BOOLEAN: "boolean" > +| < BREAK: "break" > +| < BYTE: "byte" > +| < CASE: "case" > +| < CATCH: "catch" > +| < CHAR: "char" > +| < CLASS: "class" > +| < CONST: "const" > +| < CONTINUE: "continue" > +| < _DEFAULT: "default" > +| < DO: "do" > +| < DOUBLE: "double" > +| < ELSE: "else" > +| < ENUM: "enum" > +| < EXTENDS: "extends" > +| < FALSE: "false" > +| < FINAL: "final" > +| < FINALLY: "finally" > +| < FLOAT: "float" > +| < FOR: "for" > +| < GOTO: "goto" > +| < IF: "if" > +| < IMPLEMENTS: "implements" > +| < IMPORT: "import" > +| < INSTANCEOF: "instanceof" > +| < INT: "int" > +| < INTERFACE: "interface" > +| < LONG: "long" > +| < NATIVE: "native" > +| < NEW: "new" > +| < NULL: "null" > +| < PACKAGE: "package"> +| < PRIVATE: "private" > +| < PROTECTED: "protected" > +| < PUBLIC: "public" > +| < RETURN: "return" > +| < SHORT: "short" > +| < STATIC: "static" > +| < STRICTFP: "strictfp" > +| < SUPER: "super" > +| < SWITCH: "switch" > +| < SYNCHRONIZED: "synchronized" > +| < THIS: "this" > +| < THROW: "throw" > +| < THROWS: "throws" > +| < TRANSIENT: "transient" > +| < TRUE: "true" > +| < TRY: "try" > +| < VOID: "void" > +| < VOLATILE: "volatile" > +| < WHILE: "while" > +} + +/* LITERALS */ + +TOKEN : +{ + < INTEGER_LITERAL: + <DECIMAL_LITERAL> (["l","L"])? + | <HEX_LITERAL> (["l","L"])? + | <OCTAL_LITERAL> (["l","L"])? + > +| + < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* > +| + < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ > +| + < #OCTAL_LITERAL: "0" (["0"-"7"])* > +| + < FLOATING_POINT_LITERAL: + <DECIMAL_FLOATING_POINT_LITERAL> + | <HEXADECIMAL_FLOATING_POINT_LITERAL> + > +| + < #DECIMAL_FLOATING_POINT_LITERAL: + (["0"-"9"])+ "." (["0"-"9"])* (<DECIMAL_EXPONENT>)? (["f","F","d","D"])? + | "." (["0"-"9"])+ (<DECIMAL_EXPONENT>)? (["f","F","d","D"])? + | (["0"-"9"])+ <DECIMAL_EXPONENT> (["f","F","d","D"])? + | (["0"-"9"])+ (<DECIMAL_EXPONENT>)? ["f","F","d","D"] + > +| + < #DECIMAL_EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > +| + < #HEXADECIMAL_FLOATING_POINT_LITERAL: + "0" ["x", "X"] (["0"-"9","a"-"f","A"-"F"])+ (".")? <HEXADECIMAL_EXPONENT> (["f","F","d","D"])? + | "0" ["x", "X"] (["0"-"9","a"-"f","A"-"F"])* "." (["0"-"9","a"-"f","A"-"F"])+ <HEXADECIMAL_EXPONENT> (["f","F","d","D"])? + > +| + < #HEXADECIMAL_EXPONENT: ["p","P"] (["+","-"])? (["0"-"9"])+ > +| + < CHARACTER_LITERAL: + "'" + ( (~["'","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + ) + "'" + > +| + < STRING_LITERAL: + "\"" + ( (~["\"","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + )* + "\"" + > +} + +/* IDENTIFIERS */ + +TOKEN : +{ + < IDENTIFIER: <LETTER> (<PART_LETTER>)* > +| + < #LETTER: + [ // all chars for which Character.isIdentifierStart is true + "$", + "A"-"Z", + "_", + "a"-"z", + "\u00a2"-"\u00a5", + "\u00aa", + "\u00b5", + "\u00ba", + "\u00c0"-"\u00d6", + "\u00d8"-"\u00f6", + "\u00f8"-"\u021f", + "\u0222"-"\u0233", + "\u0250"-"\u02ad", + "\u02b0"-"\u02b8", + "\u02bb"-"\u02c1", + "\u02d0"-"\u02d1", + "\u02e0"-"\u02e4", + "\u02ee", + "\u037a", + "\u0386", + "\u0388"-"\u038a", + "\u038c", + "\u038e"-"\u03a1", + "\u03a3"-"\u03ce", + "\u03d0"-"\u03d7", + "\u03da"-"\u03f3", + "\u0400"-"\u0481", + "\u048c"-"\u04c4", + "\u04c7"-"\u04c8", + "\u04cb"-"\u04cc", + "\u04d0"-"\u04f5", + "\u04f8"-"\u04f9", + "\u0531"-"\u0556", + "\u0559", + "\u0561"-"\u0587", + "\u05d0"-"\u05ea", + "\u05f0"-"\u05f2", + "\u0621"-"\u063a", + "\u0640"-"\u064a", + "\u0671"-"\u06d3", + "\u06d5", + "\u06e5"-"\u06e6", + "\u06fa"-"\u06fc", + "\u0710", + "\u0712"-"\u072c", + "\u0780"-"\u07a5", + "\u0905"-"\u0939", + "\u093d", + "\u0950", + "\u0958"-"\u0961", + "\u0985"-"\u098c", + "\u098f"-"\u0990", + "\u0993"-"\u09a8", + "\u09aa"-"\u09b0", + "\u09b2", + "\u09b6"-"\u09b9", + "\u09dc"-"\u09dd", + "\u09df"-"\u09e1", + "\u09f0"-"\u09f3", + "\u0a05"-"\u0a0a", + "\u0a0f"-"\u0a10", + "\u0a13"-"\u0a28", + "\u0a2a"-"\u0a30", + "\u0a32"-"\u0a33", + "\u0a35"-"\u0a36", + "\u0a38"-"\u0a39", + "\u0a59"-"\u0a5c", + "\u0a5e", + "\u0a72"-"\u0a74", + "\u0a85"-"\u0a8b", + "\u0a8d", + "\u0a8f"-"\u0a91", + "\u0a93"-"\u0aa8", + "\u0aaa"-"\u0ab0", + "\u0ab2"-"\u0ab3", + "\u0ab5"-"\u0ab9", + "\u0abd", + "\u0ad0", + "\u0ae0", + "\u0b05"-"\u0b0c", + "\u0b0f"-"\u0b10", + "\u0b13"-"\u0b28", + "\u0b2a"-"\u0b30", + "\u0b32"-"\u0b33", + "\u0b36"-"\u0b39", + "\u0b3d", + "\u0b5c"-"\u0b5d", + "\u0b5f"-"\u0b61", + "\u0b85"-"\u0b8a", + "\u0b8e"-"\u0b90", + "\u0b92"-"\u0b95", + "\u0b99"-"\u0b9a", + "\u0b9c", + "\u0b9e"-"\u0b9f", + "\u0ba3"-"\u0ba4", + "\u0ba8"-"\u0baa", + "\u0bae"-"\u0bb5", + "\u0bb7"-"\u0bb9", + "\u0c05"-"\u0c0c", + "\u0c0e"-"\u0c10", + "\u0c12"-"\u0c28", + "\u0c2a"-"\u0c33", + "\u0c35"-"\u0c39", + "\u0c60"-"\u0c61", + "\u0c85"-"\u0c8c", + "\u0c8e"-"\u0c90", + "\u0c92"-"\u0ca8", + "\u0caa"-"\u0cb3", + "\u0cb5"-"\u0cb9", + "\u0cde", + "\u0ce0"-"\u0ce1", + "\u0d05"-"\u0d0c", + "\u0d0e"-"\u0d10", + "\u0d12"-"\u0d28", + "\u0d2a"-"\u0d39", + "\u0d60"-"\u0d61", + "\u0d85"-"\u0d96", + "\u0d9a"-"\u0db1", + "\u0db3"-"\u0dbb", + "\u0dbd", + "\u0dc0"-"\u0dc6", + "\u0e01"-"\u0e30", + "\u0e32"-"\u0e33", + "\u0e3f"-"\u0e46", + "\u0e81"-"\u0e82", + "\u0e84", + "\u0e87"-"\u0e88", + "\u0e8a", + "\u0e8d", + "\u0e94"-"\u0e97", + "\u0e99"-"\u0e9f", + "\u0ea1"-"\u0ea3", + "\u0ea5", + "\u0ea7", + "\u0eaa"-"\u0eab", + "\u0ead"-"\u0eb0", + "\u0eb2"-"\u0eb3", + "\u0ebd", + "\u0ec0"-"\u0ec4", + "\u0ec6", + "\u0edc"-"\u0edd", + "\u0f00", + "\u0f40"-"\u0f47", + "\u0f49"-"\u0f6a", + "\u0f88"-"\u0f8b", + "\u1000"-"\u1021", + "\u1023"-"\u1027", + "\u1029"-"\u102a", + "\u1050"-"\u1055", + "\u10a0"-"\u10c5", + "\u10d0"-"\u10f6", + "\u1100"-"\u1159", + "\u115f"-"\u11a2", + "\u11a8"-"\u11f9", + "\u1200"-"\u1206", + "\u1208"-"\u1246", + "\u1248", + "\u124a"-"\u124d", + "\u1250"-"\u1256", + "\u1258", + "\u125a"-"\u125d", + "\u1260"-"\u1286", + "\u1288", + "\u128a"-"\u128d", + "\u1290"-"\u12ae", + "\u12b0", + "\u12b2"-"\u12b5", + "\u12b8"-"\u12be", + "\u12c0", + "\u12c2"-"\u12c5", + "\u12c8"-"\u12ce", + "\u12d0"-"\u12d6", + "\u12d8"-"\u12ee", + "\u12f0"-"\u130e", + "\u1310", + "\u1312"-"\u1315", + "\u1318"-"\u131e", + "\u1320"-"\u1346", + "\u1348"-"\u135a", + "\u13a0"-"\u13f4", + "\u1401"-"\u166c", + "\u166f"-"\u1676", + "\u1681"-"\u169a", + "\u16a0"-"\u16ea", + "\u1780"-"\u17b3", + "\u17db", + "\u1820"-"\u1877", + "\u1880"-"\u18a8", + "\u1e00"-"\u1e9b", + "\u1ea0"-"\u1ef9", + "\u1f00"-"\u1f15", + "\u1f18"-"\u1f1d", + "\u1f20"-"\u1f45", + "\u1f48"-"\u1f4d", + "\u1f50"-"\u1f57", + "\u1f59", + "\u1f5b", + "\u1f5d", + "\u1f5f"-"\u1f7d", + "\u1f80"-"\u1fb4", + "\u1fb6"-"\u1fbc", + "\u1fbe", + "\u1fc2"-"\u1fc4", + "\u1fc6"-"\u1fcc", + "\u1fd0"-"\u1fd3", + "\u1fd6"-"\u1fdb", + "\u1fe0"-"\u1fec", + "\u1ff2"-"\u1ff4", + "\u1ff6"-"\u1ffc", + "\u203f"-"\u2040", + "\u207f", + "\u20a0"-"\u20af", + "\u2102", + "\u2107", + "\u210a"-"\u2113", + "\u2115", + "\u2119"-"\u211d", + "\u2124", + "\u2126", + "\u2128", + "\u212a"-"\u212d", + "\u212f"-"\u2131", + "\u2133"-"\u2139", + "\u2160"-"\u2183", + "\u3005"-"\u3007", + "\u3021"-"\u3029", + "\u3031"-"\u3035", + "\u3038"-"\u303a", + "\u3041"-"\u3094", + "\u309d"-"\u309e", + "\u30a1"-"\u30fe", + "\u3105"-"\u312c", + "\u3131"-"\u318e", + "\u31a0"-"\u31b7", + "\u3400"-"\u4db5", + "\u4e00"-"\u9fa5", + "\ua000"-"\ua48c", + "\uac00"-"\ud7a3", + "\uf900"-"\ufa2d", + "\ufb00"-"\ufb06", + "\ufb13"-"\ufb17", + "\ufb1d", + "\ufb1f"-"\ufb28", + "\ufb2a"-"\ufb36", + "\ufb38"-"\ufb3c", + "\ufb3e", + "\ufb40"-"\ufb41", + "\ufb43"-"\ufb44", + "\ufb46"-"\ufbb1", + "\ufbd3"-"\ufd3d", + "\ufd50"-"\ufd8f", + "\ufd92"-"\ufdc7", + "\ufdf0"-"\ufdfb", + "\ufe33"-"\ufe34", + "\ufe4d"-"\ufe4f", + "\ufe69", + "\ufe70"-"\ufe72", + "\ufe74", + "\ufe76"-"\ufefc", + "\uff04", + "\uff21"-"\uff3a", + "\uff3f", + "\uff41"-"\uff5a", + "\uff65"-"\uffbe", + "\uffc2"-"\uffc7", + "\uffca"-"\uffcf", + "\uffd2"-"\uffd7", + "\uffda"-"\uffdc", + "\uffe0"-"\uffe1", + "\uffe5"-"\uffe6" + ] + > +| + < #PART_LETTER: + [ // all chars for which Character.isIdentifierPart is true + "\u0000"-"\u0008", + "\u000e"-"\u001b", + "$", + "0"-"9", + "A"-"Z", + "_", + "a"-"z", + "\u007f"-"\u009f", + "\u00a2"-"\u00a5", + "\u00aa", + "\u00b5", + "\u00ba", + "\u00c0"-"\u00d6", + "\u00d8"-"\u00f6", + "\u00f8"-"\u021f", + "\u0222"-"\u0233", + "\u0250"-"\u02ad", + "\u02b0"-"\u02b8", + "\u02bb"-"\u02c1", + "\u02d0"-"\u02d1", + "\u02e0"-"\u02e4", + "\u02ee", + "\u0300"-"\u034e", + "\u0360"-"\u0362", + "\u037a", + "\u0386", + "\u0388"-"\u038a", + "\u038c", + "\u038e"-"\u03a1", + "\u03a3"-"\u03ce", + "\u03d0"-"\u03d7", + "\u03da"-"\u03f3", + "\u0400"-"\u0481", + "\u0483"-"\u0486", + "\u048c"-"\u04c4", + "\u04c7"-"\u04c8", + "\u04cb"-"\u04cc", + "\u04d0"-"\u04f5", + "\u04f8"-"\u04f9", + "\u0531"-"\u0556", + "\u0559", + "\u0561"-"\u0587", + "\u0591"-"\u05a1", + "\u05a3"-"\u05b9", + "\u05bb"-"\u05bd", + "\u05bf", + "\u05c1"-"\u05c2", + "\u05c4", + "\u05d0"-"\u05ea", + "\u05f0"-"\u05f2", + "\u0621"-"\u063a", + "\u0640"-"\u0655", + "\u0660"-"\u0669", + "\u0670"-"\u06d3", + "\u06d5"-"\u06dc", + "\u06df"-"\u06e8", + "\u06ea"-"\u06ed", + "\u06f0"-"\u06fc", + "\u070f"-"\u072c", + "\u0730"-"\u074a", + "\u0780"-"\u07b0", + "\u0901"-"\u0903", + "\u0905"-"\u0939", + "\u093c"-"\u094d", + "\u0950"-"\u0954", + "\u0958"-"\u0963", + "\u0966"-"\u096f", + "\u0981"-"\u0983", + "\u0985"-"\u098c", + "\u098f"-"\u0990", + "\u0993"-"\u09a8", + "\u09aa"-"\u09b0", + "\u09b2", + "\u09b6"-"\u09b9", + "\u09bc", + "\u09be"-"\u09c4", + "\u09c7"-"\u09c8", + "\u09cb"-"\u09cd", + "\u09d7", + "\u09dc"-"\u09dd", + "\u09df"-"\u09e3", + "\u09e6"-"\u09f3", + "\u0a02", + "\u0a05"-"\u0a0a", + "\u0a0f"-"\u0a10", + "\u0a13"-"\u0a28", + "\u0a2a"-"\u0a30", + "\u0a32"-"\u0a33", + "\u0a35"-"\u0a36", + "\u0a38"-"\u0a39", + "\u0a3c", + "\u0a3e"-"\u0a42", + "\u0a47"-"\u0a48", + "\u0a4b"-"\u0a4d", + "\u0a59"-"\u0a5c", + "\u0a5e", + "\u0a66"-"\u0a74", + "\u0a81"-"\u0a83", + "\u0a85"-"\u0a8b", + "\u0a8d", + "\u0a8f"-"\u0a91", + "\u0a93"-"\u0aa8", + "\u0aaa"-"\u0ab0", + "\u0ab2"-"\u0ab3", + "\u0ab5"-"\u0ab9", + "\u0abc"-"\u0ac5", + "\u0ac7"-"\u0ac9", + "\u0acb"-"\u0acd", + "\u0ad0", + "\u0ae0", + "\u0ae6"-"\u0aef", + "\u0b01"-"\u0b03", + "\u0b05"-"\u0b0c", + "\u0b0f"-"\u0b10", + "\u0b13"-"\u0b28", + "\u0b2a"-"\u0b30", + "\u0b32"-"\u0b33", + "\u0b36"-"\u0b39", + "\u0b3c"-"\u0b43", + "\u0b47"-"\u0b48", + "\u0b4b"-"\u0b4d", + "\u0b56"-"\u0b57", + "\u0b5c"-"\u0b5d", + "\u0b5f"-"\u0b61", + "\u0b66"-"\u0b6f", + "\u0b82"-"\u0b83", + "\u0b85"-"\u0b8a", + "\u0b8e"-"\u0b90", + "\u0b92"-"\u0b95", + "\u0b99"-"\u0b9a", + "\u0b9c", + "\u0b9e"-"\u0b9f", + "\u0ba3"-"\u0ba4", + "\u0ba8"-"\u0baa", + "\u0bae"-"\u0bb5", + "\u0bb7"-"\u0bb9", + "\u0bbe"-"\u0bc2", + "\u0bc6"-"\u0bc8", + "\u0bca"-"\u0bcd", + "\u0bd7", + "\u0be7"-"\u0bef", + "\u0c01"-"\u0c03", + "\u0c05"-"\u0c0c", + "\u0c0e"-"\u0c10", + "\u0c12"-"\u0c28", + "\u0c2a"-"\u0c33", + "\u0c35"-"\u0c39", + "\u0c3e"-"\u0c44", + "\u0c46"-"\u0c48", + "\u0c4a"-"\u0c4d", + "\u0c55"-"\u0c56", + "\u0c60"-"\u0c61", + "\u0c66"-"\u0c6f", + "\u0c82"-"\u0c83", + "\u0c85"-"\u0c8c", + "\u0c8e"-"\u0c90", + "\u0c92"-"\u0ca8", + "\u0caa"-"\u0cb3", + "\u0cb5"-"\u0cb9", + "\u0cbe"-"\u0cc4", + "\u0cc6"-"\u0cc8", + "\u0cca"-"\u0ccd", + "\u0cd5"-"\u0cd6", + "\u0cde", + "\u0ce0"-"\u0ce1", + "\u0ce6"-"\u0cef", + "\u0d02"-"\u0d03", + "\u0d05"-"\u0d0c", + "\u0d0e"-"\u0d10", + "\u0d12"-"\u0d28", + "\u0d2a"-"\u0d39", + "\u0d3e"-"\u0d43", + "\u0d46"-"\u0d48", + "\u0d4a"-"\u0d4d", + "\u0d57", + "\u0d60"-"\u0d61", + "\u0d66"-"\u0d6f", + "\u0d82"-"\u0d83", + "\u0d85"-"\u0d96", + "\u0d9a"-"\u0db1", + "\u0db3"-"\u0dbb", + "\u0dbd", + "\u0dc0"-"\u0dc6", + "\u0dca", + "\u0dcf"-"\u0dd4", + "\u0dd6", + "\u0dd8"-"\u0ddf", + "\u0df2"-"\u0df3", + "\u0e01"-"\u0e3a", + "\u0e3f"-"\u0e4e", + "\u0e50"-"\u0e59", + "\u0e81"-"\u0e82", + "\u0e84", + "\u0e87"-"\u0e88", + "\u0e8a", + "\u0e8d", + "\u0e94"-"\u0e97", + "\u0e99"-"\u0e9f", + "\u0ea1"-"\u0ea3", + "\u0ea5", + "\u0ea7", + "\u0eaa"-"\u0eab", + "\u0ead"-"\u0eb9", + "\u0ebb"-"\u0ebd", + "\u0ec0"-"\u0ec4", + "\u0ec6", + "\u0ec8"-"\u0ecd", + "\u0ed0"-"\u0ed9", + "\u0edc"-"\u0edd", + "\u0f00", + "\u0f18"-"\u0f19", + "\u0f20"-"\u0f29", + "\u0f35", + "\u0f37", + "\u0f39", + "\u0f3e"-"\u0f47", + "\u0f49"-"\u0f6a", + "\u0f71"-"\u0f84", + "\u0f86"-"\u0f8b", + "\u0f90"-"\u0f97", + "\u0f99"-"\u0fbc", + "\u0fc6", + "\u1000"-"\u1021", + "\u1023"-"\u1027", + "\u1029"-"\u102a", + "\u102c"-"\u1032", + "\u1036"-"\u1039", + "\u1040"-"\u1049", + "\u1050"-"\u1059", + "\u10a0"-"\u10c5", + "\u10d0"-"\u10f6", + "\u1100"-"\u1159", + "\u115f"-"\u11a2", + "\u11a8"-"\u11f9", + "\u1200"-"\u1206", + "\u1208"-"\u1246", + "\u1248", + "\u124a"-"\u124d", + "\u1250"-"\u1256", + "\u1258", + "\u125a"-"\u125d", + "\u1260"-"\u1286", + "\u1288", + "\u128a"-"\u128d", + "\u1290"-"\u12ae", + "\u12b0", + "\u12b2"-"\u12b5", + "\u12b8"-"\u12be", + "\u12c0", + "\u12c2"-"\u12c5", + "\u12c8"-"\u12ce", + "\u12d0"-"\u12d6", + "\u12d8"-"\u12ee", + "\u12f0"-"\u130e", + "\u1310", + "\u1312"-"\u1315", + "\u1318"-"\u131e", + "\u1320"-"\u1346", + "\u1348"-"\u135a", + "\u1369"-"\u1371", + "\u13a0"-"\u13f4", + "\u1401"-"\u166c", + "\u166f"-"\u1676", + "\u1681"-"\u169a", + "\u16a0"-"\u16ea", + "\u1780"-"\u17d3", + "\u17db", + "\u17e0"-"\u17e9", + "\u180b"-"\u180e", + "\u1810"-"\u1819", + "\u1820"-"\u1877", + "\u1880"-"\u18a9", + "\u1e00"-"\u1e9b", + "\u1ea0"-"\u1ef9", + "\u1f00"-"\u1f15", + "\u1f18"-"\u1f1d", + "\u1f20"-"\u1f45", + "\u1f48"-"\u1f4d", + "\u1f50"-"\u1f57", + "\u1f59", + "\u1f5b", + "\u1f5d", + "\u1f5f"-"\u1f7d", + "\u1f80"-"\u1fb4", + "\u1fb6"-"\u1fbc", + "\u1fbe", + "\u1fc2"-"\u1fc4", + "\u1fc6"-"\u1fcc", + "\u1fd0"-"\u1fd3", + "\u1fd6"-"\u1fdb", + "\u1fe0"-"\u1fec", + "\u1ff2"-"\u1ff4", + "\u1ff6"-"\u1ffc", + "\u200c"-"\u200f", + "\u202a"-"\u202e", + "\u203f"-"\u2040", + "\u206a"-"\u206f", + "\u207f", + "\u20a0"-"\u20af", + "\u20d0"-"\u20dc", + "\u20e1", + "\u2102", + "\u2107", + "\u210a"-"\u2113", + "\u2115", + "\u2119"-"\u211d", + "\u2124", + "\u2126", + "\u2128", + "\u212a"-"\u212d", + "\u212f"-"\u2131", + "\u2133"-"\u2139", + "\u2160"-"\u2183", + "\u3005"-"\u3007", + "\u3021"-"\u302f", + "\u3031"-"\u3035", + "\u3038"-"\u303a", + "\u3041"-"\u3094", + "\u3099"-"\u309a", + "\u309d"-"\u309e", + "\u30a1"-"\u30fe", + "\u3105"-"\u312c", + "\u3131"-"\u318e", + "\u31a0"-"\u31b7", + "\u3400"-"\u4db5", + "\u4e00"-"\u9fa5", + "\ua000"-"\ua48c", + "\uac00"-"\ud7a3", + "\uf900"-"\ufa2d", + "\ufb00"-"\ufb06", + "\ufb13"-"\ufb17", + "\ufb1d"-"\ufb28", + "\ufb2a"-"\ufb36", + "\ufb38"-"\ufb3c", + "\ufb3e", + "\ufb40"-"\ufb41", + "\ufb43"-"\ufb44", + "\ufb46"-"\ufbb1", + "\ufbd3"-"\ufd3d", + "\ufd50"-"\ufd8f", + "\ufd92"-"\ufdc7", + "\ufdf0"-"\ufdfb", + "\ufe20"-"\ufe23", + "\ufe33"-"\ufe34", + "\ufe4d"-"\ufe4f", + "\ufe69", + "\ufe70"-"\ufe72", + "\ufe74", + "\ufe76"-"\ufefc", + "\ufeff", + "\uff04", + "\uff10"-"\uff19", + "\uff21"-"\uff3a", + "\uff3f", + "\uff41"-"\uff5a", + "\uff65"-"\uffbe", + "\uffc2"-"\uffc7", + "\uffca"-"\uffcf", + "\uffd2"-"\uffd7", + "\uffda"-"\uffdc", + "\uffe0"-"\uffe1", + "\uffe5"-"\uffe6", + "\ufff9"-"\ufffb" + ] + > +} + +/* SEPARATORS */ + +TOKEN : +{ + < LPAREN: "(" > +| < RPAREN: ")" > +| < LBRACE: "{" > +| < RBRACE: "}" > +| < LBRACKET: "[" > +| < RBRACKET: "]" > +| < SEMICOLON: ";" > +| < COMMA: "," > +| < DOT: "." > +| < AT: "@" > +} + +/* OPERATORS */ + +TOKEN : +{ + < ASSIGN: "=" > +| < LT: "<" > +| < BANG: "!" > +| < TILDE: "~" > +| < HOOK: "?" > +| < COLON: ":" > +| < EQ: "==" > +| < LE: "<=" > +| < GE: ">=" > +| < NE: "!=" > +| < SC_OR: "||" > +| < SC_AND: "&&" > +| < INCR: "++" > +| < DECR: "--" > +| < PLUS: "+" > +| < MINUS: "-" > +| < STAR: "*" > +| < SLASH: "/" > +| < BIT_AND: "&" > +| < BIT_OR: "|" > +| < XOR: "^" > +| < REM: "%" > +| < LSHIFT: "<<" > +| < PLUSASSIGN: "+=" > +| < MINUSASSIGN: "-=" > +| < STARASSIGN: "*=" > +| < SLASHASSIGN: "/=" > +| < ANDASSIGN: "&=" > +| < ORASSIGN: "|=" > +| < XORASSIGN: "^=" > +| < REMASSIGN: "%=" > +| < LSHIFTASSIGN: "<<=" > +| < RSIGNEDSHIFTASSIGN: ">>=" > +| < RUNSIGNEDSHIFTASSIGN: ">>>=" > +| < ELLIPSIS: "..." > +} + +/* >'s need special attention due to generics syntax. */ +TOKEN : +{ + < RUNSIGNEDSHIFT: ">>>" > + { + matchedToken.kind = GT; + ((Token.GTToken)matchedToken).realKind = RUNSIGNEDSHIFT; + input_stream.backup(2); + matchedToken.image = ">"; + } +| < RSIGNEDSHIFT: ">>" > + { + matchedToken.kind = GT; + ((Token.GTToken)matchedToken).realKind = RSIGNEDSHIFT; + input_stream.backup(1); + matchedToken.image = ">"; + } +| < GT: ">" > +} + +boolean Line() : +{/*@bgen(jjtree) Line */ + SimpleNode jjtn000 = new SimpleNode(JJTLINE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/ + int modifiers; +} +{/*@bgen(jjtree) Line */ + try { +/*@egen*/ + <EOF>/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ { + return true; + } +| + LOOKAHEAD(BlockStatement()) + BlockStatement()/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ { + return false; + } +| + LOOKAHEAD(Modifiers() [ TypeParameters() ] [ ResultType() ] <IDENTIFIER> FormalParameters() [ "throws" NameList() ] "{") + ClassOrInterfaceBodyDeclaration(false)/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ { + return false; + } +| + LOOKAHEAD(ClassOrInterfaceBodyDeclaration(false)) + ClassOrInterfaceBodyDeclaration(false)/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ { + return false; + } +| + LOOKAHEAD(Expression()) + Expression()/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ { + return false; + } +| + ImportDeclaration()/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ { + return false; + }/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +/***************************************** + * THE JAVA LANGUAGE GRAMMAR STARTS HERE * + *****************************************/ + +/* + * Program structuring syntax follows. + */ + +void CompilationUnit(): +{/*@bgen(jjtree) CompilationUnit */ + SimpleNode jjtn000 = new SimpleNode(JJTCOMPILATIONUNIT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) CompilationUnit */ + try { +/*@egen*/ + [ LOOKAHEAD( ( Annotation() )* "package" ) PackageDeclaration() ] + ( ImportDeclaration() )* + ( TypeDeclaration() )* + ( < "\u001a" > )? + ( <STUFF_TO_IGNORE: ~[]> )? + <EOF>/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PackageDeclaration(): +{/*@bgen(jjtree) PackageDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTPACKAGEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PackageDeclaration */ + try { +/*@egen*/ + Modifiers() "package" Name() ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ImportDeclaration(): +{/*@bgen(jjtree) ImportDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTIMPORTDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ImportDeclaration */ + try { +/*@egen*/ + "import" [ "static" ] Name() [ "." "*" ] ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +/* + * Modifiers. We match all modifiers in a single rule to reduce the chances of + * syntax errors for simple modifier mistakes. It will also enable us to give + * better error messages. + */ + +int Modifiers(): +{/*@bgen(jjtree) Modifiers */ + SimpleNode jjtn000 = new SimpleNode(JJTMODIFIERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/ + int modifiers = 0; +} +{/*@bgen(jjtree) Modifiers */ + try { +/*@egen*/ + ( + LOOKAHEAD(2) + ( + "public" { modifiers |= ModifierSet.PUBLIC; } + | + "static" { modifiers |= ModifierSet.STATIC; } + | + "protected" { modifiers |= ModifierSet.PROTECTED; } + | + "private" { modifiers |= ModifierSet.PRIVATE; } + | + "final" { modifiers |= ModifierSet.FINAL; } + | + "abstract" { modifiers |= ModifierSet.ABSTRACT; } + | + "synchronized" { modifiers |= ModifierSet.SYNCHRONIZED; } + | + "native" { modifiers |= ModifierSet.NATIVE; } + | + "transient" { modifiers |= ModifierSet.TRANSIENT; } + | + "volatile" { modifiers |= ModifierSet.VOLATILE; } + | + "strictfp" { modifiers |= ModifierSet.STRICTFP; } + | + Annotation() + ) + )*/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ + + { + return modifiers; + }/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +/* + * Declaration syntax follows. + */ +void TypeDeclaration(): +{/*@bgen(jjtree) TypeDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/ + int modifiers; +} +{/*@bgen(jjtree) TypeDeclaration */ + try { +/*@egen*/ + ";" +| + modifiers = Modifiers() + ( + ClassOrInterfaceDeclaration(modifiers) + | + EnumDeclaration(modifiers) + | + AnnotationTypeDeclaration(modifiers) + )/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void ClassOrInterfaceDeclaration(int modifiers): +{/*@bgen(jjtree) ClassOrInterfaceDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/ + boolean isInterface = false; +} +{/*@bgen(jjtree) ClassOrInterfaceDeclaration */ + try { +/*@egen*/ + ( "class" | "interface" { isInterface = true; } ) + <IDENTIFIER> + [ TypeParameters() ] + [ ExtendsList(isInterface) ] + [ ImplementsList(isInterface) ] + ClassOrInterfaceBody(isInterface)/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ExtendsList(boolean isInterface): +{/*@bgen(jjtree) ExtendsList */ + SimpleNode jjtn000 = new SimpleNode(JJTEXTENDSLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/ + boolean extendsMoreThanOne = false; +} +{/*@bgen(jjtree) ExtendsList */ + try { +/*@egen*/ + "extends" ClassOrInterfaceType() + ( "," ClassOrInterfaceType() { extendsMoreThanOne = true; } )*/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ + { + if (extendsMoreThanOne && !isInterface) + throw new ParseException("A class cannot extend more than one other class"); + }/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ImplementsList(boolean isInterface): +{/*@bgen(jjtree) ImplementsList */ + SimpleNode jjtn000 = new SimpleNode(JJTIMPLEMENTSLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ImplementsList */ + try { +/*@egen*/ + "implements" ClassOrInterfaceType() + ( "," ClassOrInterfaceType() )*/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ + { + if (isInterface) + throw new ParseException("An interface cannot implement other interfaces"); + }/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void EnumDeclaration(int modifiers): +{/*@bgen(jjtree) EnumDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) EnumDeclaration */ + try { +/*@egen*/ + "enum" <IDENTIFIER> + [ ImplementsList(false) ] + EnumBody()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void EnumBody(): +{/*@bgen(jjtree) EnumBody */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) EnumBody */ + try { +/*@egen*/ + "{" + [ EnumConstant() ( LOOKAHEAD(2) "," EnumConstant() )* ] + [ "," ] + [ ";" ( ClassOrInterfaceBodyDeclaration(false) )* ] + "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void EnumConstant(): +{/*@bgen(jjtree) EnumConstant */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMCONSTANT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) EnumConstant */ + try { +/*@egen*/ + Modifiers() <IDENTIFIER> [ Arguments() ] [ ClassOrInterfaceBody(false) ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void TypeParameters(): +{/*@bgen(jjtree) TypeParameters */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) TypeParameters */ + try { +/*@egen*/ + "<" TypeParameter() ( "," TypeParameter() )* ">"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void TypeParameter(): +{/*@bgen(jjtree) TypeParameter */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) TypeParameter */ + try { +/*@egen*/ + <IDENTIFIER> [ TypeBound() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void TypeBound(): +{/*@bgen(jjtree) TypeBound */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEBOUND); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) TypeBound */ + try { +/*@egen*/ + "extends" ClassOrInterfaceType() ( "&" ClassOrInterfaceType() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ClassOrInterfaceBody(boolean isInterface): +{/*@bgen(jjtree) ClassOrInterfaceBody */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ClassOrInterfaceBody */ + try { +/*@egen*/ + "{" ( ClassOrInterfaceBodyDeclaration(isInterface) )* "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ClassOrInterfaceBodyDeclaration(boolean isInterface): +{/*@bgen(jjtree) ClassOrInterfaceBodyDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODYDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/ + boolean isNestedInterface = false; + int modifiers; +} +{/*@bgen(jjtree) ClassOrInterfaceBodyDeclaration */ + try { +/*@egen*/ + LOOKAHEAD(2) + Initializer()/*@bgen(jjtree)*/ + { + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + } +/*@egen*/ + { + if (isInterface) + throw new ParseException("An interface cannot have initializers"); + } +| + modifiers = Modifiers() // Just get all the modifiers out of the way. If you want to do + // more checks, pass the modifiers down to the member + ( + ClassOrInterfaceDeclaration(modifiers) + | + EnumDeclaration(modifiers) + | + LOOKAHEAD( [ TypeParameters() ] <IDENTIFIER> "(" ) + ConstructorDeclaration() + | + LOOKAHEAD( Type() <IDENTIFIER> ( "[" "]" )* ( "," | "=" | ";" ) ) + FieldDeclaration(modifiers) + | + MethodDeclaration(modifiers) + ) +| + ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void FieldDeclaration(int modifiers): +{/*@bgen(jjtree) FieldDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTFIELDDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) FieldDeclaration */ + try { +/*@egen*/ + // Modifiers are already matched in the caller + Type() VariableDeclarator() ( "," VariableDeclarator() )* ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void VariableDeclarator(): +{/*@bgen(jjtree) VariableDeclarator */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) VariableDeclarator */ + try { +/*@egen*/ + VariableDeclaratorId() [ "=" VariableInitializer() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void VariableDeclaratorId(): +{/*@bgen(jjtree) VariableDeclaratorId */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATORID); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) VariableDeclaratorId */ + try { +/*@egen*/ + <IDENTIFIER> ( "[" "]" )*/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void VariableInitializer(): +{/*@bgen(jjtree) VariableInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) VariableInitializer */ + try { +/*@egen*/ + ArrayInitializer() +| + Expression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ArrayInitializer(): +{/*@bgen(jjtree) ArrayInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTARRAYINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ArrayInitializer */ + try { +/*@egen*/ + "{" [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MethodDeclaration(int modifiers): +{/*@bgen(jjtree) MethodDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MethodDeclaration */ + try { +/*@egen*/ + // Modifiers already matched in the caller! + [ TypeParameters() ] + ResultType() + MethodDeclarator() [ "throws" NameList() ] + ( Block() | ";" )/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MethodDeclarator(): +{/*@bgen(jjtree) MethodDeclarator */ + SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MethodDeclarator */ + try { +/*@egen*/ + <IDENTIFIER> FormalParameters() ( "[" "]" )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void FormalParameters(): +{/*@bgen(jjtree) FormalParameters */ + SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) FormalParameters */ + try { +/*@egen*/ + "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void FormalParameter(): +{/*@bgen(jjtree) FormalParameter */ + SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) FormalParameter */ + try { +/*@egen*/ + Modifiers() Type() [ "..." ] VariableDeclaratorId()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ConstructorDeclaration(): +{/*@bgen(jjtree) ConstructorDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCONSTRUCTORDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ConstructorDeclaration */ + try { +/*@egen*/ + [ TypeParameters() ] + // Modifiers matched in the caller + <IDENTIFIER> FormalParameters() [ "throws" NameList() ] + "{" + [ LOOKAHEAD(ExplicitConstructorInvocation()) + ExplicitConstructorInvocation() + ] + ( BlockStatement() )* + "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ExplicitConstructorInvocation(): +{/*@bgen(jjtree) ExplicitConstructorInvocation */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPLICITCONSTRUCTORINVOCATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ExplicitConstructorInvocation */ + try { +/*@egen*/ + ( <IDENTIFIER> "." )* [ LOOKAHEAD(2) "this" "." ] + [ TypeArguments() ] ("this"|"super") Arguments() ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void Initializer(): +{/*@bgen(jjtree) Initializer */ + SimpleNode jjtn000 = new SimpleNode(JJTINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Initializer */ + try { +/*@egen*/ + [ "static" ] Block()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +/* + * Type, name and expression syntax follows. + */ + +void Type(): +{/*@bgen(jjtree) Type */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Type */ + try { +/*@egen*/ + LOOKAHEAD(2) ReferenceType() + | + PrimitiveType()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ReferenceType(): +{/*@bgen(jjtree) ReferenceType */ + SimpleNode jjtn000 = new SimpleNode(JJTREFERENCETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ReferenceType */ + try { +/*@egen*/ + PrimitiveType() ( LOOKAHEAD(2) "[" "]" )+ + | + ( ClassOrInterfaceType() ) ( LOOKAHEAD(2) "[" "]" )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ClassOrInterfaceType(): +{/*@bgen(jjtree) ClassOrInterfaceType */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ClassOrInterfaceType */ + try { +/*@egen*/ + <IDENTIFIER> [ LOOKAHEAD(2) TypeArguments() ] + ( LOOKAHEAD(2) "." <IDENTIFIER> [ LOOKAHEAD(2) TypeArguments() ] )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void TypeArguments(): +{/*@bgen(jjtree) TypeArguments */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) TypeArguments */ + try { +/*@egen*/ + "<" TypeArgument() ( "," TypeArgument() )* ">"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void TypeArgument(): +{/*@bgen(jjtree) TypeArgument */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) TypeArgument */ + try { +/*@egen*/ + ReferenceType() + | + "?" [ WildcardBounds() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void WildcardBounds(): +{/*@bgen(jjtree) WildcardBounds */ + SimpleNode jjtn000 = new SimpleNode(JJTWILDCARDBOUNDS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) WildcardBounds */ + try { +/*@egen*/ + "extends" ReferenceType() + | + "super" ReferenceType()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +void PrimitiveType(): +{/*@bgen(jjtree) PrimitiveType */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMITIVETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PrimitiveType */ + try { +/*@egen*/ + "boolean" +| + "char" +| + "byte" +| + "short" +| + "int" +| + "long" +| + "float" +| + "double"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ResultType(): +{/*@bgen(jjtree) ResultType */ + SimpleNode jjtn000 = new SimpleNode(JJTRESULTTYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ResultType */ + try { +/*@egen*/ + "void" +| + Type()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void Name(): +/* + * A lookahead of 2 is required below since "Name" can be followed + * by a ".*" when used in the context of an "ImportDeclaration". + */ +{/*@bgen(jjtree) Name */ + SimpleNode jjtn000 = new SimpleNode(JJTNAME); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Name */ + try { +/*@egen*/ + <IDENTIFIER> + ( LOOKAHEAD(2) "." <IDENTIFIER> + )*/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void NameList(): +{/*@bgen(jjtree) NameList */ + SimpleNode jjtn000 = new SimpleNode(JJTNAMELIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) NameList */ + try { +/*@egen*/ + Name() ( "," Name() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +/* + * Expression syntax follows. + */ + +void Expression(): +/* + * This expansion has been written this way instead of: + * Assignment() | ConditionalExpression() + * for performance reasons. + * However, it is a weakening of the grammar for it allows the LHS of + * assignments to be any conditional expression whereas it can only be + * a primary expression. Consider adding a semantic predicate to work + * around this. + */ +{/*@bgen(jjtree) Expression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Expression */ + try { +/*@egen*/ + ConditionalExpression() + [ + LOOKAHEAD(2) + AssignmentOperator() Expression() + ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AssignmentOperator(): +{/*@bgen(jjtree) AssignmentOperator */ + SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTOPERATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AssignmentOperator */ + try { +/*@egen*/ + "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|="/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AssignmentExpression(): +{/*@bgen(jjtree) AssignmentExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AssignmentExpression */ + try { +/*@egen*/ + PrimaryExpression() AssignmentOperator() Expression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ConditionalExpression(): +{/*@bgen(jjtree) ConditionalExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ConditionalExpression */ + try { +/*@egen*/ + ConditionalOrExpression() [ "?" Expression() ":" Expression() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ConditionalOrExpression(): +{/*@bgen(jjtree) ConditionalOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ConditionalOrExpression */ + try { +/*@egen*/ + ConditionalAndExpression() ( "||" ConditionalAndExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ConditionalAndExpression(): +{/*@bgen(jjtree) ConditionalAndExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALANDEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ConditionalAndExpression */ + try { +/*@egen*/ + InclusiveOrExpression() ( "&&" InclusiveOrExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void InclusiveOrExpression(): +{/*@bgen(jjtree) InclusiveOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTINCLUSIVEOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) InclusiveOrExpression */ + try { +/*@egen*/ + ExclusiveOrExpression() ( "|" ExclusiveOrExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ExclusiveOrExpression(): +{/*@bgen(jjtree) ExclusiveOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXCLUSIVEOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ExclusiveOrExpression */ + try { +/*@egen*/ + AndExpression() ( "^" AndExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AndExpression(): +{/*@bgen(jjtree) AndExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTANDEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AndExpression */ + try { +/*@egen*/ + EqualityExpression() ( "&" EqualityExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void EqualityExpression(): +{/*@bgen(jjtree) EqualityExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTEQUALITYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) EqualityExpression */ + try { +/*@egen*/ + InstanceOfExpression() ( ( "==" | "!=" ) InstanceOfExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void InstanceOfExpression(): +{/*@bgen(jjtree) InstanceOfExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTINSTANCEOFEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) InstanceOfExpression */ + try { +/*@egen*/ + RelationalExpression() [ "instanceof" Type() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void RelationalExpression(): +{/*@bgen(jjtree) RelationalExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTRELATIONALEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) RelationalExpression */ + try { +/*@egen*/ + ShiftExpression() ( ( "<" | ">" | "<=" | ">=" ) ShiftExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ShiftExpression(): +{/*@bgen(jjtree) ShiftExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTSHIFTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ShiftExpression */ + try { +/*@egen*/ + AdditiveExpression() ( ( "<<" | RSIGNEDSHIFT() | RUNSIGNEDSHIFT() ) AdditiveExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AdditiveExpression(): +{/*@bgen(jjtree) AdditiveExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTADDITIVEEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AdditiveExpression */ + try { +/*@egen*/ + MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MultiplicativeExpression(): +{/*@bgen(jjtree) MultiplicativeExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTMULTIPLICATIVEEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MultiplicativeExpression */ + try { +/*@egen*/ + UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void UnaryExpression(): +{/*@bgen(jjtree) UnaryExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) UnaryExpression */ + try { +/*@egen*/ + ( "+" | "-" ) UnaryExpression() +| + PreIncrementExpression() +| + PreDecrementExpression() +| + UnaryExpressionNotPlusMinus()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PreIncrementExpression(): +{/*@bgen(jjtree) PreIncrementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPREINCREMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PreIncrementExpression */ + try { +/*@egen*/ + "++" PrimaryExpression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PreDecrementExpression(): +{/*@bgen(jjtree) PreDecrementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPREDECREMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PreDecrementExpression */ + try { +/*@egen*/ + "--" PrimaryExpression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void UnaryExpressionNotPlusMinus(): +{/*@bgen(jjtree) UnaryExpressionNotPlusMinus */ + SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSIONNOTPLUSMINUS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) UnaryExpressionNotPlusMinus */ + try { +/*@egen*/ + ( "~" | "!" ) UnaryExpression() +| + LOOKAHEAD( CastLookahead() ) + CastExpression() +| + PostfixExpression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +// This production is to determine lookahead only. The LOOKAHEAD specifications +// below are not used, but they are there just to indicate that we know about +// this. +void CastLookahead(): +{/*@bgen(jjtree) CastLookahead */ + SimpleNode jjtn000 = new SimpleNode(JJTCASTLOOKAHEAD); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) CastLookahead */ + try { +/*@egen*/ + LOOKAHEAD(2) + "(" PrimitiveType() +| + LOOKAHEAD("(" Type() "[") + "(" Type() "[" "]" +| + "(" Type() ")" ( "~" | "!" | "(" | <IDENTIFIER> | "this" | "super" | "new" | Literal() )/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PostfixExpression(): +{/*@bgen(jjtree) PostfixExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PostfixExpression */ + try { +/*@egen*/ + PrimaryExpression() [ PostfixOperator() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PostfixOperator(): +{/*@bgen(jjtree) PostfixOperator */ + SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXOPERATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PostfixOperator */ + try { +/*@egen*/ + "++" | "--"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void CastExpression(): +{/*@bgen(jjtree) CastExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCASTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) CastExpression */ + try { +/*@egen*/ + LOOKAHEAD("(" PrimitiveType()) + "(" Type() ")" UnaryExpression() +| + "(" Type() ")" UnaryExpressionNotPlusMinus()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PrimaryExpression(): +{/*@bgen(jjtree) PrimaryExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PrimaryExpression */ + try { +/*@egen*/ + PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MemberSelector(): +{/*@bgen(jjtree) MemberSelector */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERSELECTOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MemberSelector */ + try { +/*@egen*/ + "." TypeArguments() <IDENTIFIER>/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PrimaryPrefix(): +{/*@bgen(jjtree) PrimaryPrefix */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYPREFIX); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PrimaryPrefix */ + try { +/*@egen*/ + Literal() +| + LOOKAHEAD( ( <IDENTIFIER> "." )* "this" ) + ( <IDENTIFIER> "." )* + "this" +| + "super" "." <IDENTIFIER> +| + "(" Expression() ")" +| + AllocationExpression() +| + LOOKAHEAD( ResultType() "." "class" ) + ResultType() "." "class" +| + Name()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void PrimarySuffix(): +{/*@bgen(jjtree) PrimarySuffix */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYSUFFIX); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) PrimarySuffix */ + try { +/*@egen*/ + LOOKAHEAD("." "super" ".") + "." "super" +| + LOOKAHEAD("." "this") + "." "this" +| + LOOKAHEAD(2) + "." AllocationExpression() +| + LOOKAHEAD(3) + MemberSelector() +| + "[" Expression() "]" +| + "." <IDENTIFIER> +| + Arguments()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void Literal(): +{/*@bgen(jjtree) Literal */ + SimpleNode jjtn000 = new SimpleNode(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Literal */ + try { +/*@egen*/ + <INTEGER_LITERAL> +| + <FLOATING_POINT_LITERAL> +| + <CHARACTER_LITERAL> +| + <STRING_LITERAL> +| + BooleanLiteral() +| + NullLiteral()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void BooleanLiteral(): +{/*@bgen(jjtree) BooleanLiteral */ + SimpleNode jjtn000 = new SimpleNode(JJTBOOLEANLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) BooleanLiteral */ + try { +/*@egen*/ + "true" +| + "false"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void NullLiteral(): +{/*@bgen(jjtree) NullLiteral */ + SimpleNode jjtn000 = new SimpleNode(JJTNULLLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) NullLiteral */ + try { +/*@egen*/ + "null"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void Arguments(): +{/*@bgen(jjtree) Arguments */ + SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Arguments */ + try { +/*@egen*/ + "(" [ ArgumentList() ] ")"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ArgumentList(): +{/*@bgen(jjtree) ArgumentList */ + SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ArgumentList */ + try { +/*@egen*/ + Expression() ( "," Expression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AllocationExpression(): +{/*@bgen(jjtree) AllocationExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTALLOCATIONEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AllocationExpression */ + try { +/*@egen*/ + LOOKAHEAD(2) + "new" PrimitiveType() ArrayDimsAndInits() +| + "new" ClassOrInterfaceType() [ TypeArguments() ] + ( + ArrayDimsAndInits() + | + Arguments() [ ClassOrInterfaceBody(false) ] + )/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +/* + * The third LOOKAHEAD specification below is to parse to PrimarySuffix + * if there is an expression between the "[...]". + */ +void ArrayDimsAndInits(): +{/*@bgen(jjtree) ArrayDimsAndInits */ + SimpleNode jjtn000 = new SimpleNode(JJTARRAYDIMSANDINITS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ArrayDimsAndInits */ + try { +/*@egen*/ + LOOKAHEAD(2) + ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )* +| + ( "[" "]" )+ ArrayInitializer()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +/* + * Statement syntax follows. + */ + +void Statement(): +{/*@bgen(jjtree) Statement */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Statement */ + try { +/*@egen*/ + LOOKAHEAD(2) + LabeledStatement() +| + AssertStatement() +| + Block() +| + EmptyStatement() +| + StatementExpression() ";" +| + SwitchStatement() +| + IfStatement() +| + WhileStatement() +| + DoStatement() +| + ForStatement() +| + BreakStatement() +| + ContinueStatement() +| + ReturnStatement() +| + ThrowStatement() +| + SynchronizedStatement() +| + TryStatement()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AssertStatement(): +{/*@bgen(jjtree) AssertStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTASSERTSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AssertStatement */ + try { +/*@egen*/ + "assert" Expression() [ ":" Expression() ] ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void LabeledStatement(): +{/*@bgen(jjtree) LabeledStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTLABELEDSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) LabeledStatement */ + try { +/*@egen*/ + <IDENTIFIER> ":" Statement()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void Block(): +{/*@bgen(jjtree) Block */ + SimpleNode jjtn000 = new SimpleNode(JJTBLOCK); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Block */ + try { +/*@egen*/ + "{" ( BlockStatement() )* "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void BlockStatement(): +{/*@bgen(jjtree) BlockStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTBLOCKSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) BlockStatement */ + try { +/*@egen*/ + LOOKAHEAD( Modifiers() Type() <IDENTIFIER> ) + LocalVariableDeclaration() ";" +| + Statement() +| + ClassOrInterfaceDeclaration(0)/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void LocalVariableDeclaration(): +{/*@bgen(jjtree) LocalVariableDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTLOCALVARIABLEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) LocalVariableDeclaration */ + try { +/*@egen*/ + Modifiers() Type() VariableDeclarator() ( "," VariableDeclarator() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void EmptyStatement(): +{/*@bgen(jjtree) EmptyStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTEMPTYSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) EmptyStatement */ + try { +/*@egen*/ + ";"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void StatementExpression(): +{/*@bgen(jjtree) StatementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) StatementExpression */ + try { +/*@egen*/ + PreIncrementExpression() +| + PreDecrementExpression() +| + LOOKAHEAD(PrimaryExpression() AssignmentOperator()) + AssignmentExpression() +| + PostfixExpression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void SwitchStatement(): +{/*@bgen(jjtree) SwitchStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTSWITCHSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) SwitchStatement */ + try { +/*@egen*/ + "switch" "(" Expression() ")" "{" + ( SwitchLabel() ( BlockStatement() )* )* + "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void SwitchLabel(): +{/*@bgen(jjtree) SwitchLabel */ + SimpleNode jjtn000 = new SimpleNode(JJTSWITCHLABEL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) SwitchLabel */ + try { +/*@egen*/ + "case" Expression() ":" +| + "default" ":"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void IfStatement(): +/* + * The disambiguating algorithm of JavaCC automatically binds dangling + * else's to the innermost if statement. The LOOKAHEAD specification + * is to tell JavaCC that we know what we are doing. + */ +{/*@bgen(jjtree) IfStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTIFSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) IfStatement */ + try { +/*@egen*/ + "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void WhileStatement(): +{/*@bgen(jjtree) WhileStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTWHILESTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) WhileStatement */ + try { +/*@egen*/ + "while" "(" Expression() ")" Statement()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void DoStatement(): +{/*@bgen(jjtree) DoStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTDOSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) DoStatement */ + try { +/*@egen*/ + "do" Statement() "while" "(" Expression() ")" ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ForStatement(): +{/*@bgen(jjtree) ForStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTFORSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ForStatement */ + try { +/*@egen*/ + "for" "(" + + ( + LOOKAHEAD(Modifiers() Type() <IDENTIFIER> ":") + Modifiers() Type() <IDENTIFIER> ":" Expression() + | + [ ForInit() ] ";" [ Expression() ] ";" [ ForUpdate() ] + ) + + ")" Statement()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ForInit(): +{/*@bgen(jjtree) ForInit */ + SimpleNode jjtn000 = new SimpleNode(JJTFORINIT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ForInit */ + try { +/*@egen*/ + LOOKAHEAD( Modifiers() Type() <IDENTIFIER> ) + LocalVariableDeclaration() +| + StatementExpressionList()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void StatementExpressionList(): +{/*@bgen(jjtree) StatementExpressionList */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSIONLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) StatementExpressionList */ + try { +/*@egen*/ + StatementExpression() ( "," StatementExpression() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ForUpdate(): +{/*@bgen(jjtree) ForUpdate */ + SimpleNode jjtn000 = new SimpleNode(JJTFORUPDATE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ForUpdate */ + try { +/*@egen*/ + StatementExpressionList()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void BreakStatement(): +{/*@bgen(jjtree) BreakStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTBREAKSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) BreakStatement */ + try { +/*@egen*/ + "break" [ <IDENTIFIER> ] ";"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ContinueStatement(): +{/*@bgen(jjtree) ContinueStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTCONTINUESTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ContinueStatement */ + try { +/*@egen*/ + "continue" [ <IDENTIFIER> ] ";"/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ReturnStatement(): +{/*@bgen(jjtree) ReturnStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTRETURNSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ReturnStatement */ + try { +/*@egen*/ + "return" [ Expression() ] ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void ThrowStatement(): +{/*@bgen(jjtree) ThrowStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTTHROWSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) ThrowStatement */ + try { +/*@egen*/ + "throw" Expression() ";"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void SynchronizedStatement(): +{/*@bgen(jjtree) SynchronizedStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTSYNCHRONIZEDSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) SynchronizedStatement */ + try { +/*@egen*/ + "synchronized" "(" Expression() ")" Block()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void TryStatement(): +/* + * Semantic check required here to make sure that at least one + * finally/catch is present. + */ +{/*@bgen(jjtree) TryStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTTRYSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) TryStatement */ + try { +/*@egen*/ + "try" Block() + ( "catch" "(" FormalParameter() ")" Block() )* + [ "finally" Block() ]/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +/* We use productions to match >>>, >> and > so that we can keep the + * type declaration syntax with generics clean + */ + +void RUNSIGNEDSHIFT(): +{/*@bgen(jjtree) RUNSIGNEDSHIFT */ + SimpleNode jjtn000 = new SimpleNode(JJTRUNSIGNEDSHIFT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) RUNSIGNEDSHIFT */ + try { +/*@egen*/ + ( LOOKAHEAD({ getToken(1).kind == GT && + ((Token.GTToken)getToken(1)).realKind == RUNSIGNEDSHIFT} ) + ">" ">" ">" + )/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void RSIGNEDSHIFT(): +{/*@bgen(jjtree) RSIGNEDSHIFT */ + SimpleNode jjtn000 = new SimpleNode(JJTRSIGNEDSHIFT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) RSIGNEDSHIFT */ + try { +/*@egen*/ + ( LOOKAHEAD({ getToken(1).kind == GT && + ((Token.GTToken)getToken(1)).realKind == RSIGNEDSHIFT} ) + ">" ">" + )/*@bgen(jjtree)*/ + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +/* Annotation syntax follows. */ + +void Annotation(): +{/*@bgen(jjtree) Annotation */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) Annotation */ + try { +/*@egen*/ + LOOKAHEAD( "@" Name() "(" ( <IDENTIFIER> "=" | ")" )) + NormalAnnotation() + | + LOOKAHEAD( "@" Name() "(" ) + SingleMemberAnnotation() + | + MarkerAnnotation()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void NormalAnnotation(): +{/*@bgen(jjtree) NormalAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTNORMALANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) NormalAnnotation */ + try { +/*@egen*/ + "@" Name() "(" [ MemberValuePairs() ] ")"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MarkerAnnotation(): +{/*@bgen(jjtree) MarkerAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTMARKERANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MarkerAnnotation */ + try { +/*@egen*/ + "@" Name()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void SingleMemberAnnotation(): +{/*@bgen(jjtree) SingleMemberAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTSINGLEMEMBERANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) SingleMemberAnnotation */ + try { +/*@egen*/ + "@" Name() "(" MemberValue() ")"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MemberValuePairs(): +{/*@bgen(jjtree) MemberValuePairs */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIRS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MemberValuePairs */ + try { +/*@egen*/ + MemberValuePair() ( "," MemberValuePair() )*/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MemberValuePair(): +{/*@bgen(jjtree) MemberValuePair */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MemberValuePair */ + try { +/*@egen*/ + <IDENTIFIER> "=" MemberValue()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MemberValue(): +{/*@bgen(jjtree) MemberValue */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MemberValue */ + try { +/*@egen*/ + Annotation() + | + MemberValueArrayInitializer() + | + ConditionalExpression()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void MemberValueArrayInitializer(): +{/*@bgen(jjtree) MemberValueArrayInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEARRAYINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) MemberValueArrayInitializer */ + try { +/*@egen*/ + "{" MemberValue() ( LOOKAHEAD(2) "," MemberValue() )* [ "," ] "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + + +/* Annotation Types. */ + +void AnnotationTypeDeclaration(int modifiers): +{/*@bgen(jjtree) AnnotationTypeDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AnnotationTypeDeclaration */ + try { +/*@egen*/ + "@" "interface" <IDENTIFIER> AnnotationTypeBody()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AnnotationTypeBody(): +{/*@bgen(jjtree) AnnotationTypeBody */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) AnnotationTypeBody */ + try { +/*@egen*/ + "{" ( AnnotationTypeMemberDeclaration() )* "}"/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void AnnotationTypeMemberDeclaration(): +{/*@bgen(jjtree) AnnotationTypeMemberDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEMEMBERDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/ + int modifiers; +} +{/*@bgen(jjtree) AnnotationTypeMemberDeclaration */ + try { +/*@egen*/ + modifiers = Modifiers() + ( + LOOKAHEAD(Type() <IDENTIFIER> "(") + Type() <IDENTIFIER> "(" ")" [ DefaultValue() ] ";" + | + ClassOrInterfaceDeclaration(modifiers) + | + EnumDeclaration(modifiers) + | + AnnotationTypeDeclaration(modifiers) + | + FieldDeclaration(modifiers) + ) + | + ( ";" )/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} + +void DefaultValue(): +{/*@bgen(jjtree) DefaultValue */ + SimpleNode jjtn000 = new SimpleNode(JJTDEFAULTVALUE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); +/*@egen*/} +{/*@bgen(jjtree) DefaultValue */ + try { +/*@egen*/ + "default" MemberValue()/*@bgen(jjtree)*/ + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + throw (RuntimeException)jjte000; + } + if (jjte000 instanceof ParseException) { + throw (ParseException)jjte000; + } + throw (Error)jjte000; + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } +/*@egen*/ +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jjt b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jjt new file mode 100644 index 0000000..b47955f --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Java1.5.jjt @@ -0,0 +1,2150 @@ + +/* + * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * California 95054, U.S.A. All rights reserved. Sun Microsystems, Inc. has + * intellectual property rights relating to technology embodied in the product + * that is described in this document. In particular, and without limitation, + * these intellectual property rights may include one or more of the U.S. + * patents listed at http://www.sun.com/patents and one or more additional + * patents or pending patent applications in the U.S. and in other countries. + * U.S. Government Rights - Commercial software. Government users are subject + * to the Sun Microsystems, Inc. standard license agreement and applicable + * provisions of the FAR and its supplements. Use is subject to license terms. + * Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered + * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. This + * product is covered and controlled by U.S. Export Control laws and may be + * subject to the export or import laws in other countries. Nuclear, missile, + * chemical biological weapons or nuclear maritime end uses or end users, + * whether direct or indirect, are strictly prohibited. Export or reexport + * to countries subject to U.S. embargo or to entities identified on U.S. + * export exclusion lists, including, but not limited to, the denied persons + * and specially designated nationals lists is strictly prohibited. + */ + +// Slightly modified version of javacc's reference 1.5 grammar, tweaked for +// usage with JAXX. There are two main areas of changes: several new +// nonterminals were added to make identifying certain constructs easier, +// and the Line nonterminal was added to support JAXX's script tags. +// Several of the new changes are inefficient and require excess lookahead, +// but at this point I'd rather have inefficiency than risk breaking it during +// attempted optimizations. + +options { + JAVA_UNICODE_ESCAPE = true; + ERROR_REPORTING = false; + STATIC = false; + JDK_VERSION = "1.4"; + NODE_SCOPE_HOOK=true; +} + +PARSER_BEGIN(JavaParser) +package jaxx.parser; + +import java.io.*; + +/** + * Grammar to parse Java version 1.5 + * @author Sreenivasa Viswanadha - Simplified and enhanced for 1.5 + */ +public class JavaParser +{ + /** + * Class to hold modifiers. + */ + static public final class ModifierSet + { + /* Definitions of the bits in the modifiers field. */ + public static final int PUBLIC = 0x0001; + public static final int PROTECTED = 0x0002; + public static final int PRIVATE = 0x0004; + public static final int ABSTRACT = 0x0008; + public static final int STATIC = 0x0010; + public static final int FINAL = 0x0020; + public static final int SYNCHRONIZED = 0x0040; + public static final int NATIVE = 0x0080; + public static final int TRANSIENT = 0x0100; + public static final int VOLATILE = 0x0200; + public static final int STRICTFP = 0x1000; + + /** A set of accessors that indicate whether the specified modifier + is in the set. */ + + public boolean isPublic(int modifiers) + { + return (modifiers & PUBLIC) != 0; + } + + public boolean isProtected(int modifiers) + { + return (modifiers & PROTECTED) != 0; + } + + public boolean isPrivate(int modifiers) + { + return (modifiers & PRIVATE) != 0; + } + + public boolean isStatic(int modifiers) + { + return (modifiers & STATIC) != 0; + } + + public boolean isAbstract(int modifiers) + { + return (modifiers & ABSTRACT) != 0; + } + + public boolean isFinal(int modifiers) + { + return (modifiers & FINAL) != 0; + } + + public boolean isNative(int modifiers) + { + return (modifiers & NATIVE) != 0; + } + + public boolean isStrictfp(int modifiers) + { + return (modifiers & STRICTFP) != 0; + } + + public boolean isSynchronized(int modifiers) + { + return (modifiers & SYNCHRONIZED) != 0; + } + + public boolean isTransient(int modifiers) + { + return (modifiers & TRANSIENT) != 0; + } + + public boolean isVolatile(int modifiers) + { + return (modifiers & VOLATILE) != 0; + } + + /** + * Removes the given modifier. + */ + static int removeModifier(int modifiers, int mod) + { + return modifiers & ~mod; + } + } + + public JavaParser(String fileName) + { + this(System.in); + try { ReInit(new FileInputStream(new File(fileName))); } + catch(Exception e) { e.printStackTrace(); } + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public SimpleNode popNode() + { + if ( jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode)jjtree.popNode(); + else + return null; + } + public static void main(String args[]) { + JavaParser parser; + if (args.length == 0) { + System.out.println("Java Parser Version 1.1: Reading from standard input . . ."); + parser = new JavaParser(System.in); + } else if (args.length == 1) { + System.out.println("Java Parser Version 1.1: Reading from file " + args[0] + " . . ."); + try { + parser = new JavaParser(new java.io.FileInputStream(args[0])); + } catch (java.io.FileNotFoundException e) { + System.out.println("Java Parser Version 1.1: File " + args[0] + " not found."); + return; + } + } else { + System.out.println("Java Parser Version 1.1: Usage is one of:"); + System.out.println(" java JavaParser < inputfile"); + System.out.println("OR"); + System.out.println(" java JavaParser inputfile"); + return; + } + try { + parser.CompilationUnit(); + System.out.println("Java Parser Version 1.1: Java program parsed successfully."); + } catch (ParseException e) { + System.out.println(e.getMessage()); + System.out.println("Java Parser Version 1.1: Encountered errors during parse."); + } + } + +} + +PARSER_END(JavaParser) + +/* COMMENTS */ + +MORE : +{ + <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT +| + "/*" : IN_MULTI_LINE_COMMENT +} + +SPECIAL_TOKEN: +{ + <WHITE_SPACE: ([" ", "\n", "\r", "\t", "\f"])+> +} + +SPECIAL_TOKEN : +{ + <SINGLE_LINE_COMMENT: "//" (~["\n", "\r"])* ("\n" | "\r" | "\r\n")?> +} + +<IN_FORMAL_COMMENT> +SPECIAL_TOKEN : +{ + <FORMAL_COMMENT: "*/" > : DEFAULT +} + +<IN_MULTI_LINE_COMMENT> +SPECIAL_TOKEN : +{ + <MULTI_LINE_COMMENT: "*/" > : DEFAULT +} + +<IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT> +MORE : +{ + < ~[] > +} + +/* RESERVED WORDS AND LITERALS */ + +TOKEN : +{ + < ABSTRACT: "abstract" > +| < ASSERT: "assert" > +| < BOOLEAN: "boolean" > +| < BREAK: "break" > +| < BYTE: "byte" > +| < CASE: "case" > +| < CATCH: "catch" > +| < CHAR: "char" > +| < CLASS: "class" > +| < CONST: "const" > +| < CONTINUE: "continue" > +| < _DEFAULT: "default" > +| < DO: "do" > +| < DOUBLE: "double" > +| < ELSE: "else" > +| < ENUM: "enum" > +| < EXTENDS: "extends" > +| < FALSE: "false" > +| < FINAL: "final" > +| < FINALLY: "finally" > +| < FLOAT: "float" > +| < FOR: "for" > +| < GOTO: "goto" > +| < IF: "if" > +| < IMPLEMENTS: "implements" > +| < IMPORT: "import" > +| < INSTANCEOF: "instanceof" > +| < INT: "int" > +| < INTERFACE: "interface" > +| < LONG: "long" > +| < NATIVE: "native" > +| < NEW: "new" > +| < NULL: "null" > +| < PACKAGE: "package"> +| < PRIVATE: "private" > +| < PROTECTED: "protected" > +| < PUBLIC: "public" > +| < RETURN: "return" > +| < SHORT: "short" > +| < STATIC: "static" > +| < STRICTFP: "strictfp" > +| < SUPER: "super" > +| < SWITCH: "switch" > +| < SYNCHRONIZED: "synchronized" > +| < THIS: "this" > +| < THROW: "throw" > +| < THROWS: "throws" > +| < TRANSIENT: "transient" > +| < TRUE: "true" > +| < TRY: "try" > +| < VOID: "void" > +| < VOLATILE: "volatile" > +| < WHILE: "while" > +} + +/* LITERALS */ + +TOKEN : +{ + < INTEGER_LITERAL: + <DECIMAL_LITERAL> (["l","L"])? + | <HEX_LITERAL> (["l","L"])? + | <OCTAL_LITERAL> (["l","L"])? + > +| + < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* > +| + < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ > +| + < #OCTAL_LITERAL: "0" (["0"-"7"])* > +| + < FLOATING_POINT_LITERAL: + <DECIMAL_FLOATING_POINT_LITERAL> + | <HEXADECIMAL_FLOATING_POINT_LITERAL> + > +| + < #DECIMAL_FLOATING_POINT_LITERAL: + (["0"-"9"])+ "." (["0"-"9"])* (<DECIMAL_EXPONENT>)? (["f","F","d","D"])? + | "." (["0"-"9"])+ (<DECIMAL_EXPONENT>)? (["f","F","d","D"])? + | (["0"-"9"])+ <DECIMAL_EXPONENT> (["f","F","d","D"])? + | (["0"-"9"])+ (<DECIMAL_EXPONENT>)? ["f","F","d","D"] + > +| + < #DECIMAL_EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > +| + < #HEXADECIMAL_FLOATING_POINT_LITERAL: + "0" ["x", "X"] (["0"-"9","a"-"f","A"-"F"])+ (".")? <HEXADECIMAL_EXPONENT> (["f","F","d","D"])? + | "0" ["x", "X"] (["0"-"9","a"-"f","A"-"F"])* "." (["0"-"9","a"-"f","A"-"F"])+ <HEXADECIMAL_EXPONENT> (["f","F","d","D"])? + > +| + < #HEXADECIMAL_EXPONENT: ["p","P"] (["+","-"])? (["0"-"9"])+ > +| + < CHARACTER_LITERAL: + "'" + ( (~["'","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + ) + "'" + > +| + < STRING_LITERAL: + "\"" + ( (~["\"","\\","\n","\r"]) + | ("\\" + ( ["n","t","b","r","f","\\","'","\""] + | ["0"-"7"] ( ["0"-"7"] )? + | ["0"-"3"] ["0"-"7"] ["0"-"7"] + ) + ) + )* + "\"" + > +} + +/* IDENTIFIERS */ + +TOKEN : +{ + < IDENTIFIER: <LETTER> (<PART_LETTER>)* > +| + < #LETTER: + [ // all chars for which Character.isIdentifierStart is true + "$", + "A"-"Z", + "_", + "a"-"z", + "\u00a2"-"\u00a5", + "\u00aa", + "\u00b5", + "\u00ba", + "\u00c0"-"\u00d6", + "\u00d8"-"\u00f6", + "\u00f8"-"\u021f", + "\u0222"-"\u0233", + "\u0250"-"\u02ad", + "\u02b0"-"\u02b8", + "\u02bb"-"\u02c1", + "\u02d0"-"\u02d1", + "\u02e0"-"\u02e4", + "\u02ee", + "\u037a", + "\u0386", + "\u0388"-"\u038a", + "\u038c", + "\u038e"-"\u03a1", + "\u03a3"-"\u03ce", + "\u03d0"-"\u03d7", + "\u03da"-"\u03f3", + "\u0400"-"\u0481", + "\u048c"-"\u04c4", + "\u04c7"-"\u04c8", + "\u04cb"-"\u04cc", + "\u04d0"-"\u04f5", + "\u04f8"-"\u04f9", + "\u0531"-"\u0556", + "\u0559", + "\u0561"-"\u0587", + "\u05d0"-"\u05ea", + "\u05f0"-"\u05f2", + "\u0621"-"\u063a", + "\u0640"-"\u064a", + "\u0671"-"\u06d3", + "\u06d5", + "\u06e5"-"\u06e6", + "\u06fa"-"\u06fc", + "\u0710", + "\u0712"-"\u072c", + "\u0780"-"\u07a5", + "\u0905"-"\u0939", + "\u093d", + "\u0950", + "\u0958"-"\u0961", + "\u0985"-"\u098c", + "\u098f"-"\u0990", + "\u0993"-"\u09a8", + "\u09aa"-"\u09b0", + "\u09b2", + "\u09b6"-"\u09b9", + "\u09dc"-"\u09dd", + "\u09df"-"\u09e1", + "\u09f0"-"\u09f3", + "\u0a05"-"\u0a0a", + "\u0a0f"-"\u0a10", + "\u0a13"-"\u0a28", + "\u0a2a"-"\u0a30", + "\u0a32"-"\u0a33", + "\u0a35"-"\u0a36", + "\u0a38"-"\u0a39", + "\u0a59"-"\u0a5c", + "\u0a5e", + "\u0a72"-"\u0a74", + "\u0a85"-"\u0a8b", + "\u0a8d", + "\u0a8f"-"\u0a91", + "\u0a93"-"\u0aa8", + "\u0aaa"-"\u0ab0", + "\u0ab2"-"\u0ab3", + "\u0ab5"-"\u0ab9", + "\u0abd", + "\u0ad0", + "\u0ae0", + "\u0b05"-"\u0b0c", + "\u0b0f"-"\u0b10", + "\u0b13"-"\u0b28", + "\u0b2a"-"\u0b30", + "\u0b32"-"\u0b33", + "\u0b36"-"\u0b39", + "\u0b3d", + "\u0b5c"-"\u0b5d", + "\u0b5f"-"\u0b61", + "\u0b85"-"\u0b8a", + "\u0b8e"-"\u0b90", + "\u0b92"-"\u0b95", + "\u0b99"-"\u0b9a", + "\u0b9c", + "\u0b9e"-"\u0b9f", + "\u0ba3"-"\u0ba4", + "\u0ba8"-"\u0baa", + "\u0bae"-"\u0bb5", + "\u0bb7"-"\u0bb9", + "\u0c05"-"\u0c0c", + "\u0c0e"-"\u0c10", + "\u0c12"-"\u0c28", + "\u0c2a"-"\u0c33", + "\u0c35"-"\u0c39", + "\u0c60"-"\u0c61", + "\u0c85"-"\u0c8c", + "\u0c8e"-"\u0c90", + "\u0c92"-"\u0ca8", + "\u0caa"-"\u0cb3", + "\u0cb5"-"\u0cb9", + "\u0cde", + "\u0ce0"-"\u0ce1", + "\u0d05"-"\u0d0c", + "\u0d0e"-"\u0d10", + "\u0d12"-"\u0d28", + "\u0d2a"-"\u0d39", + "\u0d60"-"\u0d61", + "\u0d85"-"\u0d96", + "\u0d9a"-"\u0db1", + "\u0db3"-"\u0dbb", + "\u0dbd", + "\u0dc0"-"\u0dc6", + "\u0e01"-"\u0e30", + "\u0e32"-"\u0e33", + "\u0e3f"-"\u0e46", + "\u0e81"-"\u0e82", + "\u0e84", + "\u0e87"-"\u0e88", + "\u0e8a", + "\u0e8d", + "\u0e94"-"\u0e97", + "\u0e99"-"\u0e9f", + "\u0ea1"-"\u0ea3", + "\u0ea5", + "\u0ea7", + "\u0eaa"-"\u0eab", + "\u0ead"-"\u0eb0", + "\u0eb2"-"\u0eb3", + "\u0ebd", + "\u0ec0"-"\u0ec4", + "\u0ec6", + "\u0edc"-"\u0edd", + "\u0f00", + "\u0f40"-"\u0f47", + "\u0f49"-"\u0f6a", + "\u0f88"-"\u0f8b", + "\u1000"-"\u1021", + "\u1023"-"\u1027", + "\u1029"-"\u102a", + "\u1050"-"\u1055", + "\u10a0"-"\u10c5", + "\u10d0"-"\u10f6", + "\u1100"-"\u1159", + "\u115f"-"\u11a2", + "\u11a8"-"\u11f9", + "\u1200"-"\u1206", + "\u1208"-"\u1246", + "\u1248", + "\u124a"-"\u124d", + "\u1250"-"\u1256", + "\u1258", + "\u125a"-"\u125d", + "\u1260"-"\u1286", + "\u1288", + "\u128a"-"\u128d", + "\u1290"-"\u12ae", + "\u12b0", + "\u12b2"-"\u12b5", + "\u12b8"-"\u12be", + "\u12c0", + "\u12c2"-"\u12c5", + "\u12c8"-"\u12ce", + "\u12d0"-"\u12d6", + "\u12d8"-"\u12ee", + "\u12f0"-"\u130e", + "\u1310", + "\u1312"-"\u1315", + "\u1318"-"\u131e", + "\u1320"-"\u1346", + "\u1348"-"\u135a", + "\u13a0"-"\u13f4", + "\u1401"-"\u166c", + "\u166f"-"\u1676", + "\u1681"-"\u169a", + "\u16a0"-"\u16ea", + "\u1780"-"\u17b3", + "\u17db", + "\u1820"-"\u1877", + "\u1880"-"\u18a8", + "\u1e00"-"\u1e9b", + "\u1ea0"-"\u1ef9", + "\u1f00"-"\u1f15", + "\u1f18"-"\u1f1d", + "\u1f20"-"\u1f45", + "\u1f48"-"\u1f4d", + "\u1f50"-"\u1f57", + "\u1f59", + "\u1f5b", + "\u1f5d", + "\u1f5f"-"\u1f7d", + "\u1f80"-"\u1fb4", + "\u1fb6"-"\u1fbc", + "\u1fbe", + "\u1fc2"-"\u1fc4", + "\u1fc6"-"\u1fcc", + "\u1fd0"-"\u1fd3", + "\u1fd6"-"\u1fdb", + "\u1fe0"-"\u1fec", + "\u1ff2"-"\u1ff4", + "\u1ff6"-"\u1ffc", + "\u203f"-"\u2040", + "\u207f", + "\u20a0"-"\u20af", + "\u2102", + "\u2107", + "\u210a"-"\u2113", + "\u2115", + "\u2119"-"\u211d", + "\u2124", + "\u2126", + "\u2128", + "\u212a"-"\u212d", + "\u212f"-"\u2131", + "\u2133"-"\u2139", + "\u2160"-"\u2183", + "\u3005"-"\u3007", + "\u3021"-"\u3029", + "\u3031"-"\u3035", + "\u3038"-"\u303a", + "\u3041"-"\u3094", + "\u309d"-"\u309e", + "\u30a1"-"\u30fe", + "\u3105"-"\u312c", + "\u3131"-"\u318e", + "\u31a0"-"\u31b7", + "\u3400"-"\u4db5", + "\u4e00"-"\u9fa5", + "\ua000"-"\ua48c", + "\uac00"-"\ud7a3", + "\uf900"-"\ufa2d", + "\ufb00"-"\ufb06", + "\ufb13"-"\ufb17", + "\ufb1d", + "\ufb1f"-"\ufb28", + "\ufb2a"-"\ufb36", + "\ufb38"-"\ufb3c", + "\ufb3e", + "\ufb40"-"\ufb41", + "\ufb43"-"\ufb44", + "\ufb46"-"\ufbb1", + "\ufbd3"-"\ufd3d", + "\ufd50"-"\ufd8f", + "\ufd92"-"\ufdc7", + "\ufdf0"-"\ufdfb", + "\ufe33"-"\ufe34", + "\ufe4d"-"\ufe4f", + "\ufe69", + "\ufe70"-"\ufe72", + "\ufe74", + "\ufe76"-"\ufefc", + "\uff04", + "\uff21"-"\uff3a", + "\uff3f", + "\uff41"-"\uff5a", + "\uff65"-"\uffbe", + "\uffc2"-"\uffc7", + "\uffca"-"\uffcf", + "\uffd2"-"\uffd7", + "\uffda"-"\uffdc", + "\uffe0"-"\uffe1", + "\uffe5"-"\uffe6" + ] + > +| + < #PART_LETTER: + [ // all chars for which Character.isIdentifierPart is true + "\u0000"-"\u0008", + "\u000e"-"\u001b", + "$", + "0"-"9", + "A"-"Z", + "_", + "a"-"z", + "\u007f"-"\u009f", + "\u00a2"-"\u00a5", + "\u00aa", + "\u00b5", + "\u00ba", + "\u00c0"-"\u00d6", + "\u00d8"-"\u00f6", + "\u00f8"-"\u021f", + "\u0222"-"\u0233", + "\u0250"-"\u02ad", + "\u02b0"-"\u02b8", + "\u02bb"-"\u02c1", + "\u02d0"-"\u02d1", + "\u02e0"-"\u02e4", + "\u02ee", + "\u0300"-"\u034e", + "\u0360"-"\u0362", + "\u037a", + "\u0386", + "\u0388"-"\u038a", + "\u038c", + "\u038e"-"\u03a1", + "\u03a3"-"\u03ce", + "\u03d0"-"\u03d7", + "\u03da"-"\u03f3", + "\u0400"-"\u0481", + "\u0483"-"\u0486", + "\u048c"-"\u04c4", + "\u04c7"-"\u04c8", + "\u04cb"-"\u04cc", + "\u04d0"-"\u04f5", + "\u04f8"-"\u04f9", + "\u0531"-"\u0556", + "\u0559", + "\u0561"-"\u0587", + "\u0591"-"\u05a1", + "\u05a3"-"\u05b9", + "\u05bb"-"\u05bd", + "\u05bf", + "\u05c1"-"\u05c2", + "\u05c4", + "\u05d0"-"\u05ea", + "\u05f0"-"\u05f2", + "\u0621"-"\u063a", + "\u0640"-"\u0655", + "\u0660"-"\u0669", + "\u0670"-"\u06d3", + "\u06d5"-"\u06dc", + "\u06df"-"\u06e8", + "\u06ea"-"\u06ed", + "\u06f0"-"\u06fc", + "\u070f"-"\u072c", + "\u0730"-"\u074a", + "\u0780"-"\u07b0", + "\u0901"-"\u0903", + "\u0905"-"\u0939", + "\u093c"-"\u094d", + "\u0950"-"\u0954", + "\u0958"-"\u0963", + "\u0966"-"\u096f", + "\u0981"-"\u0983", + "\u0985"-"\u098c", + "\u098f"-"\u0990", + "\u0993"-"\u09a8", + "\u09aa"-"\u09b0", + "\u09b2", + "\u09b6"-"\u09b9", + "\u09bc", + "\u09be"-"\u09c4", + "\u09c7"-"\u09c8", + "\u09cb"-"\u09cd", + "\u09d7", + "\u09dc"-"\u09dd", + "\u09df"-"\u09e3", + "\u09e6"-"\u09f3", + "\u0a02", + "\u0a05"-"\u0a0a", + "\u0a0f"-"\u0a10", + "\u0a13"-"\u0a28", + "\u0a2a"-"\u0a30", + "\u0a32"-"\u0a33", + "\u0a35"-"\u0a36", + "\u0a38"-"\u0a39", + "\u0a3c", + "\u0a3e"-"\u0a42", + "\u0a47"-"\u0a48", + "\u0a4b"-"\u0a4d", + "\u0a59"-"\u0a5c", + "\u0a5e", + "\u0a66"-"\u0a74", + "\u0a81"-"\u0a83", + "\u0a85"-"\u0a8b", + "\u0a8d", + "\u0a8f"-"\u0a91", + "\u0a93"-"\u0aa8", + "\u0aaa"-"\u0ab0", + "\u0ab2"-"\u0ab3", + "\u0ab5"-"\u0ab9", + "\u0abc"-"\u0ac5", + "\u0ac7"-"\u0ac9", + "\u0acb"-"\u0acd", + "\u0ad0", + "\u0ae0", + "\u0ae6"-"\u0aef", + "\u0b01"-"\u0b03", + "\u0b05"-"\u0b0c", + "\u0b0f"-"\u0b10", + "\u0b13"-"\u0b28", + "\u0b2a"-"\u0b30", + "\u0b32"-"\u0b33", + "\u0b36"-"\u0b39", + "\u0b3c"-"\u0b43", + "\u0b47"-"\u0b48", + "\u0b4b"-"\u0b4d", + "\u0b56"-"\u0b57", + "\u0b5c"-"\u0b5d", + "\u0b5f"-"\u0b61", + "\u0b66"-"\u0b6f", + "\u0b82"-"\u0b83", + "\u0b85"-"\u0b8a", + "\u0b8e"-"\u0b90", + "\u0b92"-"\u0b95", + "\u0b99"-"\u0b9a", + "\u0b9c", + "\u0b9e"-"\u0b9f", + "\u0ba3"-"\u0ba4", + "\u0ba8"-"\u0baa", + "\u0bae"-"\u0bb5", + "\u0bb7"-"\u0bb9", + "\u0bbe"-"\u0bc2", + "\u0bc6"-"\u0bc8", + "\u0bca"-"\u0bcd", + "\u0bd7", + "\u0be7"-"\u0bef", + "\u0c01"-"\u0c03", + "\u0c05"-"\u0c0c", + "\u0c0e"-"\u0c10", + "\u0c12"-"\u0c28", + "\u0c2a"-"\u0c33", + "\u0c35"-"\u0c39", + "\u0c3e"-"\u0c44", + "\u0c46"-"\u0c48", + "\u0c4a"-"\u0c4d", + "\u0c55"-"\u0c56", + "\u0c60"-"\u0c61", + "\u0c66"-"\u0c6f", + "\u0c82"-"\u0c83", + "\u0c85"-"\u0c8c", + "\u0c8e"-"\u0c90", + "\u0c92"-"\u0ca8", + "\u0caa"-"\u0cb3", + "\u0cb5"-"\u0cb9", + "\u0cbe"-"\u0cc4", + "\u0cc6"-"\u0cc8", + "\u0cca"-"\u0ccd", + "\u0cd5"-"\u0cd6", + "\u0cde", + "\u0ce0"-"\u0ce1", + "\u0ce6"-"\u0cef", + "\u0d02"-"\u0d03", + "\u0d05"-"\u0d0c", + "\u0d0e"-"\u0d10", + "\u0d12"-"\u0d28", + "\u0d2a"-"\u0d39", + "\u0d3e"-"\u0d43", + "\u0d46"-"\u0d48", + "\u0d4a"-"\u0d4d", + "\u0d57", + "\u0d60"-"\u0d61", + "\u0d66"-"\u0d6f", + "\u0d82"-"\u0d83", + "\u0d85"-"\u0d96", + "\u0d9a"-"\u0db1", + "\u0db3"-"\u0dbb", + "\u0dbd", + "\u0dc0"-"\u0dc6", + "\u0dca", + "\u0dcf"-"\u0dd4", + "\u0dd6", + "\u0dd8"-"\u0ddf", + "\u0df2"-"\u0df3", + "\u0e01"-"\u0e3a", + "\u0e3f"-"\u0e4e", + "\u0e50"-"\u0e59", + "\u0e81"-"\u0e82", + "\u0e84", + "\u0e87"-"\u0e88", + "\u0e8a", + "\u0e8d", + "\u0e94"-"\u0e97", + "\u0e99"-"\u0e9f", + "\u0ea1"-"\u0ea3", + "\u0ea5", + "\u0ea7", + "\u0eaa"-"\u0eab", + "\u0ead"-"\u0eb9", + "\u0ebb"-"\u0ebd", + "\u0ec0"-"\u0ec4", + "\u0ec6", + "\u0ec8"-"\u0ecd", + "\u0ed0"-"\u0ed9", + "\u0edc"-"\u0edd", + "\u0f00", + "\u0f18"-"\u0f19", + "\u0f20"-"\u0f29", + "\u0f35", + "\u0f37", + "\u0f39", + "\u0f3e"-"\u0f47", + "\u0f49"-"\u0f6a", + "\u0f71"-"\u0f84", + "\u0f86"-"\u0f8b", + "\u0f90"-"\u0f97", + "\u0f99"-"\u0fbc", + "\u0fc6", + "\u1000"-"\u1021", + "\u1023"-"\u1027", + "\u1029"-"\u102a", + "\u102c"-"\u1032", + "\u1036"-"\u1039", + "\u1040"-"\u1049", + "\u1050"-"\u1059", + "\u10a0"-"\u10c5", + "\u10d0"-"\u10f6", + "\u1100"-"\u1159", + "\u115f"-"\u11a2", + "\u11a8"-"\u11f9", + "\u1200"-"\u1206", + "\u1208"-"\u1246", + "\u1248", + "\u124a"-"\u124d", + "\u1250"-"\u1256", + "\u1258", + "\u125a"-"\u125d", + "\u1260"-"\u1286", + "\u1288", + "\u128a"-"\u128d", + "\u1290"-"\u12ae", + "\u12b0", + "\u12b2"-"\u12b5", + "\u12b8"-"\u12be", + "\u12c0", + "\u12c2"-"\u12c5", + "\u12c8"-"\u12ce", + "\u12d0"-"\u12d6", + "\u12d8"-"\u12ee", + "\u12f0"-"\u130e", + "\u1310", + "\u1312"-"\u1315", + "\u1318"-"\u131e", + "\u1320"-"\u1346", + "\u1348"-"\u135a", + "\u1369"-"\u1371", + "\u13a0"-"\u13f4", + "\u1401"-"\u166c", + "\u166f"-"\u1676", + "\u1681"-"\u169a", + "\u16a0"-"\u16ea", + "\u1780"-"\u17d3", + "\u17db", + "\u17e0"-"\u17e9", + "\u180b"-"\u180e", + "\u1810"-"\u1819", + "\u1820"-"\u1877", + "\u1880"-"\u18a9", + "\u1e00"-"\u1e9b", + "\u1ea0"-"\u1ef9", + "\u1f00"-"\u1f15", + "\u1f18"-"\u1f1d", + "\u1f20"-"\u1f45", + "\u1f48"-"\u1f4d", + "\u1f50"-"\u1f57", + "\u1f59", + "\u1f5b", + "\u1f5d", + "\u1f5f"-"\u1f7d", + "\u1f80"-"\u1fb4", + "\u1fb6"-"\u1fbc", + "\u1fbe", + "\u1fc2"-"\u1fc4", + "\u1fc6"-"\u1fcc", + "\u1fd0"-"\u1fd3", + "\u1fd6"-"\u1fdb", + "\u1fe0"-"\u1fec", + "\u1ff2"-"\u1ff4", + "\u1ff6"-"\u1ffc", + "\u200c"-"\u200f", + "\u202a"-"\u202e", + "\u203f"-"\u2040", + "\u206a"-"\u206f", + "\u207f", + "\u20a0"-"\u20af", + "\u20d0"-"\u20dc", + "\u20e1", + "\u2102", + "\u2107", + "\u210a"-"\u2113", + "\u2115", + "\u2119"-"\u211d", + "\u2124", + "\u2126", + "\u2128", + "\u212a"-"\u212d", + "\u212f"-"\u2131", + "\u2133"-"\u2139", + "\u2160"-"\u2183", + "\u3005"-"\u3007", + "\u3021"-"\u302f", + "\u3031"-"\u3035", + "\u3038"-"\u303a", + "\u3041"-"\u3094", + "\u3099"-"\u309a", + "\u309d"-"\u309e", + "\u30a1"-"\u30fe", + "\u3105"-"\u312c", + "\u3131"-"\u318e", + "\u31a0"-"\u31b7", + "\u3400"-"\u4db5", + "\u4e00"-"\u9fa5", + "\ua000"-"\ua48c", + "\uac00"-"\ud7a3", + "\uf900"-"\ufa2d", + "\ufb00"-"\ufb06", + "\ufb13"-"\ufb17", + "\ufb1d"-"\ufb28", + "\ufb2a"-"\ufb36", + "\ufb38"-"\ufb3c", + "\ufb3e", + "\ufb40"-"\ufb41", + "\ufb43"-"\ufb44", + "\ufb46"-"\ufbb1", + "\ufbd3"-"\ufd3d", + "\ufd50"-"\ufd8f", + "\ufd92"-"\ufdc7", + "\ufdf0"-"\ufdfb", + "\ufe20"-"\ufe23", + "\ufe33"-"\ufe34", + "\ufe4d"-"\ufe4f", + "\ufe69", + "\ufe70"-"\ufe72", + "\ufe74", + "\ufe76"-"\ufefc", + "\ufeff", + "\uff04", + "\uff10"-"\uff19", + "\uff21"-"\uff3a", + "\uff3f", + "\uff41"-"\uff5a", + "\uff65"-"\uffbe", + "\uffc2"-"\uffc7", + "\uffca"-"\uffcf", + "\uffd2"-"\uffd7", + "\uffda"-"\uffdc", + "\uffe0"-"\uffe1", + "\uffe5"-"\uffe6", + "\ufff9"-"\ufffb" + ] + > +} + +/* SEPARATORS */ + +TOKEN : +{ + < LPAREN: "(" > +| < RPAREN: ")" > +| < LBRACE: "{" > +| < RBRACE: "}" > +| < LBRACKET: "[" > +| < RBRACKET: "]" > +| < SEMICOLON: ";" > +| < COMMA: "," > +| < DOT: "." > +| < AT: "@" > +} + +/* OPERATORS */ + +TOKEN : +{ + < ASSIGN: "=" > +| < LT: "<" > +| < BANG: "!" > +| < TILDE: "~" > +| < HOOK: "?" > +| < COLON: ":" > +| < EQ: "==" > +| < LE: "<=" > +| < GE: ">=" > +| < NE: "!=" > +| < SC_OR: "||" > +| < SC_AND: "&&" > +| < INCR: "++" > +| < DECR: "--" > +| < PLUS: "+" > +| < MINUS: "-" > +| < STAR: "*" > +| < SLASH: "/" > +| < BIT_AND: "&" > +| < BIT_OR: "|" > +| < XOR: "^" > +| < REM: "%" > +| < LSHIFT: "<<" > +| < PLUSASSIGN: "+=" > +| < MINUSASSIGN: "-=" > +| < STARASSIGN: "*=" > +| < SLASHASSIGN: "/=" > +| < ANDASSIGN: "&=" > +| < ORASSIGN: "|=" > +| < XORASSIGN: "^=" > +| < REMASSIGN: "%=" > +| < LSHIFTASSIGN: "<<=" > +| < RSIGNEDSHIFTASSIGN: ">>=" > +| < RUNSIGNEDSHIFTASSIGN: ">>>=" > +| < ELLIPSIS: "..." > +} + +/* >'s need special attention due to generics syntax. */ +TOKEN : +{ + < RUNSIGNEDSHIFT: ">>>" > + { + matchedToken.kind = GT; + ((Token.GTToken)matchedToken).realKind = RUNSIGNEDSHIFT; + input_stream.backup(2); + matchedToken.image = ">"; + } +| < RSIGNEDSHIFT: ">>" > + { + matchedToken.kind = GT; + ((Token.GTToken)matchedToken).realKind = RSIGNEDSHIFT; + input_stream.backup(1); + matchedToken.image = ">"; + } +| < GT: ">" > +} + +boolean Line() : +{ + int modifiers; +} +{ + <EOF> { + return true; + } +| + LOOKAHEAD(BlockStatement()) + BlockStatement() { + return false; + } +| + LOOKAHEAD(Modifiers() [ TypeParameters() ] [ ResultType() ] <IDENTIFIER> FormalParameters() [ "throws" NameList() ] "{") + ClassOrInterfaceBodyDeclaration(false) { + return false; + } +| + LOOKAHEAD(ClassOrInterfaceBodyDeclaration(false)) + ClassOrInterfaceBodyDeclaration(false) { + return false; + } +| + LOOKAHEAD(Expression()) + Expression() { + return false; + } +| + ImportDeclaration() { + return false; + } +} + +/***************************************** + * THE JAVA LANGUAGE GRAMMAR STARTS HERE * + *****************************************/ + +/* + * Program structuring syntax follows. + */ + +void CompilationUnit(): +{} +{ + [ LOOKAHEAD( ( Annotation() )* "package" ) PackageDeclaration() ] + ( ImportDeclaration() )* + ( TypeDeclaration() )* + ( < "\u001a" > )? + ( <STUFF_TO_IGNORE: ~[]> )? + <EOF> +} + +void PackageDeclaration(): +{} +{ + Modifiers() "package" Name() ";" +} + +void ImportDeclaration(): +{} +{ + "import" [ "static" ] Name() [ "." "*" ] ";" +} + +/* + * Modifiers. We match all modifiers in a single rule to reduce the chances of + * syntax errors for simple modifier mistakes. It will also enable us to give + * better error messages. + */ + +int Modifiers(): +{ + int modifiers = 0; +} +{ + ( + LOOKAHEAD(2) + ( + "public" { modifiers |= ModifierSet.PUBLIC; } + | + "static" { modifiers |= ModifierSet.STATIC; } + | + "protected" { modifiers |= ModifierSet.PROTECTED; } + | + "private" { modifiers |= ModifierSet.PRIVATE; } + | + "final" { modifiers |= ModifierSet.FINAL; } + | + "abstract" { modifiers |= ModifierSet.ABSTRACT; } + | + "synchronized" { modifiers |= ModifierSet.SYNCHRONIZED; } + | + "native" { modifiers |= ModifierSet.NATIVE; } + | + "transient" { modifiers |= ModifierSet.TRANSIENT; } + | + "volatile" { modifiers |= ModifierSet.VOLATILE; } + | + "strictfp" { modifiers |= ModifierSet.STRICTFP; } + | + Annotation() + ) + )* + + { + return modifiers; + } +} + +/* + * Declaration syntax follows. + */ +void TypeDeclaration(): +{ + int modifiers; +} +{ + ";" +| + modifiers = Modifiers() + ( + ClassOrInterfaceDeclaration(modifiers) + | + EnumDeclaration(modifiers) + | + AnnotationTypeDeclaration(modifiers) + ) +} + + +void ClassOrInterfaceDeclaration(int modifiers): +{ + boolean isInterface = false; +} +{ + ( "class" | "interface" { isInterface = true; } ) + <IDENTIFIER> + [ TypeParameters() ] + [ ExtendsList(isInterface) ] + [ ImplementsList(isInterface) ] + ClassOrInterfaceBody(isInterface) +} + +void ExtendsList(boolean isInterface): +{ + boolean extendsMoreThanOne = false; +} +{ + "extends" ClassOrInterfaceType() + ( "," ClassOrInterfaceType() { extendsMoreThanOne = true; } )* + { + if (extendsMoreThanOne && !isInterface) + throw new ParseException("A class cannot extend more than one other class"); + } +} + +void ImplementsList(boolean isInterface): +{} +{ + "implements" ClassOrInterfaceType() + ( "," ClassOrInterfaceType() )* + { + if (isInterface) + throw new ParseException("An interface cannot implement other interfaces"); + } +} + +void EnumDeclaration(int modifiers): +{} +{ + "enum" <IDENTIFIER> + [ ImplementsList(false) ] + EnumBody() +} + +void EnumBody(): +{} +{ + "{" + [ EnumConstant() ( LOOKAHEAD(2) "," EnumConstant() )* ] + [ "," ] + [ ";" ( ClassOrInterfaceBodyDeclaration(false) )* ] + "}" +} + +void EnumConstant(): +{} +{ + Modifiers() <IDENTIFIER> [ Arguments() ] [ ClassOrInterfaceBody(false) ] +} + +void TypeParameters(): +{} +{ + "<" TypeParameter() ( "," TypeParameter() )* ">" +} + +void TypeParameter(): +{} +{ + <IDENTIFIER> [ TypeBound() ] +} + +void TypeBound(): +{} +{ + "extends" ClassOrInterfaceType() ( "&" ClassOrInterfaceType() )* +} + +void ClassOrInterfaceBody(boolean isInterface): +{} +{ + "{" ( ClassOrInterfaceBodyDeclaration(isInterface) )* "}" +} + +void ClassOrInterfaceBodyDeclaration(boolean isInterface): +{ + boolean isNestedInterface = false; + int modifiers; +} +{ + LOOKAHEAD(2) + Initializer() + { + if (isInterface) + throw new ParseException("An interface cannot have initializers"); + } +| + modifiers = Modifiers() // Just get all the modifiers out of the way. If you want to do + // more checks, pass the modifiers down to the member + ( + ClassOrInterfaceDeclaration(modifiers) + | + EnumDeclaration(modifiers) + | + LOOKAHEAD( [ TypeParameters() ] <IDENTIFIER> "(" ) + ConstructorDeclaration() + | + LOOKAHEAD( Type() <IDENTIFIER> ( "[" "]" )* ( "," | "=" | ";" ) ) + FieldDeclaration(modifiers) + | + MethodDeclaration(modifiers) + ) +| + ";" +} + +void FieldDeclaration(int modifiers): +{} +{ + // Modifiers are already matched in the caller + Type() VariableDeclarator() ( "," VariableDeclarator() )* ";" +} + +void VariableDeclarator(): +{} +{ + VariableDeclaratorId() [ "=" VariableInitializer() ] +} + +void VariableDeclaratorId(): +{} +{ + <IDENTIFIER> ( "[" "]" )* +} + +void VariableInitializer(): +{} +{ + ArrayInitializer() +| + Expression() +} + +void ArrayInitializer(): +{} +{ + "{" [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}" +} + +void MethodDeclaration(int modifiers): +{} +{ + // Modifiers already matched in the caller! + [ TypeParameters() ] + ResultType() + MethodDeclarator() [ "throws" NameList() ] + ( Block() | ";" ) +} + +void MethodDeclarator(): +{} +{ + <IDENTIFIER> FormalParameters() ( "[" "]" )* +} + +void FormalParameters(): +{} +{ + "(" [ FormalParameter() ( "," FormalParameter() )* ] ")" +} + +void FormalParameter(): +{} +{ + Modifiers() Type() [ "..." ] VariableDeclaratorId() +} + +void ConstructorDeclaration(): +{} +{ + [ TypeParameters() ] + // Modifiers matched in the caller + <IDENTIFIER> FormalParameters() [ "throws" NameList() ] + "{" + [ LOOKAHEAD(ExplicitConstructorInvocation()) + ExplicitConstructorInvocation() + ] + ( BlockStatement() )* + "}" +} + +void ExplicitConstructorInvocation(): +{} +{ + ( <IDENTIFIER> "." )* [ LOOKAHEAD(2) "this" "." ] + [ TypeArguments() ] ("this"|"super") Arguments() ";" +} + +void Initializer(): +{} +{ + [ "static" ] Block() +} + + +/* + * Type, name and expression syntax follows. + */ + +void Type(): +{} +{ + LOOKAHEAD(2) ReferenceType() + | + PrimitiveType() +} + +void ReferenceType(): +{} +{ + PrimitiveType() ( LOOKAHEAD(2) "[" "]" )+ + | + ( ClassOrInterfaceType() ) ( LOOKAHEAD(2) "[" "]" )* +} + +void ClassOrInterfaceType(): +{} +{ + <IDENTIFIER> [ LOOKAHEAD(2) TypeArguments() ] + ( LOOKAHEAD(2) "." <IDENTIFIER> [ LOOKAHEAD(2) TypeArguments() ] )* +} + +void TypeArguments(): +{} +{ + "<" TypeArgument() ( "," TypeArgument() )* ">" +} + +void TypeArgument(): +{} +{ + ReferenceType() + | + "?" [ WildcardBounds() ] +} + +void WildcardBounds(): +{} +{ + "extends" ReferenceType() + | + "super" ReferenceType() +} + + +void PrimitiveType(): +{} +{ + "boolean" +| + "char" +| + "byte" +| + "short" +| + "int" +| + "long" +| + "float" +| + "double" +} + +void ResultType(): +{} +{ + "void" +| + Type() +} + +void Name(): +/* + * A lookahead of 2 is required below since "Name" can be followed + * by a ".*" when used in the context of an "ImportDeclaration". + */ +{} +{ + <IDENTIFIER> + ( LOOKAHEAD(2) "." <IDENTIFIER> + )* +} + +void NameList(): +{} +{ + Name() ( "," Name() )* +} + + +/* + * Expression syntax follows. + */ + +void Expression(): +/* + * This expansion has been written this way instead of: + * Assignment() | ConditionalExpression() + * for performance reasons. + * However, it is a weakening of the grammar for it allows the LHS of + * assignments to be any conditional expression whereas it can only be + * a primary expression. Consider adding a semantic predicate to work + * around this. + */ +{} +{ + ConditionalExpression() + [ + LOOKAHEAD(2) + AssignmentOperator() Expression() + ] +} + +void AssignmentOperator(): +{} +{ + "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|=" +} + +void AssignmentExpression(): +{} +{ + PrimaryExpression() AssignmentOperator() Expression() +} + +void ConditionalExpression(): +{} +{ + ConditionalOrExpression() [ "?" Expression() ":" Expression() ] +} + +void ConditionalOrExpression(): +{} +{ + ConditionalAndExpression() ( "||" ConditionalAndExpression() )* +} + +void ConditionalAndExpression(): +{} +{ + InclusiveOrExpression() ( "&&" InclusiveOrExpression() )* +} + +void InclusiveOrExpression(): +{} +{ + ExclusiveOrExpression() ( "|" ExclusiveOrExpression() )* +} + +void ExclusiveOrExpression(): +{} +{ + AndExpression() ( "^" AndExpression() )* +} + +void AndExpression(): +{} +{ + EqualityExpression() ( "&" EqualityExpression() )* +} + +void EqualityExpression(): +{} +{ + InstanceOfExpression() ( ( "==" | "!=" ) InstanceOfExpression() )* +} + +void InstanceOfExpression(): +{} +{ + RelationalExpression() [ "instanceof" Type() ] +} + +void RelationalExpression(): +{} +{ + ShiftExpression() ( ( "<" | ">" | "<=" | ">=" ) ShiftExpression() )* +} + +void ShiftExpression(): +{} +{ + AdditiveExpression() ( ( "<<" | RSIGNEDSHIFT() | RUNSIGNEDSHIFT() ) AdditiveExpression() )* +} + +void AdditiveExpression(): +{} +{ + MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )* +} + +void MultiplicativeExpression(): +{} +{ + UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )* +} + +void UnaryExpression(): +{} +{ + ( "+" | "-" ) UnaryExpression() +| + PreIncrementExpression() +| + PreDecrementExpression() +| + UnaryExpressionNotPlusMinus() +} + +void PreIncrementExpression(): +{} +{ + "++" PrimaryExpression() +} + +void PreDecrementExpression(): +{} +{ + "--" PrimaryExpression() +} + +void UnaryExpressionNotPlusMinus(): +{} +{ + ( "~" | "!" ) UnaryExpression() +| + LOOKAHEAD( CastLookahead() ) + CastExpression() +| + PostfixExpression() +} + +// This production is to determine lookahead only. The LOOKAHEAD specifications +// below are not used, but they are there just to indicate that we know about +// this. +void CastLookahead(): +{} +{ + LOOKAHEAD(2) + "(" PrimitiveType() +| + LOOKAHEAD("(" Type() "[") + "(" Type() "[" "]" +| + "(" Type() ")" ( "~" | "!" | "(" | <IDENTIFIER> | "this" | "super" | "new" | Literal() ) +} + +void PostfixExpression(): +{} +{ + PrimaryExpression() [ PostfixOperator() ] +} + +void PostfixOperator(): +{} +{ + "++" | "--" +} + +void CastExpression(): +{} +{ + LOOKAHEAD("(" PrimitiveType()) + "(" Type() ")" UnaryExpression() +| + "(" Type() ")" UnaryExpressionNotPlusMinus() +} + +void PrimaryExpression(): +{} +{ + PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )* +} + +void MemberSelector(): +{} +{ + "." TypeArguments() <IDENTIFIER> +} + +void PrimaryPrefix(): +{} +{ + Literal() +| + LOOKAHEAD( ( <IDENTIFIER> "." )* "this" ) + ( <IDENTIFIER> "." )* + "this" +| + "super" "." <IDENTIFIER> +| + "(" Expression() ")" +| + AllocationExpression() +| + LOOKAHEAD( ResultType() "." "class" ) + ResultType() "." "class" +| + Name() +} + +void PrimarySuffix(): +{} +{ + LOOKAHEAD("." "super" ".") + "." "super" +| + LOOKAHEAD("." "this") + "." "this" +| + LOOKAHEAD(2) + "." AllocationExpression() +| + LOOKAHEAD(3) + MemberSelector() +| + "[" Expression() "]" +| + "." <IDENTIFIER> +| + Arguments() +} + +void Literal(): +{} +{ + <INTEGER_LITERAL> +| + <FLOATING_POINT_LITERAL> +| + <CHARACTER_LITERAL> +| + <STRING_LITERAL> +| + BooleanLiteral() +| + NullLiteral() +} + +void BooleanLiteral(): +{} +{ + "true" +| + "false" +} + +void NullLiteral(): +{} +{ + "null" +} + +void Arguments(): +{} +{ + "(" [ ArgumentList() ] ")" +} + +void ArgumentList(): +{} +{ + Expression() ( "," Expression() )* +} + +void AllocationExpression(): +{} +{ + LOOKAHEAD(2) + "new" PrimitiveType() ArrayDimsAndInits() +| + "new" ClassOrInterfaceType() [ TypeArguments() ] + ( + ArrayDimsAndInits() + | + Arguments() [ ClassOrInterfaceBody(false) ] + ) +} + +/* + * The third LOOKAHEAD specification below is to parse to PrimarySuffix + * if there is an expression between the "[...]". + */ +void ArrayDimsAndInits(): +{} +{ + LOOKAHEAD(2) + ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )* +| + ( "[" "]" )+ ArrayInitializer() +} + + +/* + * Statement syntax follows. + */ + +void Statement(): +{} +{ + LOOKAHEAD(2) + LabeledStatement() +| + AssertStatement() +| + Block() +| + EmptyStatement() +| + StatementExpression() ";" +| + SwitchStatement() +| + IfStatement() +| + WhileStatement() +| + DoStatement() +| + ForStatement() +| + BreakStatement() +| + ContinueStatement() +| + ReturnStatement() +| + ThrowStatement() +| + SynchronizedStatement() +| + TryStatement() +} + +void AssertStatement(): +{} +{ + "assert" Expression() [ ":" Expression() ] ";" +} + +void LabeledStatement(): +{} +{ + <IDENTIFIER> ":" Statement() +} + +void Block(): +{} +{ + "{" ( BlockStatement() )* "}" +} + +void BlockStatement(): +{} +{ + LOOKAHEAD( Modifiers() Type() <IDENTIFIER> ) + LocalVariableDeclaration() ";" +| + Statement() +| + ClassOrInterfaceDeclaration(0) +} + +void LocalVariableDeclaration(): +{} +{ + Modifiers() Type() VariableDeclarator() ( "," VariableDeclarator() )* +} + +void EmptyStatement(): +{} +{ + ";" +} + +void StatementExpression(): +{} +{ + PreIncrementExpression() +| + PreDecrementExpression() +| + LOOKAHEAD(PrimaryExpression() AssignmentOperator()) + AssignmentExpression() +| + PostfixExpression() +} + +void SwitchStatement(): +{} +{ + "switch" "(" Expression() ")" "{" + ( SwitchLabel() ( BlockStatement() )* )* + "}" +} + +void SwitchLabel(): +{} +{ + "case" Expression() ":" +| + "default" ":" +} + +void IfStatement(): +/* + * The disambiguating algorithm of JavaCC automatically binds dangling + * else's to the innermost if statement. The LOOKAHEAD specification + * is to tell JavaCC that we know what we are doing. + */ +{} +{ + "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ] +} + +void WhileStatement(): +{} +{ + "while" "(" Expression() ")" Statement() +} + +void DoStatement(): +{} +{ + "do" Statement() "while" "(" Expression() ")" ";" +} + +void ForStatement(): +{} +{ + "for" "(" + + ( + LOOKAHEAD(Modifiers() Type() <IDENTIFIER> ":") + Modifiers() Type() <IDENTIFIER> ":" Expression() + | + [ ForInit() ] ";" [ Expression() ] ";" [ ForUpdate() ] + ) + + ")" Statement() +} + +void ForInit(): +{} +{ + LOOKAHEAD( Modifiers() Type() <IDENTIFIER> ) + LocalVariableDeclaration() +| + StatementExpressionList() +} + +void StatementExpressionList(): +{} +{ + StatementExpression() ( "," StatementExpression() )* +} + +void ForUpdate(): +{} +{ + StatementExpressionList() +} + +void BreakStatement(): +{} +{ + "break" [ <IDENTIFIER> ] ";" +} + +void ContinueStatement(): +{} +{ + "continue" [ <IDENTIFIER> ] ";" +} + +void ReturnStatement(): +{} +{ + "return" [ Expression() ] ";" +} + +void ThrowStatement(): +{} +{ + "throw" Expression() ";" +} + +void SynchronizedStatement(): +{} +{ + "synchronized" "(" Expression() ")" Block() +} + +void TryStatement(): +/* + * Semantic check required here to make sure that at least one + * finally/catch is present. + */ +{} +{ + "try" Block() + ( "catch" "(" FormalParameter() ")" Block() )* + [ "finally" Block() ] +} + +/* We use productions to match >>>, >> and > so that we can keep the + * type declaration syntax with generics clean + */ + +void RUNSIGNEDSHIFT(): +{} +{ + ( LOOKAHEAD({ getToken(1).kind == GT && + ((Token.GTToken)getToken(1)).realKind == RUNSIGNEDSHIFT} ) + ">" ">" ">" + ) +} + +void RSIGNEDSHIFT(): +{} +{ + ( LOOKAHEAD({ getToken(1).kind == GT && + ((Token.GTToken)getToken(1)).realKind == RSIGNEDSHIFT} ) + ">" ">" + ) +} + +/* Annotation syntax follows. */ + +void Annotation(): +{} +{ + LOOKAHEAD( "@" Name() "(" ( <IDENTIFIER> "=" | ")" )) + NormalAnnotation() + | + LOOKAHEAD( "@" Name() "(" ) + SingleMemberAnnotation() + | + MarkerAnnotation() +} + +void NormalAnnotation(): +{} +{ + "@" Name() "(" [ MemberValuePairs() ] ")" +} + +void MarkerAnnotation(): +{} +{ + "@" Name() +} + +void SingleMemberAnnotation(): +{} +{ + "@" Name() "(" MemberValue() ")" +} + +void MemberValuePairs(): +{} +{ + MemberValuePair() ( "," MemberValuePair() )* +} + +void MemberValuePair(): +{} +{ + <IDENTIFIER> "=" MemberValue() +} + +void MemberValue(): +{} +{ + Annotation() + | + MemberValueArrayInitializer() + | + ConditionalExpression() +} + +void MemberValueArrayInitializer(): +{} +{ + "{" MemberValue() ( LOOKAHEAD(2) "," MemberValue() )* [ "," ] "}" +} + + +/* Annotation Types. */ + +void AnnotationTypeDeclaration(int modifiers): +{} +{ + "@" "interface" <IDENTIFIER> AnnotationTypeBody() +} + +void AnnotationTypeBody(): +{} +{ + "{" ( AnnotationTypeMemberDeclaration() )* "}" +} + +void AnnotationTypeMemberDeclaration(): +{ + int modifiers; +} +{ + modifiers = Modifiers() + ( + LOOKAHEAD(Type() <IDENTIFIER> "(") + Type() <IDENTIFIER> "(" ")" [ DefaultValue() ] ";" + | + ClassOrInterfaceDeclaration(modifiers) + | + EnumDeclaration(modifiers) + | + AnnotationTypeDeclaration(modifiers) + | + FieldDeclaration(modifiers) + ) + | + ( ";" ) +} + +void DefaultValue(): +{} +{ + "default" MemberValue() +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaCharStream.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaCharStream.java new file mode 100644 index 0000000..1db31f6 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaCharStream.java @@ -0,0 +1,555 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 4.0 */ + +package jaxx.compiler.java.parser; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (with java-like unicode escape processing). + */ + +public class JavaCharStream { + public static final boolean staticFlag = false; + + static int hexval(char c) throws java.io.IOException { + switch (c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + + case 'a': + case 'A': + return 10; + case 'b': + case 'B': + return 11; + case 'c': + case 'C': + return 12; + case 'd': + case 'D': + return 13; + case 'e': + case 'E': + return 14; + case 'f': + case 'F': + return 15; + } + + throw new java.io.IOException(); // Should never come here + } + + public int bufpos = -1; + int bufsize; + int available; + int tokenBegin; + protected int bufline[]; + protected int bufcolumn[]; + + protected int column = 0; + protected int line = 1; + + protected boolean prevCharIsCR = false; + protected boolean prevCharIsLF = false; + + protected java.io.Reader inputStream; + + protected char[] nextCharBuf; + protected char[] buffer; + protected int maxNextCharInd = 0; + protected int nextCharInd = -1; + protected int inBuf = 0; + protected int tabSize = 8; + + protected void setTabSize(int i) { + tabSize = i; + } + + protected int getTabSize(int i) { + return tabSize; + } + + protected void ExpandBuff(boolean wrapAround) { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try { + if (wrapAround) { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, + bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + bufpos += (bufsize - tokenBegin); + } else { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + bufpos -= tokenBegin; + } + } + catch (Throwable t) { + throw new Error(t.getMessage()); + } + + available = (bufsize += 2048); + tokenBegin = 0; + } + + protected void FillBuff() throws java.io.IOException { + int i; + if (maxNextCharInd == 4096) + maxNextCharInd = nextCharInd = 0; + + try { + if ((i = inputStream.read(nextCharBuf, maxNextCharInd, + 4096 - maxNextCharInd)) == -1) { + inputStream.close(); + throw new java.io.IOException(); + } else { + maxNextCharInd += i; + } + } + catch (java.io.IOException e) { + if (bufpos != 0) { + --bufpos; + backup(0); + } else { + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + throw e; + } + } + + protected char ReadByte() throws java.io.IOException { + if (++nextCharInd >= maxNextCharInd) + FillBuff(); + + return nextCharBuf[nextCharInd]; + } + + public char BeginToken() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; + + if (++bufpos == bufsize) { + bufpos = 0; + } + + tokenBegin = bufpos; + return buffer[bufpos]; + } + + tokenBegin = 0; + bufpos = -1; + + return readChar(); + } + + protected void AdjustBuffSize() { + if (available == bufsize) { + if (tokenBegin > 2048) { + bufpos = 0; + available = tokenBegin; + } else + ExpandBuff(false); + } else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + protected void UpdateLineColumn(char c) { + column++; + + if (prevCharIsLF) { + prevCharIsLF = false; + line += (column = 1); + } else if (prevCharIsCR) { + prevCharIsCR = false; + if (c == '\n') { + prevCharIsLF = true; + } else + line += (column = 1); + } + + switch (c) { + case '\r': + prevCharIsCR = true; + break; + case '\n': + prevCharIsLF = true; + break; + case '\t': + column--; + column += (tabSize - (column % tabSize)); + break; + default: + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + + public char readChar() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + char c; + + if (++bufpos == available) + AdjustBuffSize(); + + if ((buffer[bufpos] = c = ReadByte()) == '\\') { + UpdateLineColumn(c); + + int backSlashCnt = 1; + + for (; ;) // Read all the backslashes + { + if (++bufpos == available) + AdjustBuffSize(); + + try { + if ((buffer[bufpos] = c = ReadByte()) != '\\') { + UpdateLineColumn(c); + // found a non-backslash char. + if ((c == 'u') && ((backSlashCnt & 1) == 1)) { + if (--bufpos < 0) + bufpos = bufsize - 1; + + break; + } + + backup(backSlashCnt); + return '\\'; + } + } + catch (java.io.IOException e) { + if (backSlashCnt > 1) + backup(backSlashCnt); + + return '\\'; + } + + UpdateLineColumn(c); + backSlashCnt++; + } + + // Here, we have seen an odd number of backslash's followed by a 'u' + try { + while ((c = ReadByte()) == 'u') + ++column; + + buffer[bufpos] = c = (char) (hexval(c) << 12 | + hexval(ReadByte()) << 8 | + hexval(ReadByte()) << 4 | + hexval(ReadByte())); + + column += 4; + } + catch (java.io.IOException e) { + throw new Error("Invalid escape character at line " + line + + " column " + column + "."); + } + + if (backSlashCnt == 1) + return c; + else { + backup(backSlashCnt - 1); + return '\\'; + } + } else { + UpdateLineColumn(c); + return (c); + } + } + + /** + * @return column index + * @see #getEndColumn + * @deprecated + */ + + public int getColumn() { + return bufcolumn[bufpos]; + } + + /** + * @return line type ??? + * @see #getEndLine + * @deprecated + */ + + public int getLine() { + return bufline[bufpos]; + } + + public int getEndColumn() { + return bufcolumn[bufpos]; + } + + public int getEndLine() { + return bufline[bufpos]; + } + + public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + public int getBeginLine() { + return bufline[tokenBegin]; + } + + public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + public JavaCharStream(java.io.Reader dstream, + int startline, int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + nextCharBuf = new char[4096]; + } + + public JavaCharStream(java.io.Reader dstream, + int startline, int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.Reader dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.Reader dstream, + int startline, int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + nextCharBuf = new char[4096]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + nextCharInd = bufpos = -1; + } + + public void ReInit(java.io.Reader dstream, + int startline, int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public void ReInit(java.io.Reader dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public JavaCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, int startline, + int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, 1, 1, 4096); + } + + public JavaCharStream(java.io.InputStream dstream) { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream) { + ReInit(dstream, 1, 1, 4096); + } + + public String GetImage() { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + public char[] GetSuffix(int len) { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + public void Done() { + nextCharBuf = null; + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + * + * @param newLine line number ? + * @param newCol column number ? + */ + public void adjustBeginLineColumn(int newLine, int newCol) { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) { + len = bufpos - tokenBegin + inBuf + 1; + } else { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k; + int nextColDiff, columnDiff = 0; + + while (i < len && + bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParser.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParser.java new file mode 100644 index 0000000..cbbfe0e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParser.java @@ -0,0 +1,10073 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParser.java */ + +package jaxx.compiler.java.parser; + +import java.io.File; +import java.io.FileInputStream; + +/** + * Grammar to parse Java version 1.5 + * + * @author Sreenivasa Viswanadha - Simplified and enhanced for 1.5 + */ +public class JavaParser/*@bgen(jjtree)*/ implements JavaParserTreeConstants, JavaParserConstants {/*@bgen(jjtree)*/ + protected JJTJavaParserState jjtree = new JJTJavaParserState(); + + /** Class to hold modifiers. */ + static public final class ModifierSet { + /* Definitions of the bits in the modifiers field. */ + public static final int PUBLIC = 0x0001; + public static final int PROTECTED = 0x0002; + public static final int PRIVATE = 0x0004; + public static final int ABSTRACT = 0x0008; + public static final int STATIC = 0x0010; + public static final int FINAL = 0x0020; + public static final int SYNCHRONIZED = 0x0040; + public static final int NATIVE = 0x0080; + public static final int TRANSIENT = 0x0100; + public static final int VOLATILE = 0x0200; + public static final int STRICTFP = 0x1000; + + /** + * A set of accessors that indicate whether the specified modifier + * is in the set. + */ + + public boolean isPublic(int modifiers) { + return (modifiers & PUBLIC) != 0; + } + + public boolean isProtected(int modifiers) { + return (modifiers & PROTECTED) != 0; + } + + public boolean isPrivate(int modifiers) { + return (modifiers & PRIVATE) != 0; + } + + public boolean isStatic(int modifiers) { + return (modifiers & STATIC) != 0; + } + + public boolean isAbstract(int modifiers) { + return (modifiers & ABSTRACT) != 0; + } + + public boolean isFinal(int modifiers) { + return (modifiers & FINAL) != 0; + } + + public boolean isNative(int modifiers) { + return (modifiers & NATIVE) != 0; + } + + public boolean isStrictfp(int modifiers) { + return (modifiers & STRICTFP) != 0; + } + + public boolean isSynchronized(int modifiers) { + return (modifiers & SYNCHRONIZED) != 0; + } + + public boolean isTransient(int modifiers) { + return (modifiers & TRANSIENT) != 0; + } + + public boolean isVolatile(int modifiers) { + return (modifiers & VOLATILE) != 0; + } + + /** Removes the given modifier. */ + static int removeModifier(int modifiers, int mod) { + return modifiers & ~mod; + } + } + + public JavaParser(String fileName) { + this(System.in); + try { + ReInit(new FileInputStream(new File(fileName))); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + void jjtreeOpenNodeScope(Node n) { + ((SimpleNode) n).firstToken = getToken(1); + } + + void jjtreeCloseNodeScope(Node n) { + ((SimpleNode) n).lastToken = getToken(0); + } + + public SimpleNode popNode() { + if (jjtree.nodeArity() > 0) // number of child nodes + return (SimpleNode) jjtree.popNode(); + else + return null; + } + + public static void main(String args[]) { + JavaParser parser; + if (args.length == 0) { + System.out.println("Java Parser Version 1.1: Reading from standard input . . ."); + parser = new JavaParser(System.in); + } else if (args.length == 1) { + System.out.println("Java Parser Version 1.1: Reading from file " + args[0] + " . . ."); + try { + parser = new JavaParser(new java.io.FileInputStream(args[0])); + } catch (java.io.FileNotFoundException e) { + System.out.println("Java Parser Version 1.1: File " + args[0] + " not found."); + return; + } + } else { + System.out.println("Java Parser Version 1.1: Usage is one of:"); + System.out.println(" java JavaParser < inputfile"); + System.out.println("OR"); + System.out.println(" java JavaParser inputfile"); + return; + } + try { + parser.CompilationUnit(); + System.out.println("Java Parser Version 1.1: Java program parsed successfully."); + } catch (ParseException e) { + System.out.println(e.getMessage()); + System.out.println("Java Parser Version 1.1: Encountered errors during parse."); + } + } + + final public boolean Line() throws ParseException { + /*@bgen(jjtree) Line */ + SimpleNode jjtn000 = new SimpleNode(JJTLINE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 0: + jj_consume_token(0); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return true; + } + break; + default: + if (jj_2_1(2147483647)) { + BlockStatement(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else if (jj_2_2(2147483647)) { + ClassOrInterfaceBodyDeclaration(false); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else if (jj_2_3(2147483647)) { + ClassOrInterfaceBodyDeclaration(false); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else if (jj_2_4(2147483647)) { + Expression(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPORT: + ImportDeclaration(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return false; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + throw new Error("Missing return statement in function"); + } + + /** + * ************************************** + * THE JAVA LANGUAGE GRAMMAR STARTS HERE * + * *************************************** + */ + +/* + * Program structuring syntax follows. + */ + final public void CompilationUnit() throws ParseException { + /*@bgen(jjtree) CompilationUnit */ + SimpleNode jjtn000 = new SimpleNode(JJTCOMPILATIONUNIT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_5(2147483647)) { + PackageDeclaration(); + } else { + ; + } + label_1: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPORT: + ; + break; + default: + break label_1; + } + ImportDeclaration(); + } + label_2: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case CLASS: + case ENUM: + case FINAL: + case INTERFACE: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case SEMICOLON: + case AT: + ; + break; + default: + break label_2; + } + TypeDeclaration(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case 123: + jj_consume_token(123); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STUFF_TO_IGNORE: + jj_consume_token(STUFF_TO_IGNORE); + break; + default: + ; + } + jj_consume_token(0); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PackageDeclaration() throws ParseException { + /*@bgen(jjtree) PackageDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTPACKAGEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + jj_consume_token(PACKAGE); + Name(); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ImportDeclaration() throws ParseException { + /*@bgen(jjtree) ImportDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTIMPORTDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IMPORT); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STATIC: + jj_consume_token(STATIC); + break; + default: + ; + } + Name(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case DOT: + jj_consume_token(DOT); + jj_consume_token(STAR); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Modifiers. We match all modifiers in a single rule to reduce the chances of + * syntax errors for simple modifier mistakes. It will also enable us to give + * better error messages. + */ + final public int Modifiers() throws ParseException { + /*@bgen(jjtree) Modifiers */ + SimpleNode jjtn000 = new SimpleNode(JJTMODIFIERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers = 0; + try { + label_3: + while (true) { + if (jj_2_6(2)) { + ; + } else { + break label_3; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PUBLIC: + jj_consume_token(PUBLIC); + modifiers |= ModifierSet.PUBLIC; + break; + case STATIC: + jj_consume_token(STATIC); + modifiers |= ModifierSet.STATIC; + break; + case PROTECTED: + jj_consume_token(PROTECTED); + modifiers |= ModifierSet.PROTECTED; + break; + case PRIVATE: + jj_consume_token(PRIVATE); + modifiers |= ModifierSet.PRIVATE; + break; + case FINAL: + jj_consume_token(FINAL); + modifiers |= ModifierSet.FINAL; + break; + case ABSTRACT: + jj_consume_token(ABSTRACT); + modifiers |= ModifierSet.ABSTRACT; + break; + case SYNCHRONIZED: + jj_consume_token(SYNCHRONIZED); + modifiers |= ModifierSet.SYNCHRONIZED; + break; + case NATIVE: + jj_consume_token(NATIVE); + modifiers |= ModifierSet.NATIVE; + break; + case TRANSIENT: + jj_consume_token(TRANSIENT); + modifiers |= ModifierSet.TRANSIENT; + break; + case VOLATILE: + jj_consume_token(VOLATILE); + modifiers |= ModifierSet.VOLATILE; + break; + case STRICTFP: + jj_consume_token(STRICTFP); + modifiers |= ModifierSet.STRICTFP; + break; + case AT: + Annotation(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + { + if (true) return modifiers; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + throw new Error("Missing return statement in function"); + } + + /* + * Declaration syntax follows. + */ + final public void TypeDeclaration() throws ParseException { + /*@bgen(jjtree) TypeDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + case ABSTRACT: + case CLASS: + case ENUM: + case FINAL: + case INTERFACE: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case AT: + modifiers = Modifiers(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(modifiers); + break; + case ENUM: + EnumDeclaration(modifiers); + break; + case AT: + AnnotationTypeDeclaration(modifiers); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + boolean isInterface = false; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + jj_consume_token(CLASS); + break; + case INTERFACE: + jj_consume_token(INTERFACE); + isInterface = true; + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeParameters(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + ExtendsList(isInterface); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPLEMENTS: + ImplementsList(isInterface); + break; + default: + ; + } + ClassOrInterfaceBody(isInterface); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ExtendsList(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ExtendsList */ + SimpleNode jjtn000 = new SimpleNode(JJTEXTENDSLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + boolean extendsMoreThanOne = false; + try { + jj_consume_token(EXTENDS); + ClassOrInterfaceType(); + label_4: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_4; + } + jj_consume_token(COMMA); + ClassOrInterfaceType(); + extendsMoreThanOne = true; + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + if (extendsMoreThanOne && !isInterface) { + if (true) + throw new ParseException("A class cannot extend more than one other class"); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ImplementsList(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ImplementsList */ + SimpleNode jjtn000 = new SimpleNode(JJTIMPLEMENTSLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IMPLEMENTS); + ClassOrInterfaceType(); + label_5: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_5; + } + jj_consume_token(COMMA); + ClassOrInterfaceType(); + } + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + if (isInterface) { + if (true) + throw new ParseException("An interface cannot implement other interfaces"); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EnumDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) EnumDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(ENUM); + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IMPLEMENTS: + ImplementsList(false); + break; + default: + ; + } + EnumBody(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EnumBody() throws ParseException { + /*@bgen(jjtree) EnumBody */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case FINAL: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case AT: + EnumConstant(); + label_6: + while (true) { + if (jj_2_7(2)) { + ; + } else { + break label_6; + } + jj_consume_token(COMMA); + EnumConstant(); + } + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SEMICOLON: + jj_consume_token(SEMICOLON); + label_7: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOID: + case VOLATILE: + case IDENTIFIER: + case LBRACE: + case SEMICOLON: + case AT: + case LT: + ; + break; + default: + break label_7; + } + ClassOrInterfaceBodyDeclaration(false); + } + break; + default: + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EnumConstant() throws ParseException { + /*@bgen(jjtree) EnumConstant */ + SimpleNode jjtn000 = new SimpleNode(JJTENUMCONSTANT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LPAREN: + Arguments(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + ClassOrInterfaceBody(false); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeParameters() throws ParseException { + /*@bgen(jjtree) TypeParameters */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LT); + TypeParameter(); + label_8: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_8; + } + jj_consume_token(COMMA); + TypeParameter(); + } + jj_consume_token(GT); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeParameter() throws ParseException { + /*@bgen(jjtree) TypeParameter */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEPARAMETER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + TypeBound(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeBound() throws ParseException { + /*@bgen(jjtree) TypeBound */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEBOUND); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(EXTENDS); + ClassOrInterfaceType(); + label_9: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BIT_AND: + ; + break; + default: + break label_9; + } + jj_consume_token(BIT_AND); + ClassOrInterfaceType(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceBody(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceBody */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + label_10: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOID: + case VOLATILE: + case IDENTIFIER: + case LBRACE: + case SEMICOLON: + case AT: + case LT: + ; + break; + default: + break label_10; + } + ClassOrInterfaceBodyDeclaration(isInterface); + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceBodyDeclaration(boolean isInterface) throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceBodyDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACEBODYDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + boolean isNestedInterface = false; + int modifiers; + try { + if (jj_2_10(2)) { + Initializer(); + jjtree.closeNodeScope(jjtn000, true); + jjtc000 = false; + jjtreeCloseNodeScope(jjtn000); + if (isInterface) { + if (true) + throw new ParseException("An interface cannot have initializers"); + } + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOID: + case VOLATILE: + case IDENTIFIER: + case AT: + case LT: + modifiers = Modifiers(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(modifiers); + break; + case ENUM: + EnumDeclaration(modifiers); + break; + default: + if (jj_2_8(2147483647)) { + ConstructorDeclaration(); + } else if (jj_2_9(2147483647)) { + FieldDeclaration(modifiers); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case VOID: + case IDENTIFIER: + case LT: + MethodDeclaration(modifiers); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + break; + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void FieldDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) FieldDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTFIELDDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Type(); + VariableDeclarator(); + label_11: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_11; + } + jj_consume_token(COMMA); + VariableDeclarator(); + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void VariableDeclarator() throws ParseException { + /*@bgen(jjtree) VariableDeclarator */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + VariableDeclaratorId(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSIGN: + jj_consume_token(ASSIGN); + VariableInitializer(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void VariableDeclaratorId() throws ParseException { + /*@bgen(jjtree) VariableDeclaratorId */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEDECLARATORID); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + label_12: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ; + break; + default: + break label_12; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void VariableInitializer() throws ParseException { + /*@bgen(jjtree) VariableInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTVARIABLEINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + ArrayInitializer(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + Expression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ArrayInitializer() throws ParseException { + /*@bgen(jjtree) ArrayInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTARRAYINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + VariableInitializer(); + label_13: + while (true) { + if (jj_2_11(2)) { + ; + } else { + break label_13; + } + jj_consume_token(COMMA); + VariableInitializer(); + } + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + break; + default: + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MethodDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) MethodDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeParameters(); + break; + default: + ; + } + ResultType(); + MethodDeclarator(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case THROWS: + jj_consume_token(THROWS); + NameList(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + Block(); + break; + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MethodDeclarator() throws ParseException { + /*@bgen(jjtree) MethodDeclarator */ + SimpleNode jjtn000 = new SimpleNode(JJTMETHODDECLARATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + FormalParameters(); + label_14: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ; + break; + default: + break label_14; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void FormalParameters() throws ParseException { + /*@bgen(jjtree) FormalParameters */ + SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETERS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FINAL: + case FLOAT: + case INT: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case AT: + FormalParameter(); + label_15: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_15; + } + jj_consume_token(COMMA); + FormalParameter(); + } + break; + default: + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void FormalParameter() throws ParseException { + /*@bgen(jjtree) FormalParameter */ + SimpleNode jjtn000 = new SimpleNode(JJTFORMALPARAMETER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + Type(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ELLIPSIS: + jj_consume_token(ELLIPSIS); + break; + default: + ; + } + VariableDeclaratorId(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConstructorDeclaration() throws ParseException { + /*@bgen(jjtree) ConstructorDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTCONSTRUCTORDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeParameters(); + break; + default: + ; + } + jj_consume_token(IDENTIFIER); + FormalParameters(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case THROWS: + jj_consume_token(THROWS); + NameList(); + break; + default: + ; + } + jj_consume_token(LBRACE); + if (jj_2_12(2147483647)) { + ExplicitConstructorInvocation(); + } else { + ; + } + label_16: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case ASSERT: + case BOOLEAN: + case BREAK: + case BYTE: + case CHAR: + case CLASS: + case CONTINUE: + case DO: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case FOR: + case IF: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case RETURN: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SWITCH: + case SYNCHRONIZED: + case THIS: + case THROW: + case TRANSIENT: + case TRUE: + case TRY: + case VOID: + case VOLATILE: + case WHILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case SEMICOLON: + case AT: + case INCR: + case DECR: + ; + break; + default: + break label_16; + } + BlockStatement(); + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ExplicitConstructorInvocation() throws ParseException { + /*@bgen(jjtree) ExplicitConstructorInvocation */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPLICITCONSTRUCTORINVOCATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + label_17: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + ; + break; + default: + break label_17; + } + jj_consume_token(IDENTIFIER); + jj_consume_token(DOT); + } + if (jj_2_13(2)) { + jj_consume_token(THIS); + jj_consume_token(DOT); + } else { + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeArguments(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case THIS: + jj_consume_token(THIS); + break; + case SUPER: + jj_consume_token(SUPER); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + Arguments(); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Initializer() throws ParseException { + /*@bgen(jjtree) Initializer */ + SimpleNode jjtn000 = new SimpleNode(JJTINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STATIC: + jj_consume_token(STATIC); + break; + default: + ; + } + Block(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Type, name and expression syntax follows. + */ + final public void Type() throws ParseException { + /*@bgen(jjtree) Type */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_14(2)) { + ReferenceType(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + PrimitiveType(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ReferenceType() throws ParseException { + /*@bgen(jjtree) ReferenceType */ + SimpleNode jjtn000 = new SimpleNode(JJTREFERENCETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + PrimitiveType(); + label_18: + while (true) { + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + if (jj_2_15(2)) { + ; + } else { + break label_18; + } + } + break; + case IDENTIFIER: + ClassOrInterfaceType(); + label_19: + while (true) { + if (jj_2_16(2)) { + ; + } else { + break label_19; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ClassOrInterfaceType() throws ParseException { + /*@bgen(jjtree) ClassOrInterfaceType */ + SimpleNode jjtn000 = new SimpleNode(JJTCLASSORINTERFACETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + if (jj_2_17(2)) { + TypeArguments(); + } else { + ; + } + label_20: + while (true) { + if (jj_2_18(2)) { + ; + } else { + break label_20; + } + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + if (jj_2_19(2)) { + TypeArguments(); + } else { + ; + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeArguments() throws ParseException { + /*@bgen(jjtree) TypeArguments */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LT); + TypeArgument(); + label_21: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_21; + } + jj_consume_token(COMMA); + TypeArgument(); + } + jj_consume_token(GT); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TypeArgument() throws ParseException { + /*@bgen(jjtree) TypeArgument */ + SimpleNode jjtn000 = new SimpleNode(JJTTYPEARGUMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case IDENTIFIER: + ReferenceType(); + break; + case HOOK: + jj_consume_token(HOOK); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + case SUPER: + WildcardBounds(); + break; + default: + ; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void WildcardBounds() throws ParseException { + /*@bgen(jjtree) WildcardBounds */ + SimpleNode jjtn000 = new SimpleNode(JJTWILDCARDBOUNDS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EXTENDS: + jj_consume_token(EXTENDS); + ReferenceType(); + break; + case SUPER: + jj_consume_token(SUPER); + ReferenceType(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimitiveType() throws ParseException { + /*@bgen(jjtree) PrimitiveType */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMITIVETYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + jj_consume_token(BOOLEAN); + break; + case CHAR: + jj_consume_token(CHAR); + break; + case BYTE: + jj_consume_token(BYTE); + break; + case SHORT: + jj_consume_token(SHORT); + break; + case INT: + jj_consume_token(INT); + break; + case LONG: + jj_consume_token(LONG); + break; + case FLOAT: + jj_consume_token(FLOAT); + break; + case DOUBLE: + jj_consume_token(DOUBLE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ResultType() throws ParseException { + /*@bgen(jjtree) ResultType */ + SimpleNode jjtn000 = new SimpleNode(JJTRESULTTYPE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case VOID: + jj_consume_token(VOID); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case IDENTIFIER: + Type(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Name() throws ParseException { + /*@bgen(jjtree) Name */ + SimpleNode jjtn000 = new SimpleNode(JJTNAME); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + label_22: + while (true) { + if (jj_2_20(2)) { + ; + } else { + break label_22; + } + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void NameList() throws ParseException { + /*@bgen(jjtree) NameList */ + SimpleNode jjtn000 = new SimpleNode(JJTNAMELIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Name(); + label_23: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_23; + } + jj_consume_token(COMMA); + Name(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Expression syntax follows. + */ + final public void Expression() throws ParseException { + /*@bgen(jjtree) Expression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ConditionalExpression(); + if (jj_2_21(2)) { + AssignmentOperator(); + Expression(); + } else { + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AssignmentOperator() throws ParseException { + /*@bgen(jjtree) AssignmentOperator */ + SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTOPERATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSIGN: + jj_consume_token(ASSIGN); + break; + case STARASSIGN: + jj_consume_token(STARASSIGN); + break; + case SLASHASSIGN: + jj_consume_token(SLASHASSIGN); + break; + case REMASSIGN: + jj_consume_token(REMASSIGN); + break; + case PLUSASSIGN: + jj_consume_token(PLUSASSIGN); + break; + case MINUSASSIGN: + jj_consume_token(MINUSASSIGN); + break; + case LSHIFTASSIGN: + jj_consume_token(LSHIFTASSIGN); + break; + case RSIGNEDSHIFTASSIGN: + jj_consume_token(RSIGNEDSHIFTASSIGN); + break; + case RUNSIGNEDSHIFTASSIGN: + jj_consume_token(RUNSIGNEDSHIFTASSIGN); + break; + case ANDASSIGN: + jj_consume_token(ANDASSIGN); + break; + case XORASSIGN: + jj_consume_token(XORASSIGN); + break; + case ORASSIGN: + jj_consume_token(ORASSIGN); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AssignmentExpression() throws ParseException { + /*@bgen(jjtree) AssignmentExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTASSIGNMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + PrimaryExpression(); + AssignmentOperator(); + Expression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConditionalExpression() throws ParseException { + /*@bgen(jjtree) ConditionalExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ConditionalOrExpression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case HOOK: + jj_consume_token(HOOK); + Expression(); + jj_consume_token(COLON); + Expression(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConditionalOrExpression() throws ParseException { + /*@bgen(jjtree) ConditionalOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ConditionalAndExpression(); + label_24: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SC_OR: + ; + break; + default: + break label_24; + } + jj_consume_token(SC_OR); + ConditionalAndExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ConditionalAndExpression() throws ParseException { + /*@bgen(jjtree) ConditionalAndExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCONDITIONALANDEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + InclusiveOrExpression(); + label_25: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SC_AND: + ; + break; + default: + break label_25; + } + jj_consume_token(SC_AND); + InclusiveOrExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void InclusiveOrExpression() throws ParseException { + /*@bgen(jjtree) InclusiveOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTINCLUSIVEOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ExclusiveOrExpression(); + label_26: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BIT_OR: + ; + break; + default: + break label_26; + } + jj_consume_token(BIT_OR); + ExclusiveOrExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ExclusiveOrExpression() throws ParseException { + /*@bgen(jjtree) ExclusiveOrExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTEXCLUSIVEOREXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + AndExpression(); + label_27: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case XOR: + ; + break; + default: + break label_27; + } + jj_consume_token(XOR); + AndExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AndExpression() throws ParseException { + /*@bgen(jjtree) AndExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTANDEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + EqualityExpression(); + label_28: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BIT_AND: + ; + break; + default: + break label_28; + } + jj_consume_token(BIT_AND); + EqualityExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EqualityExpression() throws ParseException { + /*@bgen(jjtree) EqualityExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTEQUALITYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + InstanceOfExpression(); + label_29: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EQ: + case NE: + ; + break; + default: + break label_29; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case EQ: + jj_consume_token(EQ); + break; + case NE: + jj_consume_token(NE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + InstanceOfExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void InstanceOfExpression() throws ParseException { + /*@bgen(jjtree) InstanceOfExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTINSTANCEOFEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + RelationalExpression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INSTANCEOF: + jj_consume_token(INSTANCEOF); + Type(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void RelationalExpression() throws ParseException { + /*@bgen(jjtree) RelationalExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTRELATIONALEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + ShiftExpression(); + label_30: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + case LE: + case GE: + case GT: + ; + break; + default: + break label_30; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + jj_consume_token(LT); + break; + case GT: + jj_consume_token(GT); + break; + case LE: + jj_consume_token(LE); + break; + case GE: + jj_consume_token(GE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + ShiftExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ShiftExpression() throws ParseException { + /*@bgen(jjtree) ShiftExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTSHIFTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + AdditiveExpression(); + label_31: + while (true) { + if (jj_2_22(1)) { + ; + } else { + break label_31; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LSHIFT: + jj_consume_token(LSHIFT); + break; + default: + if (jj_2_23(1)) { + RSIGNEDSHIFT(); + } else if (jj_2_24(1)) { + RUNSIGNEDSHIFT(); + } else { + jj_consume_token(-1); + throw new ParseException(); + } + } + AdditiveExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AdditiveExpression() throws ParseException { + /*@bgen(jjtree) AdditiveExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTADDITIVEEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + MultiplicativeExpression(); + label_32: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + case MINUS: + ; + break; + default: + break label_32; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + jj_consume_token(PLUS); + break; + case MINUS: + jj_consume_token(MINUS); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + MultiplicativeExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MultiplicativeExpression() throws ParseException { + /*@bgen(jjtree) MultiplicativeExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTMULTIPLICATIVEEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + UnaryExpression(); + label_33: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STAR: + case SLASH: + case REM: + ; + break; + default: + break label_33; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case STAR: + jj_consume_token(STAR); + break; + case SLASH: + jj_consume_token(SLASH); + break; + case REM: + jj_consume_token(REM); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + UnaryExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void UnaryExpression() throws ParseException { + /*@bgen(jjtree) UnaryExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + case MINUS: + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case PLUS: + jj_consume_token(PLUS); + break; + case MINUS: + jj_consume_token(MINUS); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + UnaryExpression(); + break; + case INCR: + PreIncrementExpression(); + break; + case DECR: + PreDecrementExpression(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + UnaryExpressionNotPlusMinus(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PreIncrementExpression() throws ParseException { + /*@bgen(jjtree) PreIncrementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPREINCREMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(INCR); + PrimaryExpression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PreDecrementExpression() throws ParseException { + /*@bgen(jjtree) PreDecrementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPREDECREMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(DECR); + PrimaryExpression(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void UnaryExpressionNotPlusMinus() throws ParseException { + /*@bgen(jjtree) UnaryExpressionNotPlusMinus */ + SimpleNode jjtn000 = new SimpleNode(JJTUNARYEXPRESSIONNOTPLUSMINUS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BANG: + case TILDE: + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case TILDE: + jj_consume_token(TILDE); + break; + case BANG: + jj_consume_token(BANG); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + UnaryExpression(); + break; + default: + if (jj_2_25(2147483647)) { + CastExpression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + PostfixExpression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + +// This production is to determine lookahead only. The LOOKAHEAD specifications +// below are not used, but they are there just to indicate that we know about + + // this. + final public void CastLookahead() throws ParseException { + /*@bgen(jjtree) CastLookahead */ + SimpleNode jjtn000 = new SimpleNode(JJTCASTLOOKAHEAD); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_26(2)) { + jj_consume_token(LPAREN); + PrimitiveType(); + } else if (jj_2_27(2147483647)) { + jj_consume_token(LPAREN); + Type(); + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LPAREN: + jj_consume_token(LPAREN); + Type(); + jj_consume_token(RPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case TILDE: + jj_consume_token(TILDE); + break; + case BANG: + jj_consume_token(BANG); + break; + case LPAREN: + jj_consume_token(LPAREN); + break; + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + case THIS: + jj_consume_token(THIS); + break; + case SUPER: + jj_consume_token(SUPER); + break; + case NEW: + jj_consume_token(NEW); + break; + case FALSE: + case NULL: + case TRUE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + Literal(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PostfixExpression() throws ParseException { + /*@bgen(jjtree) PostfixExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + PrimaryExpression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INCR: + case DECR: + PostfixOperator(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PostfixOperator() throws ParseException { + /*@bgen(jjtree) PostfixOperator */ + SimpleNode jjtn000 = new SimpleNode(JJTPOSTFIXOPERATOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INCR: + jj_consume_token(INCR); + break; + case DECR: + jj_consume_token(DECR); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void CastExpression() throws ParseException { + /*@bgen(jjtree) CastExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTCASTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_28(2147483647)) { + jj_consume_token(LPAREN); + Type(); + jj_consume_token(RPAREN); + UnaryExpression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LPAREN: + jj_consume_token(LPAREN); + Type(); + jj_consume_token(RPAREN); + UnaryExpressionNotPlusMinus(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimaryExpression() throws ParseException { + /*@bgen(jjtree) PrimaryExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + PrimaryPrefix(); + label_34: + while (true) { + if (jj_2_29(2)) { + ; + } else { + break label_34; + } + PrimarySuffix(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberSelector() throws ParseException { + /*@bgen(jjtree) MemberSelector */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERSELECTOR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(DOT); + TypeArguments(); + jj_consume_token(IDENTIFIER); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimaryPrefix() throws ParseException { + /*@bgen(jjtree) PrimaryPrefix */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYPREFIX); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case FALSE: + case NULL: + case TRUE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + Literal(); + break; + default: + if (jj_2_30(2147483647)) { + label_35: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + ; + break; + default: + break label_35; + } + jj_consume_token(IDENTIFIER); + jj_consume_token(DOT); + } + jj_consume_token(THIS); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case SUPER: + jj_consume_token(SUPER); + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + break; + case LPAREN: + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + break; + case NEW: + AllocationExpression(); + break; + default: + if (jj_2_31(2147483647)) { + ResultType(); + jj_consume_token(DOT); + jj_consume_token(CLASS); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + Name(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void PrimarySuffix() throws ParseException { + /*@bgen(jjtree) PrimarySuffix */ + SimpleNode jjtn000 = new SimpleNode(JJTPRIMARYSUFFIX); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_32(2147483647)) { + jj_consume_token(DOT); + jj_consume_token(SUPER); + } else if (jj_2_33(2147483647)) { + jj_consume_token(DOT); + jj_consume_token(THIS); + } else if (jj_2_34(2)) { + jj_consume_token(DOT); + AllocationExpression(); + } else if (jj_2_35(3)) { + MemberSelector(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + jj_consume_token(LBRACKET); + Expression(); + jj_consume_token(RBRACKET); + break; + case DOT: + jj_consume_token(DOT); + jj_consume_token(IDENTIFIER); + break; + case LPAREN: + Arguments(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Literal() throws ParseException { + /*@bgen(jjtree) Literal */ + SimpleNode jjtn000 = new SimpleNode(JJTLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INTEGER_LITERAL: + jj_consume_token(INTEGER_LITERAL); + break; + case FLOATING_POINT_LITERAL: + jj_consume_token(FLOATING_POINT_LITERAL); + break; + case CHARACTER_LITERAL: + jj_consume_token(CHARACTER_LITERAL); + break; + case STRING_LITERAL: + jj_consume_token(STRING_LITERAL); + break; + case FALSE: + case TRUE: + BooleanLiteral(); + break; + case NULL: + NullLiteral(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void BooleanLiteral() throws ParseException { + /*@bgen(jjtree) BooleanLiteral */ + SimpleNode jjtn000 = new SimpleNode(JJTBOOLEANLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case TRUE: + jj_consume_token(TRUE); + break; + case FALSE: + jj_consume_token(FALSE); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void NullLiteral() throws ParseException { + /*@bgen(jjtree) NullLiteral */ + SimpleNode jjtn000 = new SimpleNode(JJTNULLLITERAL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(NULL); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Arguments() throws ParseException { + /*@bgen(jjtree) Arguments */ + SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + ArgumentList(); + break; + default: + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ArgumentList() throws ParseException { + /*@bgen(jjtree) ArgumentList */ + SimpleNode jjtn000 = new SimpleNode(JJTARGUMENTLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Expression(); + label_36: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_36; + } + jj_consume_token(COMMA); + Expression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AllocationExpression() throws ParseException { + /*@bgen(jjtree) AllocationExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTALLOCATIONEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_36(2)) { + jj_consume_token(NEW); + PrimitiveType(); + ArrayDimsAndInits(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case NEW: + jj_consume_token(NEW); + ClassOrInterfaceType(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LT: + TypeArguments(); + break; + default: + ; + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ArrayDimsAndInits(); + break; + case LPAREN: + Arguments(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACE: + ClassOrInterfaceBody(false); + break; + default: + ; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * The third LOOKAHEAD specification below is to parse to PrimarySuffix + * if there is an expression between the "[...]". + */ + final public void ArrayDimsAndInits() throws ParseException { + /*@bgen(jjtree) ArrayDimsAndInits */ + SimpleNode jjtn000 = new SimpleNode(JJTARRAYDIMSANDINITS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_39(2)) { + label_37: + while (true) { + jj_consume_token(LBRACKET); + Expression(); + jj_consume_token(RBRACKET); + if (jj_2_37(2)) { + ; + } else { + break label_37; + } + } + label_38: + while (true) { + if (jj_2_38(2)) { + ; + } else { + break label_38; + } + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + } + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + label_39: + while (true) { + jj_consume_token(LBRACKET); + jj_consume_token(RBRACKET); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case LBRACKET: + ; + break; + default: + break label_39; + } + } + ArrayInitializer(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* + * Statement syntax follows. + */ + final public void Statement() throws ParseException { + /*@bgen(jjtree) Statement */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_40(2)) { + LabeledStatement(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSERT: + AssertStatement(); + break; + case LBRACE: + Block(); + break; + case SEMICOLON: + EmptyStatement(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case INCR: + case DECR: + StatementExpression(); + jj_consume_token(SEMICOLON); + break; + case SWITCH: + SwitchStatement(); + break; + case IF: + IfStatement(); + break; + case WHILE: + WhileStatement(); + break; + case DO: + DoStatement(); + break; + case FOR: + ForStatement(); + break; + case BREAK: + BreakStatement(); + break; + case CONTINUE: + ContinueStatement(); + break; + case RETURN: + ReturnStatement(); + break; + case THROW: + ThrowStatement(); + break; + case SYNCHRONIZED: + SynchronizedStatement(); + break; + case TRY: + TryStatement(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AssertStatement() throws ParseException { + /*@bgen(jjtree) AssertStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTASSERTSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(ASSERT); + Expression(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COLON: + jj_consume_token(COLON); + Expression(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void LabeledStatement() throws ParseException { + /*@bgen(jjtree) LabeledStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTLABELEDSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + jj_consume_token(COLON); + Statement(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void Block() throws ParseException { + /*@bgen(jjtree) Block */ + SimpleNode jjtn000 = new SimpleNode(JJTBLOCK); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + label_40: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case ASSERT: + case BOOLEAN: + case BREAK: + case BYTE: + case CHAR: + case CLASS: + case CONTINUE: + case DO: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case FOR: + case IF: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case RETURN: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SWITCH: + case SYNCHRONIZED: + case THIS: + case THROW: + case TRANSIENT: + case TRUE: + case TRY: + case VOID: + case VOLATILE: + case WHILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case SEMICOLON: + case AT: + case INCR: + case DECR: + ; + break; + default: + break label_40; + } + BlockStatement(); + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void BlockStatement() throws ParseException { + /*@bgen(jjtree) BlockStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTBLOCKSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_41(2147483647)) { + LocalVariableDeclaration(); + jj_consume_token(SEMICOLON); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ASSERT: + case BOOLEAN: + case BREAK: + case BYTE: + case CHAR: + case CONTINUE: + case DO: + case DOUBLE: + case FALSE: + case FLOAT: + case FOR: + case IF: + case INT: + case LONG: + case NEW: + case NULL: + case RETURN: + case SHORT: + case SUPER: + case SWITCH: + case SYNCHRONIZED: + case THIS: + case THROW: + case TRUE: + case TRY: + case VOID: + case WHILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case SEMICOLON: + case INCR: + case DECR: + Statement(); + break; + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(0); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void LocalVariableDeclaration() throws ParseException { + /*@bgen(jjtree) LocalVariableDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTLOCALVARIABLEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + Modifiers(); + Type(); + VariableDeclarator(); + label_41: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_41; + } + jj_consume_token(COMMA); + VariableDeclarator(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void EmptyStatement() throws ParseException { + /*@bgen(jjtree) EmptyStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTEMPTYSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(SEMICOLON); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void StatementExpression() throws ParseException { + /*@bgen(jjtree) StatementExpression */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case INCR: + PreIncrementExpression(); + break; + case DECR: + PreDecrementExpression(); + break; + default: + if (jj_2_42(2147483647)) { + AssignmentExpression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + PostfixExpression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SwitchStatement() throws ParseException { + /*@bgen(jjtree) SwitchStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTSWITCHSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(SWITCH); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + jj_consume_token(LBRACE); + label_42: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CASE: + case _DEFAULT: + ; + break; + default: + break label_42; + } + SwitchLabel(); + label_43: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case ASSERT: + case BOOLEAN: + case BREAK: + case BYTE: + case CHAR: + case CLASS: + case CONTINUE: + case DO: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case FOR: + case IF: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case RETURN: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SWITCH: + case SYNCHRONIZED: + case THIS: + case THROW: + case TRANSIENT: + case TRUE: + case TRY: + case VOID: + case VOLATILE: + case WHILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case LBRACE: + case SEMICOLON: + case AT: + case INCR: + case DECR: + ; + break; + default: + break label_43; + } + BlockStatement(); + } + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SwitchLabel() throws ParseException { + /*@bgen(jjtree) SwitchLabel */ + SimpleNode jjtn000 = new SimpleNode(JJTSWITCHLABEL); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CASE: + jj_consume_token(CASE); + Expression(); + jj_consume_token(COLON); + break; + case _DEFAULT: + jj_consume_token(_DEFAULT); + jj_consume_token(COLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void IfStatement() throws ParseException { + /*@bgen(jjtree) IfStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTIFSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IF); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + Statement(); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ELSE: + jj_consume_token(ELSE); + Statement(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void WhileStatement() throws ParseException { + /*@bgen(jjtree) WhileStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTWHILESTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(WHILE); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + Statement(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void DoStatement() throws ParseException { + /*@bgen(jjtree) DoStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTDOSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(DO); + Statement(); + jj_consume_token(WHILE); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ForStatement() throws ParseException { + /*@bgen(jjtree) ForStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTFORSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(FOR); + jj_consume_token(LPAREN); + if (jj_2_43(2147483647)) { + Modifiers(); + Type(); + jj_consume_token(IDENTIFIER); + jj_consume_token(COLON); + Expression(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case INT: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SYNCHRONIZED: + case THIS: + case TRANSIENT: + case TRUE: + case VOID: + case VOLATILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case SEMICOLON: + case AT: + case INCR: + case DECR: + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FINAL: + case FLOAT: + case INT: + case LONG: + case NATIVE: + case NEW: + case NULL: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SUPER: + case SYNCHRONIZED: + case THIS: + case TRANSIENT: + case TRUE: + case VOID: + case VOLATILE: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case AT: + case INCR: + case DECR: + ForInit(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + Expression(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case INCR: + case DECR: + ForUpdate(); + break; + default: + ; + } + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + jj_consume_token(RPAREN); + Statement(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ForInit() throws ParseException { + /*@bgen(jjtree) ForInit */ + SimpleNode jjtn000 = new SimpleNode(JJTFORINIT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_44(2147483647)) { + LocalVariableDeclaration(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case INCR: + case DECR: + StatementExpressionList(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void StatementExpressionList() throws ParseException { + /*@bgen(jjtree) StatementExpressionList */ + SimpleNode jjtn000 = new SimpleNode(JJTSTATEMENTEXPRESSIONLIST); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + StatementExpression(); + label_44: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_44; + } + jj_consume_token(COMMA); + StatementExpression(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ForUpdate() throws ParseException { + /*@bgen(jjtree) ForUpdate */ + SimpleNode jjtn000 = new SimpleNode(JJTFORUPDATE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + StatementExpressionList(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void BreakStatement() throws ParseException { + /*@bgen(jjtree) BreakStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTBREAKSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(BREAK); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ContinueStatement() throws ParseException { + /*@bgen(jjtree) ContinueStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTCONTINUESTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(CONTINUE); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + jj_consume_token(IDENTIFIER); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ReturnStatement() throws ParseException { + /*@bgen(jjtree) ReturnStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTRETURNSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(RETURN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + Expression(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void ThrowStatement() throws ParseException { + /*@bgen(jjtree) ThrowStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTTHROWSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(THROW); + Expression(); + jj_consume_token(SEMICOLON); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SynchronizedStatement() throws ParseException { + /*@bgen(jjtree) SynchronizedStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTSYNCHRONIZEDSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(SYNCHRONIZED); + jj_consume_token(LPAREN); + Expression(); + jj_consume_token(RPAREN); + Block(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void TryStatement() throws ParseException { + /*@bgen(jjtree) TryStatement */ + SimpleNode jjtn000 = new SimpleNode(JJTTRYSTATEMENT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(TRY); + Block(); + label_45: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CATCH: + ; + break; + default: + break label_45; + } + jj_consume_token(CATCH); + jj_consume_token(LPAREN); + FormalParameter(); + jj_consume_token(RPAREN); + Block(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case FINALLY: + jj_consume_token(FINALLY); + Block(); + break; + default: + ; + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* We use productions to match >>>, >> and > so that we can keep the + * type declaration syntax with generics clean + */ + final public void RUNSIGNEDSHIFT() throws ParseException { + /*@bgen(jjtree) RUNSIGNEDSHIFT */ + SimpleNode jjtn000 = new SimpleNode(JJTRUNSIGNEDSHIFT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RUNSIGNEDSHIFT) { + + } else { + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(GT); + jj_consume_token(GT); + jj_consume_token(GT); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void RSIGNEDSHIFT() throws ParseException { + /*@bgen(jjtree) RSIGNEDSHIFT */ + SimpleNode jjtn000 = new SimpleNode(JJTRSIGNEDSHIFT); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RSIGNEDSHIFT) { + + } else { + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(GT); + jj_consume_token(GT); + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* Annotation syntax follows. */ + final public void Annotation() throws ParseException { + /*@bgen(jjtree) Annotation */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + if (jj_2_45(2147483647)) { + NormalAnnotation(); + } else if (jj_2_46(2147483647)) { + SingleMemberAnnotation(); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case AT: + MarkerAnnotation(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void NormalAnnotation() throws ParseException { + /*@bgen(jjtree) NormalAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTNORMALANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + Name(); + jj_consume_token(LPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case IDENTIFIER: + MemberValuePairs(); + break; + default: + ; + } + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MarkerAnnotation() throws ParseException { + /*@bgen(jjtree) MarkerAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTMARKERANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + Name(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void SingleMemberAnnotation() throws ParseException { + /*@bgen(jjtree) SingleMemberAnnotation */ + SimpleNode jjtn000 = new SimpleNode(JJTSINGLEMEMBERANNOTATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + Name(); + jj_consume_token(LPAREN); + MemberValue(); + jj_consume_token(RPAREN); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValuePairs() throws ParseException { + /*@bgen(jjtree) MemberValuePairs */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIRS); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + MemberValuePair(); + label_46: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + ; + break; + default: + break label_46; + } + jj_consume_token(COMMA); + MemberValuePair(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValuePair() throws ParseException { + /*@bgen(jjtree) MemberValuePair */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEPAIR); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(IDENTIFIER); + jj_consume_token(ASSIGN); + MemberValue(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValue() throws ParseException { + /*@bgen(jjtree) MemberValue */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case AT: + Annotation(); + break; + case LBRACE: + MemberValueArrayInitializer(); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FALSE: + case FLOAT: + case INT: + case LONG: + case NEW: + case NULL: + case SHORT: + case SUPER: + case THIS: + case TRUE: + case VOID: + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case CHARACTER_LITERAL: + case STRING_LITERAL: + case IDENTIFIER: + case LPAREN: + case BANG: + case TILDE: + case INCR: + case DECR: + case PLUS: + case MINUS: + ConditionalExpression(); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void MemberValueArrayInitializer() throws ParseException { + /*@bgen(jjtree) MemberValueArrayInitializer */ + SimpleNode jjtn000 = new SimpleNode(JJTMEMBERVALUEARRAYINITIALIZER); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + MemberValue(); + label_47: + while (true) { + if (jj_2_47(2)) { + ; + } else { + break label_47; + } + jj_consume_token(COMMA); + MemberValue(); + } + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case COMMA: + jj_consume_token(COMMA); + break; + default: + ; + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + /* Annotation Types. */ + final public void AnnotationTypeDeclaration(int modifiers) throws ParseException { + /*@bgen(jjtree) AnnotationTypeDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(AT); + jj_consume_token(INTERFACE); + jj_consume_token(IDENTIFIER); + AnnotationTypeBody(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnnotationTypeBody() throws ParseException { + /*@bgen(jjtree) AnnotationTypeBody */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEBODY); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(LBRACE); + label_48: + while (true) { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case SEMICOLON: + case AT: + ; + break; + default: + break label_48; + } + AnnotationTypeMemberDeclaration(); + } + jj_consume_token(RBRACE); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void AnnotationTypeMemberDeclaration() throws ParseException { + /*@bgen(jjtree) AnnotationTypeMemberDeclaration */ + SimpleNode jjtn000 = new SimpleNode(JJTANNOTATIONTYPEMEMBERDECLARATION); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + int modifiers; + try { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case ABSTRACT: + case BOOLEAN: + case BYTE: + case CHAR: + case CLASS: + case DOUBLE: + case ENUM: + case FINAL: + case FLOAT: + case INT: + case INTERFACE: + case LONG: + case NATIVE: + case PRIVATE: + case PROTECTED: + case PUBLIC: + case SHORT: + case STATIC: + case STRICTFP: + case SYNCHRONIZED: + case TRANSIENT: + case VOLATILE: + case IDENTIFIER: + case AT: + modifiers = Modifiers(); + if (jj_2_48(2147483647)) { + Type(); + jj_consume_token(IDENTIFIER); + jj_consume_token(LPAREN); + jj_consume_token(RPAREN); + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case _DEFAULT: + DefaultValue(); + break; + default: + ; + } + jj_consume_token(SEMICOLON); + } else { + switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk) { + case CLASS: + case INTERFACE: + ClassOrInterfaceDeclaration(modifiers); + break; + case ENUM: + EnumDeclaration(modifiers); + break; + case AT: + AnnotationTypeDeclaration(modifiers); + break; + case BOOLEAN: + case BYTE: + case CHAR: + case DOUBLE: + case FLOAT: + case INT: + case LONG: + case SHORT: + case IDENTIFIER: + FieldDeclaration(modifiers); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } + break; + case SEMICOLON: + jj_consume_token(SEMICOLON); + break; + default: + jj_consume_token(-1); + throw new ParseException(); + } + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final public void DefaultValue() throws ParseException { + /*@bgen(jjtree) DefaultValue */ + SimpleNode jjtn000 = new SimpleNode(JJTDEFAULTVALUE); + boolean jjtc000 = true; + jjtree.openNodeScope(jjtn000); + jjtreeOpenNodeScope(jjtn000); + try { + jj_consume_token(_DEFAULT); + MemberValue(); + } catch (Throwable jjte000) { + if (jjtc000) { + jjtree.clearNodeScope(jjtn000); + jjtc000 = false; + } else { + jjtree.popNode(); + } + if (jjte000 instanceof RuntimeException) { + { + if (true) throw (RuntimeException) jjte000; + } + } + if (jjte000 instanceof ParseException) { + { + if (true) throw (ParseException) jjte000; + } + } + { + if (true) throw (Error) jjte000; + } + } finally { + if (jjtc000) { + jjtree.closeNodeScope(jjtn000, true); + jjtreeCloseNodeScope(jjtn000); + } + } + } + + final private boolean jj_2_1(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_1(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_2(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_2(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_3(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_3(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_4(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_4(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_5(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_5(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_6(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_6(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_7(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_7(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_8(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_8(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_9(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_9(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_10(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_10(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_11(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_11(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_12(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_12(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_13(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_13(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_14(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_14(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_15(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_15(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_16(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_16(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_17(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_17(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_18(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_18(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_19(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_19(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_20(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_20(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_21(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_21(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_22(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_22(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_23(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_23(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_24(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_24(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_25(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_25(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_26(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_26(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_27(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_27(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_28(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_28(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_29(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_29(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_30(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_30(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_31(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_31(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_32(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_32(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_33(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_33(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_34(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_34(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_35(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_35(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_36(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_36(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_37(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_37(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_38(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_38(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_39(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_39(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_40(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_40(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_41(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_41(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_42(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_42(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_43(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_43(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_44(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_44(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_45(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_45(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_46(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_46(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_47(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_47(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_2_48(int xla) { + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try { + return !jj_3_48(); + } + catch (LookaheadSuccess ls) { + return true; + } + } + + final private boolean jj_3R_56() { + if (jj_3R_101()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3_21()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_135() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_91()) return true; + return false; + } + + final private boolean jj_3R_99() { + if (jj_3R_91()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_135()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3_20() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_91() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_20()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_122() { + if (jj_3R_72()) return true; + return false; + } + + final private boolean jj_3R_86() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(58)) { + jj_scanpos = xsp; + if (jj_3R_122()) return true; + } + return false; + } + + final private boolean jj_3_19() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3R_83() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(10)) { + jj_scanpos = xsp; + if (jj_scan_token(15)) { + jj_scanpos = xsp; + if (jj_scan_token(12)) { + jj_scanpos = xsp; + if (jj_scan_token(46)) { + jj_scanpos = xsp; + if (jj_scan_token(35)) { + jj_scanpos = xsp; + if (jj_scan_token(37)) { + jj_scanpos = xsp; + if (jj_scan_token(28)) { + jj_scanpos = xsp; + if (jj_scan_token(21)) return true; + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_194() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_112()) return true; + return false; + } + + final private boolean jj_3R_290() { + if (jj_scan_token(SUPER)) return true; + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3_16() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_289() { + if (jj_scan_token(EXTENDS)) return true; + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3R_277() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_289()) { + jj_scanpos = xsp; + if (jj_3R_290()) return true; + } + return false; + } + + final private boolean jj_3R_256() { + if (jj_3R_277()) return true; + return false; + } + + final private boolean jj_3R_151() { + if (jj_scan_token(HOOK)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_256()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3_17() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3R_112() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_150()) { + jj_scanpos = xsp; + if (jj_3R_151()) return true; + } + return false; + } + + final private boolean jj_3R_150() { + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3_15() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_78() { + if (jj_scan_token(LT)) return true; + if (jj_3R_112()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_194()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3_18() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3_19()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_149() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3_17()) jj_scanpos = xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_18()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_111() { + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_16()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_110() { + if (jj_3R_83()) return true; + Token xsp; + if (jj_3_15()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3_15()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_77() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_110()) { + jj_scanpos = xsp; + if (jj_3R_111()) return true; + } + return false; + } + + final private boolean jj_3_13() { + if (jj_scan_token(THIS)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_221() { + if (jj_scan_token(THROWS)) return true; + if (jj_3R_99()) return true; + return false; + } + + final private boolean jj_3R_103() { + if (jj_3R_83()) return true; + return false; + } + + final private boolean jj_3R_72() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_14()) { + jj_scanpos = xsp; + if (jj_3R_103()) return true; + } + return false; + } + + final private boolean jj_3_14() { + if (jj_3R_77()) return true; + return false; + } + + final private boolean jj_3R_74() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(47)) jj_scanpos = xsp; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3_12() { + if (jj_3R_76()) return true; + return false; + } + + final private boolean jj_3R_108() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3R_107() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_252() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_76() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_107()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_3_13()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_108()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_scan_token(52)) { + jj_scanpos = xsp; + if (jj_scan_token(49)) return true; + } + if (jj_3R_109()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_134() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_133()) return true; + return false; + } + + final private boolean jj_3R_223() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3R_222() { + if (jj_3R_76()) return true; + return false; + } + + final private boolean jj_3R_220() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_186() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_220()) jj_scanpos = xsp; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_3R_53()) return true; + xsp = jj_scanpos; + if (jj_3R_221()) jj_scanpos = xsp; + if (jj_scan_token(LBRACE)) return true; + xsp = jj_scanpos; + if (jj_3R_222()) jj_scanpos = xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_223()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3_11() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_75()) return true; + return false; + } + + final private boolean jj_3R_227() { + if (jj_scan_token(THROWS)) return true; + if (jj_3R_99()) return true; + return false; + } + + final private boolean jj_3R_98() { + if (jj_3R_133()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_134()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_133() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(119)) jj_scanpos = xsp; + if (jj_3R_184()) return true; + return false; + } + + final private boolean jj_3R_53() { + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_98()) jj_scanpos = xsp; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3_48() { + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(LPAREN)) return true; + return false; + } + + final private boolean jj_3R_226() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_3R_53()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_252()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_228() { + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_225() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_292() { + if (jj_3R_75()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_11()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_188() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_225()) jj_scanpos = xsp; + if (jj_3R_86()) return true; + if (jj_3R_226()) return true; + xsp = jj_scanpos; + if (jj_3R_227()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_228()) { + jj_scanpos = xsp; + if (jj_scan_token(81)) return true; + } + return false; + } + + final private boolean jj_3R_198() { + if (jj_scan_token(ASSIGN)) return true; + if (jj_3R_75()) return true; + return false; + } + + final private boolean jj_3R_224() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_161()) return true; + return false; + } + + final private boolean jj_3_47() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_93()) return true; + return false; + } + + final private boolean jj_3R_217() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_147() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_292()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_scan_token(82)) jj_scanpos = xsp; + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_73() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_106() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_105() { + if (jj_3R_147()) return true; + return false; + } + + final private boolean jj_3R_75() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_105()) { + jj_scanpos = xsp; + if (jj_3R_106()) return true; + } + return false; + } + + final private boolean jj_3R_184() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_217()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_160() { + if (jj_scan_token(LBRACE)) return true; + if (jj_3R_93()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_47()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_scan_token(82)) jj_scanpos = xsp; + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_276() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_275()) return true; + return false; + } + + final private boolean jj_3R_161() { + if (jj_3R_184()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_198()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_127() { + if (jj_3R_101()) return true; + return false; + } + + final private boolean jj_3_9() { + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_73()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_scan_token(82)) { + jj_scanpos = xsp; + if (jj_scan_token(85)) { + jj_scanpos = xsp; + if (jj_scan_token(81)) return true; + } + } + return false; + } + + final private boolean jj_3R_126() { + if (jj_3R_160()) return true; + return false; + } + + final private boolean jj_3R_71() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_93() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_125()) { + jj_scanpos = xsp; + if (jj_3R_126()) { + jj_scanpos = xsp; + if (jj_3R_127()) return true; + } + } + return false; + } + + final private boolean jj_3R_125() { + if (jj_3R_102()) return true; + return false; + } + + final private boolean jj_3_8() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_71()) jj_scanpos = xsp; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(LPAREN)) return true; + return false; + } + + final private boolean jj_3R_187() { + if (jj_3R_72()) return true; + if (jj_3R_161()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_224()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_275() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(ASSIGN)) return true; + if (jj_3R_93()) return true; + return false; + } + + final private boolean jj_3R_140() { + if (jj_3R_188()) return true; + return false; + } + + final private boolean jj_3R_139() { + if (jj_3R_187()) return true; + return false; + } + + final private boolean jj_3R_249() { + if (jj_scan_token(BIT_AND)) return true; + if (jj_3R_149()) return true; + return false; + } + + final private boolean jj_3R_138() { + if (jj_3R_186()) return true; + return false; + } + + final private boolean jj_3R_255() { + if (jj_3R_275()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_276()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_231() { + if (jj_3R_255()) return true; + return false; + } + + final private boolean jj_3R_137() { + if (jj_3R_185()) return true; + return false; + } + + final private boolean jj_3R_92() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(ASSIGN)) return true; + return false; + } + + final private boolean jj_3R_136() { + if (jj_3R_130()) return true; + return false; + } + + final private boolean jj_3R_192() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_93()) return true; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3R_286() { + if (jj_3R_182()) return true; + return false; + } + + final private boolean jj_3R_100() { + if (jj_3R_50()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_136()) { + jj_scanpos = xsp; + if (jj_3R_137()) { + jj_scanpos = xsp; + if (jj_3R_138()) { + jj_scanpos = xsp; + if (jj_3R_139()) { + jj_scanpos = xsp; + if (jj_3R_140()) return true; + } + } + } + } + return false; + } + + final private boolean jj_3R_193() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + return false; + } + + final private boolean jj_3_46() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + return false; + } + + final private boolean jj_3_10() { + if (jj_3R_74()) return true; + return false; + } + + final private boolean jj_3R_55() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_10()) { + jj_scanpos = xsp; + if (jj_3R_100()) { + jj_scanpos = xsp; + if (jj_scan_token(81)) return true; + } + } + return false; + } + + final private boolean jj_3R_191() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_231()) jj_scanpos = xsp; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3_45() { + if (jj_scan_token(AT)) return true; + if (jj_3R_91()) return true; + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_92()) { + jj_scanpos = xsp; + if (jj_scan_token(76)) return true; + } + return false; + } + + final private boolean jj_3R_215() { + if (jj_3R_55()) return true; + return false; + } + + final private boolean jj_3R_132() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_131()) return true; + return false; + } + + final private boolean jj_3R_183() { + if (jj_3R_216()) return true; + return false; + } + + final private boolean jj_3R_285() { + if (jj_3R_109()) return true; + return false; + } + + final private boolean jj_3R_145() { + if (jj_3R_193()) return true; + return false; + } + + final private boolean jj_3R_182() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_215()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_144() { + if (jj_3R_192()) return true; + return false; + } + + final private boolean jj_3R_113() { + return false; + } + + final private boolean jj_3R_102() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_143()) { + jj_scanpos = xsp; + if (jj_3R_144()) { + jj_scanpos = xsp; + if (jj_3R_145()) return true; + } + } + return false; + } + + final private boolean jj_3R_143() { + if (jj_3R_191()) return true; + return false; + } + + final private boolean jj_3R_216() { + if (jj_scan_token(EXTENDS)) return true; + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_249()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_131() { + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_183()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_114() { + return false; + } + + final private boolean jj_3_7() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_70()) return true; + return false; + } + + final private boolean jj_3R_80() { + Token xsp; + xsp = jj_scanpos; + lookingAhead = true; + jj_semLA = getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RSIGNEDSHIFT; + lookingAhead = false; + if (!jj_semLA || jj_3R_113()) return true; + if (jj_scan_token(GT)) return true; + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3R_97() { + if (jj_scan_token(LT)) return true; + if (jj_3R_131()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_132()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3R_272() { + if (jj_3R_55()) return true; + return false; + } + + final private boolean jj_3R_70() { + if (jj_3R_50()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_285()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_286()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_81() { + Token xsp; + xsp = jj_scanpos; + lookingAhead = true; + jj_semLA = getToken(1).kind == GT && + ((Token.GTToken) getToken(1)).realKind == RUNSIGNEDSHIFT; + lookingAhead = false; + if (!jj_semLA || jj_3R_114()) return true; + if (jj_scan_token(GT)) return true; + if (jj_scan_token(GT)) return true; + if (jj_scan_token(GT)) return true; + return false; + } + + final private boolean jj_3R_251() { + if (jj_scan_token(SEMICOLON)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_272()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_250() { + if (jj_3R_70()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_7()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_246() { + if (jj_scan_token(FINALLY)) return true; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_219() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_250()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_scan_token(82)) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_251()) jj_scanpos = xsp; + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_245() { + if (jj_scan_token(CATCH)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_133()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_212() { + if (jj_scan_token(TRY)) return true; + if (jj_3R_104()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_245()) { + jj_scanpos = xsp; + break; + } + } + xsp = jj_scanpos; + if (jj_3R_246()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_218() { + if (jj_3R_214()) return true; + return false; + } + + final private boolean jj_3R_185() { + if (jj_scan_token(ENUM)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_218()) jj_scanpos = xsp; + if (jj_3R_219()) return true; + return false; + } + + final private boolean jj_3R_211() { + if (jj_scan_token(SYNCHRONIZED)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_244() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_248() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_149()) return true; + return false; + } + + final private boolean jj_3R_214() { + if (jj_scan_token(IMPLEMENTS)) return true; + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_248()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_210() { + if (jj_scan_token(THROW)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_271() { + if (jj_3R_284()) return true; + return false; + } + + final private boolean jj_3R_299() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_201()) return true; + return false; + } + + final private boolean jj_3R_209() { + if (jj_scan_token(RETURN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_244()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_247() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_149()) return true; + return false; + } + + final private boolean jj_3R_213() { + if (jj_scan_token(EXTENDS)) return true; + if (jj_3R_149()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_247()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_208() { + if (jj_scan_token(CONTINUE)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(72)) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_178() { + if (jj_scan_token(INTERFACE)) return true; + return false; + } + + final private boolean jj_3R_207() { + if (jj_scan_token(BREAK)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(72)) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_181() { + if (jj_3R_214()) return true; + return false; + } + + final private boolean jj_3R_180() { + if (jj_3R_213()) return true; + return false; + } + + final private boolean jj_3R_179() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_284() { + if (jj_3R_296()) return true; + return false; + } + + final private boolean jj_3R_270() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_130() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(16)) { + jj_scanpos = xsp; + if (jj_3R_178()) return true; + } + if (jj_scan_token(IDENTIFIER)) return true; + xsp = jj_scanpos; + if (jj_3R_179()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_180()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_181()) jj_scanpos = xsp; + if (jj_3R_182()) return true; + return false; + } + + final private boolean jj_3_44() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_296() { + if (jj_3R_201()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_299()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_241() { + if (jj_scan_token(ELSE)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3R_295() { + if (jj_3R_296()) return true; + return false; + } + + final private boolean jj_3_43() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(COLON)) return true; + return false; + } + + final private boolean jj_3R_294() { + if (jj_3R_128()) return true; + return false; + } + + final private boolean jj_3R_283() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_294()) { + jj_scanpos = xsp; + if (jj_3R_295()) return true; + } + return false; + } + + final private boolean jj_3R_269() { + if (jj_3R_283()) return true; + return false; + } + + final private boolean jj_3R_243() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_269()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + xsp = jj_scanpos; + if (jj_3R_270()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + xsp = jj_scanpos; + if (jj_3R_271()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_242() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(COLON)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_54() { + if (jj_scan_token(THROWS)) return true; + if (jj_3R_99()) return true; + return false; + } + + final private boolean jj_3R_206() { + if (jj_scan_token(FOR)) return true; + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_242()) { + jj_scanpos = xsp; + if (jj_3R_243()) return true; + } + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3R_69() { + if (jj_3R_102()) return true; + return false; + } + + final private boolean jj_3R_205() { + if (jj_scan_token(DO)) return true; + if (jj_3R_129()) return true; + if (jj_scan_token(WHILE)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_68() { + if (jj_scan_token(STRICTFP)) return true; + return false; + } + + final private boolean jj_3R_67() { + if (jj_scan_token(VOLATILE)) return true; + return false; + } + + final private boolean jj_3R_66() { + if (jj_scan_token(TRANSIENT)) return true; + return false; + } + + final private boolean jj_3R_204() { + if (jj_scan_token(WHILE)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3R_65() { + if (jj_scan_token(NATIVE)) return true; + return false; + } + + final private boolean jj_3R_64() { + if (jj_scan_token(SYNCHRONIZED)) return true; + return false; + } + + final private boolean jj_3R_63() { + if (jj_scan_token(ABSTRACT)) return true; + return false; + } + + final private boolean jj_3R_268() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3R_203() { + if (jj_scan_token(IF)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_129()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_241()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_62() { + if (jj_scan_token(FINAL)) return true; + return false; + } + + final private boolean jj_3R_61() { + if (jj_scan_token(PRIVATE)) return true; + return false; + } + + final private boolean jj_3R_162() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_161()) return true; + return false; + } + + final private boolean jj_3R_60() { + if (jj_scan_token(PROTECTED)) return true; + return false; + } + + final private boolean jj_3R_59() { + if (jj_scan_token(STATIC)) return true; + return false; + } + + final private boolean jj_3R_58() { + if (jj_scan_token(PUBLIC)) return true; + return false; + } + + final private boolean jj_3R_282() { + if (jj_scan_token(_DEFAULT)) return true; + if (jj_scan_token(COLON)) return true; + return false; + } + + final private boolean jj_3_6() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_58()) { + jj_scanpos = xsp; + if (jj_3R_59()) { + jj_scanpos = xsp; + if (jj_3R_60()) { + jj_scanpos = xsp; + if (jj_3R_61()) { + jj_scanpos = xsp; + if (jj_3R_62()) { + jj_scanpos = xsp; + if (jj_3R_63()) { + jj_scanpos = xsp; + if (jj_3R_64()) { + jj_scanpos = xsp; + if (jj_3R_65()) { + jj_scanpos = xsp; + if (jj_3R_66()) { + jj_scanpos = xsp; + if (jj_3R_67()) { + jj_scanpos = xsp; + if (jj_3R_68()) { + jj_scanpos = xsp; + if (jj_3R_69()) return true; + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_281() { + if (jj_scan_token(CASE)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(COLON)) return true; + return false; + } + + final private boolean jj_3R_267() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_281()) { + jj_scanpos = xsp; + if (jj_3R_282()) return true; + } + return false; + } + + final private boolean jj_3R_50() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_6()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_240() { + if (jj_3R_267()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_268()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3_42() { + if (jj_3R_90()) return true; + if (jj_3R_79()) return true; + return false; + } + + final private boolean jj_3R_202() { + if (jj_scan_token(SWITCH)) return true; + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_scan_token(LBRACE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_240()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3R_239() { + if (jj_3R_266()) return true; + return false; + } + + final private boolean jj_3R_57() { + if (jj_3R_102()) return true; + return false; + } + + final private boolean jj_3R_52() { + if (jj_3R_86()) return true; + return false; + } + + final private boolean jj_3R_238() { + if (jj_3R_265()) return true; + return false; + } + + final private boolean jj_3_5() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_57()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(PACKAGE)) return true; + return false; + } + + final private boolean jj_3R_237() { + if (jj_3R_264()) return true; + return false; + } + + final private boolean jj_3R_201() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_236()) { + jj_scanpos = xsp; + if (jj_3R_237()) { + jj_scanpos = xsp; + if (jj_3R_238()) { + jj_scanpos = xsp; + if (jj_3R_239()) return true; + } + } + } + return false; + } + + final private boolean jj_3R_236() { + if (jj_3R_263()) return true; + return false; + } + + final private boolean jj_3R_200() { + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3_41() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_128() { + if (jj_3R_50()) return true; + if (jj_3R_72()) return true; + if (jj_3R_161()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_162()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_51() { + if (jj_3R_97()) return true; + return false; + } + + final private boolean jj_3R_235() { + if (jj_scan_token(COLON)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_96() { + if (jj_3R_130()) return true; + return false; + } + + final private boolean jj_3R_95() { + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3_4() { + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_94() { + if (jj_3R_128()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_49() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_94()) { + jj_scanpos = xsp; + if (jj_3R_95()) { + jj_scanpos = xsp; + if (jj_3R_96()) return true; + } + } + return false; + } + + final private boolean jj_3R_146() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3_3() { + if (jj_3R_55()) return true; + return false; + } + + final private boolean jj_3R_104() { + if (jj_scan_token(LBRACE)) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_146()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RBRACE)) return true; + return false; + } + + final private boolean jj_3_2() { + if (jj_3R_50()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_51()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_52()) jj_scanpos = xsp; + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_3R_53()) return true; + xsp = jj_scanpos; + if (jj_3R_54()) jj_scanpos = xsp; + if (jj_scan_token(LBRACE)) return true; + return false; + } + + final private boolean jj_3R_89() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(COLON)) return true; + if (jj_3R_129()) return true; + return false; + } + + final private boolean jj_3_1() { + if (jj_3R_49()) return true; + return false; + } + + final private boolean jj_3R_199() { + if (jj_scan_token(ASSERT)) return true; + if (jj_3R_56()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_235()) jj_scanpos = xsp; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_177() { + if (jj_3R_212()) return true; + return false; + } + + final private boolean jj_3R_176() { + if (jj_3R_211()) return true; + return false; + } + + final private boolean jj_3_38() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_175() { + if (jj_3R_210()) return true; + return false; + } + + final private boolean jj_3R_174() { + if (jj_3R_209()) return true; + return false; + } + + final private boolean jj_3R_173() { + if (jj_3R_208()) return true; + return false; + } + + final private boolean jj_3R_172() { + if (jj_3R_207()) return true; + return false; + } + + final private boolean jj_3R_171() { + if (jj_3R_206()) return true; + return false; + } + + final private boolean jj_3R_170() { + if (jj_3R_205()) return true; + return false; + } + + final private boolean jj_3R_169() { + if (jj_3R_204()) return true; + return false; + } + + final private boolean jj_3R_168() { + if (jj_3R_203()) return true; + return false; + } + + final private boolean jj_3R_167() { + if (jj_3R_202()) return true; + return false; + } + + final private boolean jj_3R_166() { + if (jj_3R_201()) return true; + if (jj_scan_token(SEMICOLON)) return true; + return false; + } + + final private boolean jj_3R_165() { + if (jj_3R_200()) return true; + return false; + } + + final private boolean jj_3R_164() { + if (jj_3R_104()) return true; + return false; + } + + final private boolean jj_3R_163() { + if (jj_3R_199()) return true; + return false; + } + + final private boolean jj_3R_260() { + if (jj_3R_78()) return true; + return false; + } + + final private boolean jj_3_40() { + if (jj_3R_89()) return true; + return false; + } + + final private boolean jj_3R_129() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_40()) { + jj_scanpos = xsp; + if (jj_3R_163()) { + jj_scanpos = xsp; + if (jj_3R_164()) { + jj_scanpos = xsp; + if (jj_3R_165()) { + jj_scanpos = xsp; + if (jj_3R_166()) { + jj_scanpos = xsp; + if (jj_3R_167()) { + jj_scanpos = xsp; + if (jj_3R_168()) { + jj_scanpos = xsp; + if (jj_3R_169()) { + jj_scanpos = xsp; + if (jj_3R_170()) { + jj_scanpos = xsp; + if (jj_3R_171()) { + jj_scanpos = xsp; + if (jj_3R_172()) { + jj_scanpos = xsp; + if (jj_3R_173()) { + jj_scanpos = xsp; + if (jj_3R_174()) { + jj_scanpos = xsp; + if (jj_3R_175()) { + jj_scanpos = xsp; + if (jj_3R_176()) { + jj_scanpos = xsp; + if (jj_3R_177()) + return true; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_279() { + if (jj_3R_182()) return true; + return false; + } + + final private boolean jj_3R_291() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_278() { + Token xsp; + if (jj_3R_291()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3R_291()) { + jj_scanpos = xsp; + break; + } + } + if (jj_3R_147()) return true; + return false; + } + + final private boolean jj_3_37() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3_39() { + Token xsp; + if (jj_3_37()) return true; + while (true) { + xsp = jj_scanpos; + if (jj_3_37()) { + jj_scanpos = xsp; + break; + } + } + while (true) { + xsp = jj_scanpos; + if (jj_3_38()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_259() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_39()) { + jj_scanpos = xsp; + if (jj_3R_278()) return true; + } + return false; + } + + final private boolean jj_3R_262() { + if (jj_3R_109()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_279()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_232() { + if (jj_scan_token(COMMA)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_261() { + if (jj_3R_259()) return true; + return false; + } + + final private boolean jj_3R_123() { + if (jj_scan_token(NEW)) return true; + if (jj_3R_149()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_260()) jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_261()) { + jj_scanpos = xsp; + if (jj_3R_262()) return true; + } + return false; + } + + final private boolean jj_3R_87() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_36()) { + jj_scanpos = xsp; + if (jj_3R_123()) return true; + } + return false; + } + + final private boolean jj_3_36() { + if (jj_scan_token(NEW)) return true; + if (jj_3R_83()) return true; + if (jj_3R_259()) return true; + return false; + } + + final private boolean jj_3R_148() { + if (jj_3R_195()) return true; + return false; + } + + final private boolean jj_3R_195() { + if (jj_3R_56()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_232()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_109() { + if (jj_scan_token(LPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_148()) jj_scanpos = xsp; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3R_258() { + if (jj_scan_token(NULL)) return true; + return false; + } + + final private boolean jj_3R_257() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(56)) { + jj_scanpos = xsp; + if (jj_scan_token(25)) return true; + } + return false; + } + + final private boolean jj_3R_234() { + if (jj_3R_258()) return true; + return false; + } + + final private boolean jj_3R_233() { + if (jj_3R_257()) return true; + return false; + } + + final private boolean jj_3R_196() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(61)) { + jj_scanpos = xsp; + if (jj_scan_token(65)) { + jj_scanpos = xsp; + if (jj_scan_token(70)) { + jj_scanpos = xsp; + if (jj_scan_token(71)) { + jj_scanpos = xsp; + if (jj_3R_233()) { + jj_scanpos = xsp; + if (jj_3R_234()) return true; + } + } + } + } + } + return false; + } + + final private boolean jj_3R_152() { + if (jj_3R_196()) return true; + return false; + } + + final private boolean jj_3R_121() { + if (jj_3R_109()) return true; + return false; + } + + final private boolean jj_3R_120() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3_33() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3R_119() { + if (jj_scan_token(LBRACKET)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3_32() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(SUPER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3_35() { + if (jj_3R_88()) return true; + return false; + } + + final private boolean jj_3_34() { + if (jj_scan_token(DOT)) return true; + if (jj_3R_87()) return true; + return false; + } + + final private boolean jj_3R_118() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3_31() { + if (jj_3R_86()) return true; + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(CLASS)) return true; + return false; + } + + final private boolean jj_3R_117() { + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(SUPER)) return true; + return false; + } + + final private boolean jj_3R_84() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_117()) { + jj_scanpos = xsp; + if (jj_3R_118()) { + jj_scanpos = xsp; + if (jj_3_34()) { + jj_scanpos = xsp; + if (jj_3_35()) { + jj_scanpos = xsp; + if (jj_3R_119()) { + jj_scanpos = xsp; + if (jj_3R_120()) { + jj_scanpos = xsp; + if (jj_3R_121()) return true; + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_85() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_159() { + if (jj_3R_91()) return true; + return false; + } + + final private boolean jj_3_30() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_85()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3R_158() { + if (jj_3R_86()) return true; + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(CLASS)) return true; + return false; + } + + final private boolean jj_3R_157() { + if (jj_3R_87()) return true; + return false; + } + + final private boolean jj_3R_156() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(RPAREN)) return true; + return false; + } + + final private boolean jj_3_29() { + if (jj_3R_84()) return true; + return false; + } + + final private boolean jj_3R_155() { + if (jj_scan_token(SUPER)) return true; + if (jj_scan_token(DOT)) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_197() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_scan_token(DOT)) return true; + return false; + } + + final private boolean jj_3R_154() { + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_197()) { + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(THIS)) return true; + return false; + } + + final private boolean jj_3R_124() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_153()) { + jj_scanpos = xsp; + if (jj_3R_154()) { + jj_scanpos = xsp; + if (jj_3R_155()) { + jj_scanpos = xsp; + if (jj_3R_156()) { + jj_scanpos = xsp; + if (jj_3R_157()) { + jj_scanpos = xsp; + if (jj_3R_158()) { + jj_scanpos = xsp; + if (jj_3R_159()) return true; + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_153() { + if (jj_3R_196()) return true; + return false; + } + + final private boolean jj_3R_88() { + if (jj_scan_token(DOT)) return true; + if (jj_3R_78()) return true; + if (jj_scan_token(IDENTIFIER)) return true; + return false; + } + + final private boolean jj_3R_280() { + if (jj_3R_293()) return true; + return false; + } + + final private boolean jj_3_28() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_83()) return true; + return false; + } + + final private boolean jj_3R_90() { + if (jj_3R_124()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_29()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_319() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_313()) return true; + return false; + } + + final private boolean jj_3R_318() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(RPAREN)) return true; + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3R_317() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_318()) { + jj_scanpos = xsp; + if (jj_3R_319()) return true; + } + return false; + } + + final private boolean jj_3R_293() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(97)) { + jj_scanpos = xsp; + if (jj_scan_token(98)) return true; + } + return false; + } + + final private boolean jj_3_27() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(LBRACKET)) return true; + return false; + } + + final private boolean jj_3R_266() { + if (jj_3R_90()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_280()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_116() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(RPAREN)) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(88)) { + jj_scanpos = xsp; + if (jj_scan_token(87)) { + jj_scanpos = xsp; + if (jj_scan_token(75)) { + jj_scanpos = xsp; + if (jj_scan_token(72)) { + jj_scanpos = xsp; + if (jj_scan_token(52)) { + jj_scanpos = xsp; + if (jj_scan_token(49)) { + jj_scanpos = xsp; + if (jj_scan_token(39)) { + jj_scanpos = xsp; + if (jj_3R_152()) return true; + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3R_115() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_72()) return true; + if (jj_scan_token(LBRACKET)) return true; + if (jj_scan_token(RBRACKET)) return true; + return false; + } + + final private boolean jj_3R_82() { + Token xsp; + xsp = jj_scanpos; + if (jj_3_26()) { + jj_scanpos = xsp; + if (jj_3R_115()) { + jj_scanpos = xsp; + if (jj_3R_116()) return true; + } + } + return false; + } + + final private boolean jj_3_26() { + if (jj_scan_token(LPAREN)) return true; + if (jj_3R_83()) return true; + return false; + } + + final private boolean jj_3_25() { + if (jj_3R_82()) return true; + return false; + } + + final private boolean jj_3_24() { + if (jj_3R_81()) return true; + return false; + } + + final private boolean jj_3R_316() { + if (jj_3R_266()) return true; + return false; + } + + final private boolean jj_3R_315() { + if (jj_3R_317()) return true; + return false; + } + + final private boolean jj_3R_314() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(88)) { + jj_scanpos = xsp; + if (jj_scan_token(87)) return true; + } + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3R_313() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_314()) { + jj_scanpos = xsp; + if (jj_3R_315()) { + jj_scanpos = xsp; + if (jj_3R_316()) return true; + } + } + return false; + } + + final private boolean jj_3R_264() { + if (jj_scan_token(DECR)) return true; + if (jj_3R_90()) return true; + return false; + } + + final private boolean jj_3R_306() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(99)) { + jj_scanpos = xsp; + if (jj_scan_token(100)) return true; + } + if (jj_3R_305()) return true; + return false; + } + + final private boolean jj_3R_308() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(101)) { + jj_scanpos = xsp; + if (jj_scan_token(102)) { + jj_scanpos = xsp; + if (jj_scan_token(106)) return true; + } + } + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3_23() { + if (jj_3R_80()) return true; + return false; + } + + final private boolean jj_3R_263() { + if (jj_scan_token(INCR)) return true; + if (jj_3R_90()) return true; + return false; + } + + final private boolean jj_3R_312() { + if (jj_3R_313()) return true; + return false; + } + + final private boolean jj_3_22() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(107)) { + jj_scanpos = xsp; + if (jj_3_23()) { + jj_scanpos = xsp; + if (jj_3_24()) return true; + } + } + if (jj_3R_304()) return true; + return false; + } + + final private boolean jj_3R_311() { + if (jj_3R_264()) return true; + return false; + } + + final private boolean jj_3R_310() { + if (jj_3R_263()) return true; + return false; + } + + final private boolean jj_3R_309() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(99)) { + jj_scanpos = xsp; + if (jj_scan_token(100)) return true; + } + if (jj_3R_307()) return true; + return false; + } + + final private boolean jj_3R_307() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_309()) { + jj_scanpos = xsp; + if (jj_3R_310()) { + jj_scanpos = xsp; + if (jj_3R_311()) { + jj_scanpos = xsp; + if (jj_3R_312()) return true; + } + } + } + return false; + } + + final private boolean jj_3R_303() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(86)) { + jj_scanpos = xsp; + if (jj_scan_token(122)) { + jj_scanpos = xsp; + if (jj_scan_token(92)) { + jj_scanpos = xsp; + if (jj_scan_token(93)) return true; + } + } + } + if (jj_3R_302()) return true; + return false; + } + + final private boolean jj_3R_301() { + if (jj_scan_token(INSTANCEOF)) return true; + if (jj_3R_72()) return true; + return false; + } + + final private boolean jj_3R_305() { + if (jj_3R_307()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_308()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_298() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(91)) { + jj_scanpos = xsp; + if (jj_scan_token(94)) return true; + } + if (jj_3R_297()) return true; + return false; + } + + final private boolean jj_3R_304() { + if (jj_3R_305()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_306()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_302() { + if (jj_3R_304()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3_22()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_288() { + if (jj_scan_token(BIT_AND)) return true; + if (jj_3R_287()) return true; + return false; + } + + final private boolean jj_3R_300() { + if (jj_3R_302()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_303()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_254() { + if (jj_scan_token(BIT_OR)) return true; + if (jj_3R_253()) return true; + return false; + } + + final private boolean jj_3R_297() { + if (jj_3R_300()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_301()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_274() { + if (jj_scan_token(XOR)) return true; + if (jj_3R_273()) return true; + return false; + } + + final private boolean jj_3R_230() { + if (jj_scan_token(SC_AND)) return true; + if (jj_3R_229()) return true; + return false; + } + + final private boolean jj_3R_287() { + if (jj_3R_297()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_298()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_190() { + if (jj_scan_token(SC_OR)) return true; + if (jj_3R_189()) return true; + return false; + } + + final private boolean jj_3R_273() { + if (jj_3R_287()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_288()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_142() { + if (jj_scan_token(HOOK)) return true; + if (jj_3R_56()) return true; + if (jj_scan_token(COLON)) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_253() { + if (jj_3R_273()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_274()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_229() { + if (jj_3R_253()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_254()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_189() { + if (jj_3R_229()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_230()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_141() { + if (jj_3R_189()) return true; + Token xsp; + while (true) { + xsp = jj_scanpos; + if (jj_3R_190()) { + jj_scanpos = xsp; + break; + } + } + return false; + } + + final private boolean jj_3R_101() { + if (jj_3R_141()) return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_142()) jj_scanpos = xsp; + return false; + } + + final private boolean jj_3R_265() { + if (jj_3R_90()) return true; + if (jj_3R_79()) return true; + if (jj_3R_56()) return true; + return false; + } + + final private boolean jj_3R_79() { + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(85)) { + jj_scanpos = xsp; + if (jj_scan_token(110)) { + jj_scanpos = xsp; + if (jj_scan_token(111)) { + jj_scanpos = xsp; + if (jj_scan_token(115)) { + jj_scanpos = xsp; + if (jj_scan_token(108)) { + jj_scanpos = xsp; + if (jj_scan_token(109)) { + jj_scanpos = xsp; + if (jj_scan_token(116)) { + jj_scanpos = xsp; + if (jj_scan_token(117)) { + jj_scanpos = xsp; + if (jj_scan_token(118)) { + jj_scanpos = xsp; + if (jj_scan_token(112)) { + jj_scanpos = xsp; + if (jj_scan_token(114)) { + jj_scanpos = xsp; + if (jj_scan_token(113)) + return true; + } + } + } + } + } + } + } + } + } + } + } + return false; + } + + final private boolean jj_3_21() { + if (jj_3R_79()) return true; + if (jj_3R_56()) return true; + return false; + } + + public JavaParserTokenManager token_source; + JavaCharStream jj_input_stream; + public Token token, jj_nt; + private int jj_ntk; + private Token jj_scanpos, jj_lastpos; + private int jj_la; + public boolean lookingAhead = false; + private boolean jj_semLA; + + public JavaParser(java.io.InputStream stream) { + this(stream, null); + } + + public JavaParser(java.io.InputStream stream, String encoding) { + try { + jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source = new JavaParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + } + + public void ReInit(java.io.InputStream stream) { + ReInit(stream, null); + } + + public void ReInit(java.io.InputStream stream, String encoding) { + try { + jj_input_stream.ReInit(stream, encoding, 1, 1); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + } + + public JavaParser(java.io.Reader stream) { + jj_input_stream = new JavaCharStream(stream, 1, 1); + token_source = new JavaParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + } + + public void ReInit(java.io.Reader stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + } + + public JavaParser(JavaParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + } + + public void ReInit(JavaParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jjtree.reset(); + } + + final private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + return token; + } + token = oldToken; + throw generateParseException(); + } + + static private final class LookaheadSuccess extends java.lang.Error { + } + + final private LookaheadSuccess jj_ls = new LookaheadSuccess(); + + final private boolean jj_scan_token(int kind) { + if (jj_scanpos == jj_lastpos) { + jj_la--; + if (jj_scanpos.next == null) { + jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); + } else { + jj_lastpos = jj_scanpos = jj_scanpos.next; + } + } else { + jj_scanpos = jj_scanpos.next; + } + if (jj_scanpos.kind != kind) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; + return false; + } + + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + return token; + } + + final public Token getToken(int index) { + Token t = lookingAhead ? jj_scanpos : token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + final private int jj_ntk() { + if ((jj_nt = token.next) == null) + return (jj_ntk = (token.next = token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + public ParseException generateParseException() { + Token errortok = token.next; + int line = errortok.beginLine, column = errortok.beginColumn; + String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image; + return new ParseException("Unable to parse Java code near token: " + mess, line, column); + } + + final public void enable_tracing() { + } + + final public void disable_tracing() { + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserConstants.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserConstants.java new file mode 100644 index 0000000..ba58d40 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserConstants.java @@ -0,0 +1,285 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParserConstants.java */ + +package jaxx.compiler.java.parser; + +public interface JavaParserConstants { + + int EOF = 0; + int WHITE_SPACE = 3; + int SINGLE_LINE_COMMENT = 4; + int FORMAL_COMMENT = 5; + int MULTI_LINE_COMMENT = 6; + int ABSTRACT = 8; + int ASSERT = 9; + int BOOLEAN = 10; + int BREAK = 11; + int BYTE = 12; + int CASE = 13; + int CATCH = 14; + int CHAR = 15; + int CLASS = 16; + int CONST = 17; + int CONTINUE = 18; + int _DEFAULT = 19; + int DO = 20; + int DOUBLE = 21; + int ELSE = 22; + int ENUM = 23; + int EXTENDS = 24; + int FALSE = 25; + int FINAL = 26; + int FINALLY = 27; + int FLOAT = 28; + int FOR = 29; + int GOTO = 30; + int IF = 31; + int IMPLEMENTS = 32; + int IMPORT = 33; + int INSTANCEOF = 34; + int INT = 35; + int INTERFACE = 36; + int LONG = 37; + int NATIVE = 38; + int NEW = 39; + int NULL = 40; + int PACKAGE = 41; + int PRIVATE = 42; + int PROTECTED = 43; + int PUBLIC = 44; + int RETURN = 45; + int SHORT = 46; + int STATIC = 47; + int STRICTFP = 48; + int SUPER = 49; + int SWITCH = 50; + int SYNCHRONIZED = 51; + int THIS = 52; + int THROW = 53; + int THROWS = 54; + int TRANSIENT = 55; + int TRUE = 56; + int TRY = 57; + int VOID = 58; + int VOLATILE = 59; + int WHILE = 60; + int INTEGER_LITERAL = 61; + int DECIMAL_LITERAL = 62; + int HEX_LITERAL = 63; + int OCTAL_LITERAL = 64; + int FLOATING_POINT_LITERAL = 65; + int DECIMAL_FLOATING_POINT_LITERAL = 66; + int DECIMAL_EXPONENT = 67; + int HEXADECIMAL_FLOATING_POINT_LITERAL = 68; + int HEXADECIMAL_EXPONENT = 69; + int CHARACTER_LITERAL = 70; + int STRING_LITERAL = 71; + int IDENTIFIER = 72; + int LETTER = 73; + int PART_LETTER = 74; + int LPAREN = 75; + int RPAREN = 76; + int LBRACE = 77; + int RBRACE = 78; + int LBRACKET = 79; + int RBRACKET = 80; + int SEMICOLON = 81; + int COMMA = 82; + int DOT = 83; + int AT = 84; + int ASSIGN = 85; + int LT = 86; + int BANG = 87; + int TILDE = 88; + int HOOK = 89; + int COLON = 90; + int EQ = 91; + int LE = 92; + int GE = 93; + int NE = 94; + int SC_OR = 95; + int SC_AND = 96; + int INCR = 97; + int DECR = 98; + int PLUS = 99; + int MINUS = 100; + int STAR = 101; + int SLASH = 102; + int BIT_AND = 103; + int BIT_OR = 104; + int XOR = 105; + int REM = 106; + int LSHIFT = 107; + int PLUSASSIGN = 108; + int MINUSASSIGN = 109; + int STARASSIGN = 110; + int SLASHASSIGN = 111; + int ANDASSIGN = 112; + int ORASSIGN = 113; + int XORASSIGN = 114; + int REMASSIGN = 115; + int LSHIFTASSIGN = 116; + int RSIGNEDSHIFTASSIGN = 117; + int RUNSIGNEDSHIFTASSIGN = 118; + int ELLIPSIS = 119; + int RUNSIGNEDSHIFT = 120; + int RSIGNEDSHIFT = 121; + int GT = 122; + int STUFF_TO_IGNORE = 124; + + int DEFAULT = 0; + int IN_FORMAL_COMMENT = 1; + int IN_MULTI_LINE_COMMENT = 2; + + String[] tokenImage = { + "<EOF>", + "<token of kind 1>", + "\"/*\"", + "<WHITE_SPACE>", + "<SINGLE_LINE_COMMENT>", + "\"*/\"", + "\"*/\"", + "<token of kind 7>", + "\"abstract\"", + "\"assert\"", + "\"boolean\"", + "\"break\"", + "\"byte\"", + "\"case\"", + "\"catch\"", + "\"char\"", + "\"class\"", + "\"const\"", + "\"continue\"", + "\"default\"", + "\"do\"", + "\"double\"", + "\"else\"", + "\"enum\"", + "\"extends\"", + "\"false\"", + "\"final\"", + "\"finally\"", + "\"float\"", + "\"for\"", + "\"goto\"", + "\"if\"", + "\"implements\"", + "\"import\"", + "\"instanceof\"", + "\"int\"", + "\"interface\"", + "\"long\"", + "\"native\"", + "\"new\"", + "\"null\"", + "\"package\"", + "\"private\"", + "\"protected\"", + "\"public\"", + "\"return\"", + "\"short\"", + "\"static\"", + "\"strictfp\"", + "\"super\"", + "\"switch\"", + "\"synchronized\"", + "\"this\"", + "\"throw\"", + "\"throws\"", + "\"transient\"", + "\"true\"", + "\"try\"", + "\"void\"", + "\"volatile\"", + "\"while\"", + "<INTEGER_LITERAL>", + "<DECIMAL_LITERAL>", + "<HEX_LITERAL>", + "<OCTAL_LITERAL>", + "<FLOATING_POINT_LITERAL>", + "<DECIMAL_FLOATING_POINT_LITERAL>", + "<DECIMAL_EXPONENT>", + "<HEXADECIMAL_FLOATING_POINT_LITERAL>", + "<HEXADECIMAL_EXPONENT>", + "<CHARACTER_LITERAL>", + "<STRING_LITERAL>", + "<IDENTIFIER>", + "<LETTER>", + "<PART_LETTER>", + "\"(\"", + "\")\"", + "\"{\"", + "\"}\"", + "\"[\"", + "\"]\"", + "\";\"", + "\",\"", + "\".\"", + "\"@\"", + "\"=\"", + "\"<\"", + "\"!\"", + "\"~\"", + "\"?\"", + "\":\"", + "\"==\"", + "\"<=\"", + "\">=\"", + "\"!=\"", + "\"||\"", + "\"&&\"", + "\"++\"", + "\"--\"", + "\"+\"", + "\"-\"", + "\"*\"", + "\"/\"", + "\"&\"", + "\"|\"", + "\"^\"", + "\"%\"", + "\"<<\"", + "\"+=\"", + "\"-=\"", + "\"*=\"", + "\"/=\"", + "\"&=\"", + "\"|=\"", + "\"^=\"", + "\"%=\"", + "\"<<=\"", + "\">>=\"", + "\">>>=\"", + "\"...\"", + "\">>>\"", + "\">>\"", + "\">\"", + "\"\\u001a\"", + "<STUFF_TO_IGNORE>", + }; + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTokenManager.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTokenManager.java new file mode 100644 index 0000000..f489bed --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTokenManager.java @@ -0,0 +1,2100 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree&JavaCC: Do not edit this line. JavaParserTokenManager.java */ + +package jaxx.compiler.java.parser; + +import java.io.IOException; +import java.io.PrintStream; + +public class JavaParserTokenManager implements JavaParserConstants { + public PrintStream debugStream = System.out; + + public void setDebugStream(PrintStream ds) { + debugStream = ds; + } + + private int jjStopStringLiteralDfa_0(int pos, long active0, long active1) { + switch (pos) { + case 0: + if ((active0 & 0x4L) != 0L || (active1 & 0x804000000000L) != 0L) + return 48; + if ((active1 & 0x80000000080000L) != 0L) + return 5; + if ((active0 & 0x1fffffffffffff00L) != 0L) { + jjmatchedKind = 72; + return 29; + } + return -1; + case 1: + if ((active0 & 0x4L) != 0L) + return 46; + if ((active0 & 0x1fffffff7fcfff00L) != 0L) { + if (jjmatchedPos != 1) { + jjmatchedKind = 72; + jjmatchedPos = 1; + } + return 29; + } + if ((active0 & 0x80300000L) != 0L) + return 29; + return -1; + case 2: + if ((active0 & 0x1dffff675fefff00L) != 0L) { + if (jjmatchedPos != 2) { + jjmatchedKind = 72; + jjmatchedPos = 2; + } + return 29; + } + if ((active0 & 0x200009820000000L) != 0L) + return 29; + return -1; + case 3: + if ((active0 & 0x18effe571f2f4f00L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 3; + return 29; + } + if ((active0 & 0x510012040c0b000L) != 0L) + return 29; + return -1; + case 4: + if ((active0 & 0x88dbe57012c0700L) != 0L) { + if (jjmatchedPos != 4) { + jjmatchedKind = 72; + jjmatchedPos = 4; + } + return 29; + } + if ((active0 & 0x106240001e034800L) != 0L) + return 29; + return -1; + case 5: + if ((active0 & 0x8890e15090c0500L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 5; + return 29; + } + if ((active0 & 0x44b04200200200L) != 0L) + return 29; + return -1; + case 6: + if ((active0 & 0x889081500040100L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 6; + return 29; + } + if ((active0 & 0x60009080400L) != 0L) + return 29; + return -1; + case 7: + if ((active0 & 0x801000000040100L) != 0L) + return 29; + if ((active0 & 0x88081500000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 7; + return 29; + } + return -1; + case 8: + if ((active0 & 0x8000500000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 8; + return 29; + } + if ((active0 & 0x80081000000000L) != 0L) + return 29; + return -1; + case 9: + if ((active0 & 0x8000000000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 9; + return 29; + } + if ((active0 & 0x500000000L) != 0L) + return 29; + return -1; + case 10: + if ((active0 & 0x8000000000000L) != 0L) { + jjmatchedKind = 72; + jjmatchedPos = 10; + return 29; + } + return -1; + default: + return -1; + } + } + + private int jjStartNfa_0(int pos, long active0, long active1) { + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1), pos + 1); + } + + private int jjStopAtPos(int pos, int kind) { + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; + } + + private int jjStartNfaWithStates_0(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + return pos + 1; + } + return jjMoveNfa_0(state, pos + 1); + } + + private int jjMoveStringLiteralDfa0_0() { + switch (curChar) { + case 26: + return jjStopAtPos(0, 123); + case 33: + jjmatchedKind = 87; + return jjMoveStringLiteralDfa1_0(0x0L, 0x40000000L); + case 37: + jjmatchedKind = 106; + return jjMoveStringLiteralDfa1_0(0x0L, 0x8000000000000L); + case 38: + jjmatchedKind = 103; + return jjMoveStringLiteralDfa1_0(0x0L, 0x1000100000000L); + case 40: + return jjStopAtPos(0, 75); + case 41: + return jjStopAtPos(0, 76); + case 42: + jjmatchedKind = 101; + return jjMoveStringLiteralDfa1_0(0x0L, 0x400000000000L); + case 43: + jjmatchedKind = 99; + return jjMoveStringLiteralDfa1_0(0x0L, 0x100200000000L); + case 44: + return jjStopAtPos(0, 82); + case 45: + jjmatchedKind = 100; + return jjMoveStringLiteralDfa1_0(0x0L, 0x200400000000L); + case 46: + jjmatchedKind = 83; + return jjMoveStringLiteralDfa1_0(0x0L, 0x80000000000000L); + case 47: + jjmatchedKind = 102; + return jjMoveStringLiteralDfa1_0(0x4L, 0x800000000000L); + case 58: + return jjStopAtPos(0, 90); + case 59: + return jjStopAtPos(0, 81); + case 60: + jjmatchedKind = 86; + return jjMoveStringLiteralDfa1_0(0x0L, 0x10080010000000L); + case 61: + jjmatchedKind = 85; + return jjMoveStringLiteralDfa1_0(0x0L, 0x8000000L); + case 62: + jjmatchedKind = 122; + return jjMoveStringLiteralDfa1_0(0x0L, 0x360000020000000L); + case 63: + return jjStopAtPos(0, 89); + case 64: + return jjStopAtPos(0, 84); + case 91: + return jjStopAtPos(0, 79); + case 93: + return jjStopAtPos(0, 80); + case 94: + jjmatchedKind = 105; + return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000000000L); + case 97: + return jjMoveStringLiteralDfa1_0(0x300L, 0x0L); + case 98: + return jjMoveStringLiteralDfa1_0(0x1c00L, 0x0L); + case 99: + return jjMoveStringLiteralDfa1_0(0x7e000L, 0x0L); + case 100: + return jjMoveStringLiteralDfa1_0(0x380000L, 0x0L); + case 101: + return jjMoveStringLiteralDfa1_0(0x1c00000L, 0x0L); + case 102: + return jjMoveStringLiteralDfa1_0(0x3e000000L, 0x0L); + case 103: + return jjMoveStringLiteralDfa1_0(0x40000000L, 0x0L); + case 105: + return jjMoveStringLiteralDfa1_0(0x1f80000000L, 0x0L); + case 108: + return jjMoveStringLiteralDfa1_0(0x2000000000L, 0x0L); + case 110: + return jjMoveStringLiteralDfa1_0(0x1c000000000L, 0x0L); + case 112: + return jjMoveStringLiteralDfa1_0(0x1e0000000000L, 0x0L); + case 114: + return jjMoveStringLiteralDfa1_0(0x200000000000L, 0x0L); + case 115: + return jjMoveStringLiteralDfa1_0(0xfc00000000000L, 0x0L); + case 116: + return jjMoveStringLiteralDfa1_0(0x3f0000000000000L, 0x0L); + case 118: + return jjMoveStringLiteralDfa1_0(0xc00000000000000L, 0x0L); + case 119: + return jjMoveStringLiteralDfa1_0(0x1000000000000000L, 0x0L); + case 123: + return jjStopAtPos(0, 77); + case 124: + jjmatchedKind = 104; + return jjMoveStringLiteralDfa1_0(0x0L, 0x2000080000000L); + case 125: + return jjStopAtPos(0, 78); + case 126: + return jjStopAtPos(0, 88); + default: + return jjMoveNfa_0(1, 0); + } + } + + private int jjMoveStringLiteralDfa1_0(long active0, long active1) { + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(0, active0, active1); + return 1; + } + switch (curChar) { + case 38: + if ((active1 & 0x100000000L) != 0L) + return jjStopAtPos(1, 96); + break; + case 42: + if ((active0 & 0x4L) != 0L) + return jjStartNfaWithStates_0(1, 2, 46); + break; + case 43: + if ((active1 & 0x200000000L) != 0L) + return jjStopAtPos(1, 97); + break; + case 45: + if ((active1 & 0x400000000L) != 0L) + return jjStopAtPos(1, 98); + break; + case 46: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x80000000000000L); + case 60: + if ((active1 & 0x80000000000L) != 0L) { + jjmatchedKind = 107; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x10000000000000L); + case 61: + if ((active1 & 0x8000000L) != 0L) + return jjStopAtPos(1, 91); + else if ((active1 & 0x10000000L) != 0L) + return jjStopAtPos(1, 92); + else if ((active1 & 0x20000000L) != 0L) + return jjStopAtPos(1, 93); + else if ((active1 & 0x40000000L) != 0L) + return jjStopAtPos(1, 94); + else if ((active1 & 0x100000000000L) != 0L) + return jjStopAtPos(1, 108); + else if ((active1 & 0x200000000000L) != 0L) + return jjStopAtPos(1, 109); + else if ((active1 & 0x400000000000L) != 0L) + return jjStopAtPos(1, 110); + else if ((active1 & 0x800000000000L) != 0L) + return jjStopAtPos(1, 111); + else if ((active1 & 0x1000000000000L) != 0L) + return jjStopAtPos(1, 112); + else if ((active1 & 0x2000000000000L) != 0L) + return jjStopAtPos(1, 113); + else if ((active1 & 0x4000000000000L) != 0L) + return jjStopAtPos(1, 114); + else if ((active1 & 0x8000000000000L) != 0L) + return jjStopAtPos(1, 115); + break; + case 62: + if ((active1 & 0x200000000000000L) != 0L) { + jjmatchedKind = 121; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x160000000000000L); + case 97: + return jjMoveStringLiteralDfa2_0(active0, 0x24002006000L, active1, 0L); + case 98: + return jjMoveStringLiteralDfa2_0(active0, 0x100L, active1, 0L); + case 101: + return jjMoveStringLiteralDfa2_0(active0, 0x208000080000L, active1, 0L); + case 102: + if ((active0 & 0x80000000L) != 0L) + return jjStartNfaWithStates_0(1, 31, 29); + break; + case 104: + return jjMoveStringLiteralDfa2_0(active0, 0x1070400000008000L, active1, 0L); + case 105: + return jjMoveStringLiteralDfa2_0(active0, 0xc000000L, active1, 0L); + case 108: + return jjMoveStringLiteralDfa2_0(active0, 0x10410000L, active1, 0L); + case 109: + return jjMoveStringLiteralDfa2_0(active0, 0x300000000L, active1, 0L); + case 110: + return jjMoveStringLiteralDfa2_0(active0, 0x1c00800000L, active1, 0L); + case 111: + if ((active0 & 0x100000L) != 0L) { + jjmatchedKind = 20; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0xc00002060260400L, active1, 0L); + case 114: + return jjMoveStringLiteralDfa2_0(active0, 0x3800c0000000800L, active1, 0L); + case 115: + return jjMoveStringLiteralDfa2_0(active0, 0x200L, active1, 0L); + case 116: + return jjMoveStringLiteralDfa2_0(active0, 0x1800000000000L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa2_0(active0, 0x2110000000000L, active1, 0L); + case 119: + return jjMoveStringLiteralDfa2_0(active0, 0x4000000000000L, active1, 0L); + case 120: + return jjMoveStringLiteralDfa2_0(active0, 0x1000000L, active1, 0L); + case 121: + return jjMoveStringLiteralDfa2_0(active0, 0x8000000001000L, active1, 0L); + case 124: + if ((active1 & 0x80000000L) != 0L) + return jjStopAtPos(1, 95); + break; + default: + break; + } + return jjStartNfa_0(0, active0, active1); + } + + private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1) { + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(0, old0, old1); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(1, active0, active1); + return 2; + } + switch (curChar) { + case 46: + if ((active1 & 0x80000000000000L) != 0L) + return jjStopAtPos(2, 119); + break; + case 61: + if ((active1 & 0x10000000000000L) != 0L) + return jjStopAtPos(2, 116); + else if ((active1 & 0x20000000000000L) != 0L) + return jjStopAtPos(2, 117); + break; + case 62: + if ((active1 & 0x100000000000000L) != 0L) { + jjmatchedKind = 120; + jjmatchedPos = 2; + } + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x40000000000000L); + case 97: + return jjMoveStringLiteralDfa3_0(active0, 0x80800000018000L, active1, 0L); + case 98: + return jjMoveStringLiteralDfa3_0(active0, 0x100000000000L, active1, 0L); + case 99: + return jjMoveStringLiteralDfa3_0(active0, 0x20000000000L, active1, 0L); + case 101: + return jjMoveStringLiteralDfa3_0(active0, 0x800L, active1, 0L); + case 102: + return jjMoveStringLiteralDfa3_0(active0, 0x80000L, active1, 0L); + case 105: + return jjMoveStringLiteralDfa3_0(active0, 0x1414040000000000L, active1, 0L); + case 108: + return jjMoveStringLiteralDfa3_0(active0, 0x800010002000000L, active1, 0L); + case 110: + return jjMoveStringLiteralDfa3_0(active0, 0x800200c060000L, active1, 0L); + case 111: + return jjMoveStringLiteralDfa3_0(active0, 0x480010000400L, active1, 0L); + case 112: + return jjMoveStringLiteralDfa3_0(active0, 0x2000300000000L, active1, 0L); + case 114: + if ((active0 & 0x20000000L) != 0L) + return jjStartNfaWithStates_0(2, 29, 29); + return jjMoveStringLiteralDfa3_0(active0, 0x61000000000000L, active1, 0L); + case 115: + return jjMoveStringLiteralDfa3_0(active0, 0x400402300L, active1, 0L); + case 116: + if ((active0 & 0x800000000L) != 0L) { + jjmatchedKind = 35; + jjmatchedPos = 2; + } + return jjMoveStringLiteralDfa3_0(active0, 0x205041005000L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa3_0(active0, 0x100000000a00000L, active1, 0L); + case 119: + if ((active0 & 0x8000000000L) != 0L) + return jjStartNfaWithStates_0(2, 39, 29); + break; + case 121: + if ((active0 & 0x200000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 57, 29); + break; + default: + break; + } + return jjStartNfa_0(1, active0, active1); + } + + private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1) { + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(1, old0, old1); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(2, active0, active1); + return 3; + } + switch (curChar) { + case 61: + if ((active1 & 0x40000000000000L) != 0L) + return jjStopAtPos(3, 118); + break; + case 97: + return jjMoveStringLiteralDfa4_0(active0, 0x80000001c080800L, active1, 0L); + case 98: + return jjMoveStringLiteralDfa4_0(active0, 0x200000L, active1, 0L); + case 99: + return jjMoveStringLiteralDfa4_0(active0, 0x8000000004000L, active1, 0L); + case 100: + if ((active0 & 0x400000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 58, 29); + break; + case 101: + if ((active0 & 0x1000L) != 0L) + return jjStartNfaWithStates_0(3, 12, 29); + else if ((active0 & 0x2000L) != 0L) + return jjStartNfaWithStates_0(3, 13, 29); + else if ((active0 & 0x400000L) != 0L) + return jjStartNfaWithStates_0(3, 22, 29); + else if ((active0 & 0x100000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 56, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x2001001000200L, active1, 0L); + case 103: + if ((active0 & 0x2000000000L) != 0L) + return jjStartNfaWithStates_0(3, 37, 29); + break; + case 105: + return jjMoveStringLiteralDfa4_0(active0, 0x1004000000000L, active1, 0L); + case 107: + return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L, active1, 0L); + case 108: + if ((active0 & 0x10000000000L) != 0L) + return jjStartNfaWithStates_0(3, 40, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x1000100100000400L, active1, 0L); + case 109: + if ((active0 & 0x800000L) != 0L) + return jjStartNfaWithStates_0(3, 23, 29); + break; + case 110: + return jjMoveStringLiteralDfa4_0(active0, 0x80000000000000L, active1, 0L); + case 111: + if ((active0 & 0x40000000L) != 0L) + return jjStartNfaWithStates_0(3, 30, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x60000200000000L, active1, 0L); + case 114: + if ((active0 & 0x8000L) != 0L) + return jjStartNfaWithStates_0(3, 15, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x400000000000L, active1, 0L); + case 115: + if ((active0 & 0x10000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 52, 29); + return jjMoveStringLiteralDfa4_0(active0, 0x2030000L, active1, 0L); + case 116: + return jjMoveStringLiteralDfa4_0(active0, 0x4880400040100L, active1, 0L); + case 117: + return jjMoveStringLiteralDfa4_0(active0, 0x200000000000L, active1, 0L); + case 118: + return jjMoveStringLiteralDfa4_0(active0, 0x40000000000L, active1, 0L); + default: + break; + } + return jjStartNfa_0(2, active0, active1); + } + + private int jjMoveStringLiteralDfa4_0(long old0, long active0, long old1, long active1) { + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(2, old0, old1); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(3, active0, 0L); + return 4; + } + switch (curChar) { + case 97: + return jjMoveStringLiteralDfa5_0(active0, 0x60400000000L); + case 99: + return jjMoveStringLiteralDfa5_0(active0, 0x5000000000000L); + case 101: + if ((active0 & 0x2000000L) != 0L) + return jjStartNfaWithStates_0(4, 25, 29); + else if ((active0 & 0x1000000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 60, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x80100000400L); + case 104: + if ((active0 & 0x4000L) != 0L) + return jjStartNfaWithStates_0(4, 14, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x8000000000000L); + case 105: + return jjMoveStringLiteralDfa5_0(active0, 0x900000040000L); + case 107: + if ((active0 & 0x800L) != 0L) + return jjStartNfaWithStates_0(4, 11, 29); + break; + case 108: + if ((active0 & 0x4000000L) != 0L) { + jjmatchedKind = 26; + jjmatchedPos = 4; + } + return jjMoveStringLiteralDfa5_0(active0, 0x8200000L); + case 110: + return jjMoveStringLiteralDfa5_0(active0, 0x1000000L); + case 114: + if ((active0 & 0x2000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 49, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x201200000300L); + case 115: + if ((active0 & 0x10000L) != 0L) + return jjStartNfaWithStates_0(4, 16, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x80000000000000L); + case 116: + if ((active0 & 0x20000L) != 0L) + return jjStartNfaWithStates_0(4, 17, 29); + else if ((active0 & 0x10000000L) != 0L) + return jjStartNfaWithStates_0(4, 28, 29); + else if ((active0 & 0x400000000000L) != 0L) + return jjStartNfaWithStates_0(4, 46, 29); + return jjMoveStringLiteralDfa5_0(active0, 0x800000000000000L); + case 117: + return jjMoveStringLiteralDfa5_0(active0, 0x80000L); + case 118: + return jjMoveStringLiteralDfa5_0(active0, 0x4000000000L); + case 119: + if ((active0 & 0x20000000000000L) != 0L) { + jjmatchedKind = 53; + jjmatchedPos = 4; + } + return jjMoveStringLiteralDfa5_0(active0, 0x40000000000000L); + default: + break; + } + return jjStartNfa_0(3, active0, 0L); + } + + private int jjMoveStringLiteralDfa5_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(3, old0, 0L); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(4, active0, 0L); + return 5; + } + switch (curChar) { + case 97: + return jjMoveStringLiteralDfa6_0(active0, 0x500L); + case 99: + if ((active0 & 0x100000000000L) != 0L) + return jjStartNfaWithStates_0(5, 44, 29); + else if ((active0 & 0x800000000000L) != 0L) + return jjStartNfaWithStates_0(5, 47, 29); + return jjMoveStringLiteralDfa6_0(active0, 0x80000000000L); + case 100: + return jjMoveStringLiteralDfa6_0(active0, 0x1000000L); + case 101: + if ((active0 & 0x200000L) != 0L) + return jjStartNfaWithStates_0(5, 21, 29); + else if ((active0 & 0x4000000000L) != 0L) + return jjStartNfaWithStates_0(5, 38, 29); + break; + case 102: + return jjMoveStringLiteralDfa6_0(active0, 0x1000000000L); + case 103: + return jjMoveStringLiteralDfa6_0(active0, 0x20000000000L); + case 104: + if ((active0 & 0x4000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 50, 29); + break; + case 105: + return jjMoveStringLiteralDfa6_0(active0, 0x880000000000000L); + case 108: + return jjMoveStringLiteralDfa6_0(active0, 0x8080000L); + case 109: + return jjMoveStringLiteralDfa6_0(active0, 0x100000000L); + case 110: + if ((active0 & 0x200000000000L) != 0L) + return jjStartNfaWithStates_0(5, 45, 29); + return jjMoveStringLiteralDfa6_0(active0, 0x400040000L); + case 114: + return jjMoveStringLiteralDfa6_0(active0, 0x8000000000000L); + case 115: + if ((active0 & 0x40000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 54, 29); + break; + case 116: + if ((active0 & 0x200L) != 0L) + return jjStartNfaWithStates_0(5, 9, 29); + else if ((active0 & 0x200000000L) != 0L) + return jjStartNfaWithStates_0(5, 33, 29); + return jjMoveStringLiteralDfa6_0(active0, 0x1040000000000L); + default: + break; + } + return jjStartNfa_0(4, active0, 0L); + } + + private int jjMoveStringLiteralDfa6_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(4, old0, 0L); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(5, active0, 0L); + return 6; + } + switch (curChar) { + case 97: + return jjMoveStringLiteralDfa7_0(active0, 0x1000000000L); + case 99: + return jjMoveStringLiteralDfa7_0(active0, 0x400000100L); + case 101: + if ((active0 & 0x20000000000L) != 0L) + return jjStartNfaWithStates_0(6, 41, 29); + else if ((active0 & 0x40000000000L) != 0L) + return jjStartNfaWithStates_0(6, 42, 29); + return jjMoveStringLiteralDfa7_0(active0, 0x80000100000000L); + case 102: + return jjMoveStringLiteralDfa7_0(active0, 0x1000000000000L); + case 108: + return jjMoveStringLiteralDfa7_0(active0, 0x800000000000000L); + case 110: + if ((active0 & 0x400L) != 0L) + return jjStartNfaWithStates_0(6, 10, 29); + break; + case 111: + return jjMoveStringLiteralDfa7_0(active0, 0x8000000000000L); + case 115: + if ((active0 & 0x1000000L) != 0L) + return jjStartNfaWithStates_0(6, 24, 29); + break; + case 116: + if ((active0 & 0x80000L) != 0L) + return jjStartNfaWithStates_0(6, 19, 29); + return jjMoveStringLiteralDfa7_0(active0, 0x80000000000L); + case 117: + return jjMoveStringLiteralDfa7_0(active0, 0x40000L); + case 121: + if ((active0 & 0x8000000L) != 0L) + return jjStartNfaWithStates_0(6, 27, 29); + break; + default: + break; + } + return jjStartNfa_0(5, active0, 0L); + } + + private int jjMoveStringLiteralDfa7_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(5, old0, 0L); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(6, active0, 0L); + return 7; + } + switch (curChar) { + case 99: + return jjMoveStringLiteralDfa8_0(active0, 0x1000000000L); + case 101: + if ((active0 & 0x40000L) != 0L) + return jjStartNfaWithStates_0(7, 18, 29); + else if ((active0 & 0x800000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 59, 29); + return jjMoveStringLiteralDfa8_0(active0, 0x80400000000L); + case 110: + return jjMoveStringLiteralDfa8_0(active0, 0x88000100000000L); + case 112: + if ((active0 & 0x1000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 48, 29); + break; + case 116: + if ((active0 & 0x100L) != 0L) + return jjStartNfaWithStates_0(7, 8, 29); + break; + default: + break; + } + return jjStartNfa_0(6, active0, 0L); + } + + private int jjMoveStringLiteralDfa8_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(6, old0, 0L); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(7, active0, 0L); + return 8; + } + switch (curChar) { + case 100: + if ((active0 & 0x80000000000L) != 0L) + return jjStartNfaWithStates_0(8, 43, 29); + break; + case 101: + if ((active0 & 0x1000000000L) != 0L) + return jjStartNfaWithStates_0(8, 36, 29); + break; + case 105: + return jjMoveStringLiteralDfa9_0(active0, 0x8000000000000L); + case 111: + return jjMoveStringLiteralDfa9_0(active0, 0x400000000L); + case 116: + if ((active0 & 0x80000000000000L) != 0L) + return jjStartNfaWithStates_0(8, 55, 29); + return jjMoveStringLiteralDfa9_0(active0, 0x100000000L); + default: + break; + } + return jjStartNfa_0(7, active0, 0L); + } + + private int jjMoveStringLiteralDfa9_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(7, old0, 0L); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(8, active0, 0L); + return 9; + } + switch (curChar) { + case 102: + if ((active0 & 0x400000000L) != 0L) + return jjStartNfaWithStates_0(9, 34, 29); + break; + case 115: + if ((active0 & 0x100000000L) != 0L) + return jjStartNfaWithStates_0(9, 32, 29); + break; + case 122: + return jjMoveStringLiteralDfa10_0(active0, 0x8000000000000L); + default: + break; + } + return jjStartNfa_0(8, active0, 0L); + } + + private int jjMoveStringLiteralDfa10_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(8, old0, 0L); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(9, active0, 0L); + return 10; + } + switch (curChar) { + case 101: + return jjMoveStringLiteralDfa11_0(active0, 0x8000000000000L); + default: + break; + } + return jjStartNfa_0(9, active0, 0L); + } + + private int jjMoveStringLiteralDfa11_0(long old0, long active0) { + if ((active0 &= old0) == 0L) + return jjStartNfa_0(9, old0, 0L); + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + jjStopStringLiteralDfa_0(10, active0, 0L); + return 11; + } + switch (curChar) { + case 100: + if ((active0 & 0x8000000000000L) != 0L) + return jjStartNfaWithStates_0(11, 51, 29); + break; + default: + break; + } + return jjStartNfa_0(10, active0, 0L); + } + + private void jjCheckNAdd(int state) { + if (jjrounds[state] != jjround) { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } + } + + private void jjAddStates(int start, int end) { + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); + } + + private void jjCheckNAddTwoStates(int state1, int state2) { + jjCheckNAdd(state1); + jjCheckNAdd(state2); + } + + private void jjCheckNAddStates(int start, int end) { + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); + } + + private void jjCheckNAddStates(int start) { + jjCheckNAdd(jjnextStates[start]); + jjCheckNAdd(jjnextStates[start + 1]); + } + + static final long[] jjbitVec0 = { + 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL + }; + static final long[] jjbitVec2 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL + }; + static final long[] jjbitVec3 = { + 0xfff0000000200002L, 0xffffffffffffdfffL, 0xfffff00f7fffffffL, 0x12000000007fffffL + }; + static final long[] jjbitVec4 = { + 0x0L, 0x0L, 0x420043c00000000L, 0xff7fffffff7fffffL + }; + static final long[] jjbitVec5 = { + 0xffffcffffffffL, 0xffffffffffff0000L, 0xf9ff3fffffffffffL, 0x401f00030003L + }; + static final long[] jjbitVec6 = { + 0x0L, 0x400000000000000L, 0xfffffffbffffd740L, 0xffffffcff7fffL + }; + static final long[] jjbitVec7 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffff003L, 0x33fffffffff199fL + }; + static final long[] jjbitVec8 = { + 0xfffe000000000000L, 0xfffffffe027fffffL, 0xffL, 0x707ffffff0000L + }; + static final long[] jjbitVec9 = { + 0x7fffffe00000000L, 0xfffe0000000007ffL, 0xffffffffffffffffL, 0x1c000060002fffffL + }; + static final long[] jjbitVec10 = { + 0x1ffffffd0000L, 0x0L, 0x3fffffffffL, 0x0L + }; + static final long[] jjbitVec11 = { + 0x23ffffffffffffe0L, 0x3ff010000L, 0x3c5fdfffff99fe0L, 0xf0003b0000000L + }; + static final long[] jjbitVec12 = { + 0x36dfdfffff987e0L, 0x1c00005e000000L, 0x23edfdfffffbafe0L, 0x100010000L + }; + static final long[] jjbitVec13 = { + 0x23cdfdfffff99fe0L, 0x3b0000000L, 0x3bfc718d63dc7e0L, 0x0L + }; + static final long[] jjbitVec14 = { + 0x3effdfffffddfe0L, 0x300000000L, 0x3effdfffffddfe0L, 0x340000000L + }; + static final long[] jjbitVec15 = { + 0x3fffdfffffddfe0L, 0x300000000L, 0x2ffbfffffc7fffe0L, 0x7fL + }; + static final long[] jjbitVec16 = { + 0x800dfffffffffffeL, 0x7fL, 0x200decaefef02596L, 0x3000005fL + }; + static final long[] jjbitVec17 = { + 0x1L, 0x7fffffffeffL, 0xf00L, 0x0L + }; + static final long[] jjbitVec18 = { + 0x6fbffffffffL, 0x3f0000L, 0xffffffff00000000L, 0x7fffffffff003fL + }; + static final long[] jjbitVec19 = { + 0xffffffffffffffffL, 0xffffffff83ffffffL, 0xffffff07ffffffffL, 0x3ffffffffffffffL + }; + static final long[] jjbitVec20 = { + 0xffffffffffffff7fL, 0xffffffff3d7f3d7fL, 0x7f3d7fffffff3d7fL, 0xffff7fffff7f7f3dL + }; + static final long[] jjbitVec21 = { + 0xffffffff7f3d7fffL, 0x7ffff7fL, 0xffffffff00000000L, 0x1fffffffffffffL + }; + static final long[] jjbitVec22 = { + 0xffffffffffffffffL, 0x7f9fffffffffffL, 0xffffffff07fffffeL, 0x7ffffffffffL + }; + static final long[] jjbitVec23 = { + 0x0L, 0x0L, 0xfffffffffffffL, 0x8000000L + }; + static final long[] jjbitVec24 = { + 0xffffffff00000000L, 0xffffffffffffffL, 0x1ffffffffffL, 0x0L + }; + static final long[] jjbitVec25 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffff0fffffffL, 0x3ffffffffffffffL + }; + static final long[] jjbitVec26 = { + 0xffffffff3f3fffffL, 0x3fffffffaaff3f3fL, 0x5fdfffffffffffffL, 0x1fdc1fff0fcf1fdcL + }; + static final long[] jjbitVec27 = { + 0x8000000000000000L, 0x8000000000000001L, 0xffff00000000L, 0x0L + }; + static final long[] jjbitVec28 = { + 0x3fbbd503e2ffc84L, 0xffffffff00000000L, 0xfL, 0x0L + }; + static final long[] jjbitVec29 = { + 0x73e03fe000000e0L, 0xfffffffffffffffeL, 0xfffffffe601fffffL, 0x7fffffffffffffffL + }; + static final long[] jjbitVec30 = { + 0xfffe1fffffffffe0L, 0xffffffffffffffffL, 0xffffff00007fffL, 0x0L + }; + static final long[] jjbitVec31 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffffffL, 0x0L + }; + static final long[] jjbitVec32 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x3fffffffffL, 0x0L + }; + static final long[] jjbitVec33 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x1fffL, 0x0L + }; + static final long[] jjbitVec34 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffL, 0x0L + }; + static final long[] jjbitVec35 = { + 0x3fffffffffffL, 0x0L, 0x0L, 0x0L + }; + static final long[] jjbitVec36 = { + 0x5f7ffdffa0f8007fL, 0xffffffffffffffdbL, 0x3ffffffffffffL, 0xfffffffffff80000L + }; + static final long[] jjbitVec37 = { + 0x3fffffffffffffffL, 0xffffffffffff0000L, 0xfffffffffffcffffL, 0xfff0000000000ffL + }; + static final long[] jjbitVec38 = { + 0x18000000000000L, 0xffd702000000e000L, 0xffffffffffffffffL, 0x1fffffffffffffffL + }; + static final long[] jjbitVec39 = { + 0x87fffffe00000010L, 0xffffffe007fffffeL, 0x7fffffffffffffffL, 0x631cfcfcfcL + }; + static final long[] jjbitVec40 = { + 0x0L, 0x0L, 0x420043cffffffffL, 0xff7fffffff7fffffL + }; + static final long[] jjbitVec41 = { + 0xffffffffffffffffL, 0x400000700007fffL, 0xfffffffbffffd740L, 0xffffffcff7fffL + }; + static final long[] jjbitVec42 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xfffffffffffff07bL, 0x33fffffffff199fL + }; + static final long[] jjbitVec43 = { + 0xfffe000000000000L, 0xfffffffe027fffffL, 0xbbfffffbfffe00ffL, 0x707ffffff0016L + }; + static final long[] jjbitVec44 = { + 0x7fffffe00000000L, 0xffff03ff003fffffL, 0xffffffffffffffffL, 0x1fff3dff9fefffffL + }; + static final long[] jjbitVec45 = { + 0xffff1fffffff8000L, 0x7ffL, 0x1ffffffffffffL, 0x0L + }; + static final long[] jjbitVec46 = { + 0xf3ffffffffffffeeL, 0xffcfff1f3fffL, 0xd3c5fdfffff99feeL, 0xfffcfb080399fL + }; + static final long[] jjbitVec47 = { + 0xd36dfdfffff987e4L, 0x1fffc05e003987L, 0xf3edfdfffffbafeeL, 0xffc100013bbfL + }; + static final long[] jjbitVec48 = { + 0xf3cdfdfffff99feeL, 0xffc3b0c0398fL, 0xc3bfc718d63dc7ecL, 0xff8000803dc7L + }; + static final long[] jjbitVec49 = { + 0xc3effdfffffddfeeL, 0xffc300603ddfL, 0xc3effdfffffddfecL, 0xffc340603ddfL + }; + static final long[] jjbitVec50 = { + 0xc3fffdfffffddfecL, 0xffc300803dcfL, 0x2ffbfffffc7fffecL, 0xc0000ff5f847fL + }; + static final long[] jjbitVec51 = { + 0x87fffffffffffffeL, 0x3ff7fffL, 0x3bffecaefef02596L, 0x33ff3f5fL + }; + static final long[] jjbitVec52 = { + 0xc2a003ff03000001L, 0xfffe07fffffffeffL, 0x1ffffffffeff0fdfL, 0x40L + }; + static final long[] jjbitVec53 = { + 0x3c7f6fbffffffffL, 0x3ff03ffL, 0xffffffff00000000L, 0x7fffffffff003fL + }; + static final long[] jjbitVec54 = { + 0xffffffff7f3d7fffL, 0x3fe0007ffff7fL, 0xffffffff00000000L, 0x1fffffffffffffL + }; + static final long[] jjbitVec55 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0x3ff080fffffL + }; + static final long[] jjbitVec56 = { + 0xffffffff03ff7800L, 0xffffffffffffffL, 0x3ffffffffffL, 0x0L + }; + static final long[] jjbitVec57 = { + 0x80007c000000f000L, 0x8000fc0000000001L, 0xffff00000000L, 0x21fff0000L + }; + static final long[] jjbitVec58 = { + 0x73efffe000000e0L, 0xfffffffffffffffeL, 0xfffffffe661fffffL, 0x7fffffffffffffffL + }; + static final long[] jjbitVec59 = { + 0x5f7ffdffe0f8007fL, 0xffffffffffffffdbL, 0x3ffffffffffffL, 0xfffffffffff80000L + }; + static final long[] jjbitVec60 = { + 0x18000f00000000L, 0xffd702000000e000L, 0xffffffffffffffffL, 0x9fffffffffffffffL + }; + static final long[] jjbitVec61 = { + 0x87fffffe03ff0010L, 0xffffffe007fffffeL, 0x7fffffffffffffffL, 0xe0000631cfcfcfcL + }; + + private int jjMoveNfa_0(int startState, int curPos) { + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 71; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (; ;) { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) { + long l = 1L << curChar; + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 1: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(0, 6); + else if ((0x100003600L & l) != 0L) { + if (kind > 3) + kind = 3; + jjCheckNAdd(0); + } else if (curChar == 47) + jjAddStates(7, 8); + else if (curChar == 36) { + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + } else if (curChar == 34) + jjCheckNAddStates(9, 11); + else if (curChar == 39) + jjAddStates(12, 13); + else if (curChar == 46) + jjCheckNAdd(5); + if ((0x3fe000000000000L & l) != 0L) { + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(2, 3); + } else if (curChar == 48) { + if (kind > 61) + kind = 61; + jjCheckNAddStates(14, 18); + } + break; + case 48: + if (curChar == 47) { + if (kind > 4) + kind = 4; + jjCheckNAddStates(19, 21); + } else if (curChar == 42) + jjstateSet[jjnewStateCnt++] = 46; + break; + case 0: + if ((0x100003600L & l) == 0L) + break; + if (kind > 3) + kind = 3; + jjCheckNAdd(0); + break; + case 2: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(2, 3); + break; + case 4: + if (curChar == 46) + jjCheckNAdd(5); + break; + case 5: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddStates(22, 24); + break; + case 7: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(8); + break; + case 8: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(8, 9); + break; + case 10: + if (curChar == 39) + jjAddStates(12, 13); + break; + case 11: + if ((0xffffff7fffffdbffL & l) != 0L) + jjCheckNAdd(12); + break; + case 12: + if (curChar == 39 && kind > 70) + kind = 70; + break; + case 14: + if ((0x8400000000L & l) != 0L) + jjCheckNAdd(12); + break; + case 15: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddTwoStates(16, 12); + break; + case 16: + if ((0xff000000000000L & l) != 0L) + jjCheckNAdd(12); + break; + case 17: + if ((0xf000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 18; + break; + case 18: + if ((0xff000000000000L & l) != 0L) + jjCheckNAdd(16); + break; + case 19: + if (curChar == 34) + jjCheckNAddStates(9, 11); + break; + case 20: + if ((0xfffffffbffffdbffL & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 22: + if ((0x8400000000L & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 23: + if (curChar == 34 && kind > 71) + kind = 71; + break; + case 24: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddStates(25, 28); + break; + case 25: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 26: + if ((0xf000000000000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 27; + break; + case 27: + if ((0xff000000000000L & l) != 0L) + jjCheckNAdd(25); + break; + case 28: + if (curChar != 36) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 29: + if ((0x3ff00100fffc1ffL & l) == 0L) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 30: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(0, 6); + break; + case 31: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(29, 31); + break; + case 33: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(34); + break; + case 34: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(34, 9); + break; + case 35: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(35, 36); + break; + case 37: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(38); + break; + case 38: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(38, 9); + break; + case 39: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(39, 40); + break; + case 40: + if (curChar != 46) + break; + if (kind > 65) + kind = 65; + jjCheckNAddStates(32, 34); + break; + case 41: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddStates(32, 34); + break; + case 43: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(44); + break; + case 44: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(44, 9); + break; + case 45: + if (curChar == 47) + jjAddStates(7, 8); + break; + case 46: + if (curChar == 42) + jjstateSet[jjnewStateCnt++] = 47; + break; + case 47: + if ((0xffff7fffffffffffL & l) != 0L && kind > 1) + kind = 1; + break; + case 49: + if (curChar != 47) + break; + if (kind > 4) + kind = 4; + jjCheckNAddStates(19, 21); + break; + case 50: + if ((0xffffffffffffdbffL & l) == 0L) + break; + if (kind > 4) + kind = 4; + jjCheckNAddStates(19, 21); + break; + case 51: + if ((0x2400L & l) != 0L && kind > 4) + kind = 4; + break; + case 52: + if (curChar == 10 && kind > 4) + kind = 4; + break; + case 53: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 52; + break; + case 54: + if (curChar != 48) + break; + if (kind > 61) + kind = 61; + jjCheckNAddStates(14, 18); + break; + case 56: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(56, 3); + break; + case 57: + if ((0xff000000000000L & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(57, 3); + break; + case 59: + if ((0x3ff000000000000L & l) != 0L) + jjAddStates(35, 36); + break; + case 60: + if (curChar == 46) + jjCheckNAdd(61); + break; + case 61: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(61, 62); + break; + case 63: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(64); + break; + case 64: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(64, 9); + break; + case 66: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(37, 39); + break; + case 67: + if (curChar == 46) + jjCheckNAdd(68); + break; + case 69: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(70); + break; + case 70: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 65) + kind = 65; + jjCheckNAddTwoStates(70, 9); + break; + default: + break; + } + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 1: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 3: + if ((0x100000001000L & l) != 0L && kind > 61) + kind = 61; + break; + case 6: + if ((0x2000000020L & l) != 0L) + jjAddStates(40, 41); + break; + case 9: + if ((0x5000000050L & l) != 0L && kind > 65) + kind = 65; + break; + case 11: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAdd(12); + break; + case 13: + if (curChar == 92) + jjAddStates(42, 44); + break; + case 14: + if ((0x14404410000000L & l) != 0L) + jjCheckNAdd(12); + break; + case 20: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 21: + if (curChar == 92) + jjAddStates(45, 47); + break; + case 22: + if ((0x14404410000000L & l) != 0L) + jjCheckNAddStates(9, 11); + break; + case 29: + if ((0x87fffffe87fffffeL & l) == 0L) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 32: + if ((0x2000000020L & l) != 0L) + jjAddStates(48, 49); + break; + case 36: + if ((0x2000000020L & l) != 0L) + jjAddStates(50, 51); + break; + case 42: + if ((0x2000000020L & l) != 0L) + jjAddStates(52, 53); + break; + case 47: + if (kind > 1) + kind = 1; + break; + case 50: + if (kind > 4) + kind = 4; + jjAddStates(19, 21); + break; + case 55: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(56); + break; + case 56: + if ((0x7e0000007eL & l) == 0L) + break; + if (kind > 61) + kind = 61; + jjCheckNAddTwoStates(56, 3); + break; + case 58: + if ((0x100000001000000L & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 59: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 61: + if ((0x7e0000007eL & l) != 0L) + jjAddStates(54, 55); + break; + case 62: + if ((0x1000000010000L & l) != 0L) + jjAddStates(56, 57); + break; + case 65: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(66); + break; + case 66: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(37, 39); + break; + case 68: + if ((0x1000000010000L & l) != 0L) + jjAddStates(58, 59); + break; + default: + break; + } + } while (i != startsAt); + } else { + int hiByte = (int) (curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: + do { + switch (jjstateSet[--i]) { + case 1: + if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 11: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 20: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(9, 11); + break; + case 29: + if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) + break; + if (kind > 72) + kind = 72; + jjCheckNAdd(29); + break; + case 47: + if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 1) + kind = 1; + break; + case 50: + if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) + break; + if (kind > 4) + kind = 4; + jjAddStates(19, 21); + break; + default: + break; + } + } while (i != startsAt); + } + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 71 - (jjnewStateCnt = startsAt))) + return curPos; + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + return curPos; + } + } + } + + private int jjMoveStringLiteralDfa0_2() { + switch (curChar) { + case 42: + return jjMoveStringLiteralDfa1_2(0x40L); + default: + return 1; + } + } + + private int jjMoveStringLiteralDfa1_2(long active0) { + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + return 1; + } + switch (curChar) { + case 47: + if ((active0 & 0x40L) != 0L) + return jjStopAtPos(1, 6); + break; + default: + return 2; + } + return 2; + } + + private int jjMoveStringLiteralDfa0_1() { + switch (curChar) { + case 42: + return jjMoveStringLiteralDfa1_1(0x20L); + default: + return 1; + } + } + + private int jjMoveStringLiteralDfa1_1(long active0) { + try { + curChar = input_stream.readChar(); + } + catch (IOException e) { + return 1; + } + switch (curChar) { + case 47: + if ((active0 & 0x20L) != 0L) + return jjStopAtPos(1, 5); + break; + default: + return 2; + } + return 2; + } + + static final int[] jjnextStates = { + 31, 32, 9, 35, 36, 39, 40, 48, 49, 20, 21, 23, 11, 13, 55, 57, + 3, 58, 65, 50, 51, 53, 5, 6, 9, 20, 21, 25, 23, 31, 32, 9, + 41, 42, 9, 59, 60, 66, 67, 68, 7, 8, 14, 15, 17, 22, 24, 26, + 33, 34, 37, 38, 43, 44, 61, 62, 63, 64, 69, 70, + }; + + private static boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) { + switch (hiByte) { + case 0: + return (jjbitVec2[i2] & l2) != 0L; + default: + if ((jjbitVec0[i1] & l1) != 0L) + return true; + return false; + } + } + + private static boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) { + switch (hiByte) { + case 0: + return (jjbitVec4[i2] & l2) != 0L; + case 2: + return (jjbitVec5[i2] & l2) != 0L; + case 3: + return (jjbitVec6[i2] & l2) != 0L; + case 4: + return (jjbitVec7[i2] & l2) != 0L; + case 5: + return (jjbitVec8[i2] & l2) != 0L; + case 6: + return (jjbitVec9[i2] & l2) != 0L; + case 7: + return (jjbitVec10[i2] & l2) != 0L; + case 9: + return (jjbitVec11[i2] & l2) != 0L; + case 10: + return (jjbitVec12[i2] & l2) != 0L; + case 11: + return (jjbitVec13[i2] & l2) != 0L; + case 12: + return (jjbitVec14[i2] & l2) != 0L; + case 13: + return (jjbitVec15[i2] & l2) != 0L; + case 14: + return (jjbitVec16[i2] & l2) != 0L; + case 15: + return (jjbitVec17[i2] & l2) != 0L; + case 16: + return (jjbitVec18[i2] & l2) != 0L; + case 17: + return (jjbitVec19[i2] & l2) != 0L; + case 18: + return (jjbitVec20[i2] & l2) != 0L; + case 19: + return (jjbitVec21[i2] & l2) != 0L; + case 20: + return (jjbitVec0[i2] & l2) != 0L; + case 22: + return (jjbitVec22[i2] & l2) != 0L; + case 23: + return (jjbitVec23[i2] & l2) != 0L; + case 24: + return (jjbitVec24[i2] & l2) != 0L; + case 30: + return (jjbitVec25[i2] & l2) != 0L; + case 31: + return (jjbitVec26[i2] & l2) != 0L; + case 32: + return (jjbitVec27[i2] & l2) != 0L; + case 33: + return (jjbitVec28[i2] & l2) != 0L; + case 48: + return (jjbitVec29[i2] & l2) != 0L; + case 49: + return (jjbitVec30[i2] & l2) != 0L; + case 77: + return (jjbitVec31[i2] & l2) != 0L; + case 159: + return (jjbitVec32[i2] & l2) != 0L; + case 164: + return (jjbitVec33[i2] & l2) != 0L; + case 215: + return (jjbitVec34[i2] & l2) != 0L; + case 250: + return (jjbitVec35[i2] & l2) != 0L; + case 251: + return (jjbitVec36[i2] & l2) != 0L; + case 253: + return (jjbitVec37[i2] & l2) != 0L; + case 254: + return (jjbitVec38[i2] & l2) != 0L; + case 255: + return (jjbitVec39[i2] & l2) != 0L; + default: + if ((jjbitVec3[i1] & l1) != 0L) + return true; + return false; + } + } + + private static boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2) { + switch (hiByte) { + case 0: + return (jjbitVec40[i2] & l2) != 0L; + case 2: + return (jjbitVec5[i2] & l2) != 0L; + case 3: + return (jjbitVec41[i2] & l2) != 0L; + case 4: + return (jjbitVec42[i2] & l2) != 0L; + case 5: + return (jjbitVec43[i2] & l2) != 0L; + case 6: + return (jjbitVec44[i2] & l2) != 0L; + case 7: + return (jjbitVec45[i2] & l2) != 0L; + case 9: + return (jjbitVec46[i2] & l2) != 0L; + case 10: + return (jjbitVec47[i2] & l2) != 0L; + case 11: + return (jjbitVec48[i2] & l2) != 0L; + case 12: + return (jjbitVec49[i2] & l2) != 0L; + case 13: + return (jjbitVec50[i2] & l2) != 0L; + case 14: + return (jjbitVec51[i2] & l2) != 0L; + case 15: + return (jjbitVec52[i2] & l2) != 0L; + case 16: + return (jjbitVec53[i2] & l2) != 0L; + case 17: + return (jjbitVec19[i2] & l2) != 0L; + case 18: + return (jjbitVec20[i2] & l2) != 0L; + case 19: + return (jjbitVec54[i2] & l2) != 0L; + case 20: + return (jjbitVec0[i2] & l2) != 0L; + case 22: + return (jjbitVec22[i2] & l2) != 0L; + case 23: + return (jjbitVec55[i2] & l2) != 0L; + case 24: + return (jjbitVec56[i2] & l2) != 0L; + case 30: + return (jjbitVec25[i2] & l2) != 0L; + case 31: + return (jjbitVec26[i2] & l2) != 0L; + case 32: + return (jjbitVec57[i2] & l2) != 0L; + case 33: + return (jjbitVec28[i2] & l2) != 0L; + case 48: + return (jjbitVec58[i2] & l2) != 0L; + case 49: + return (jjbitVec30[i2] & l2) != 0L; + case 77: + return (jjbitVec31[i2] & l2) != 0L; + case 159: + return (jjbitVec32[i2] & l2) != 0L; + case 164: + return (jjbitVec33[i2] & l2) != 0L; + case 215: + return (jjbitVec34[i2] & l2) != 0L; + case 250: + return (jjbitVec35[i2] & l2) != 0L; + case 251: + return (jjbitVec59[i2] & l2) != 0L; + case 253: + return (jjbitVec37[i2] & l2) != 0L; + case 254: + return (jjbitVec60[i2] & l2) != 0L; + case 255: + return (jjbitVec61[i2] & l2) != 0L; + default: + if ((jjbitVec3[i1] & l1) != 0L) + return true; + return false; + } + } + + public static final String[] jjstrLiteralImages = { + "", null, null, null, null, null, null, null, + "\141\142\163\164\162\141\143\164", "\141\163\163\145\162\164", "\142\157\157\154\145\141\156", + "\142\162\145\141\153", "\142\171\164\145", "\143\141\163\145", "\143\141\164\143\150", + "\143\150\141\162", "\143\154\141\163\163", "\143\157\156\163\164", + "\143\157\156\164\151\156\165\145", "\144\145\146\141\165\154\164", "\144\157", "\144\157\165\142\154\145", + "\145\154\163\145", "\145\156\165\155", "\145\170\164\145\156\144\163", "\146\141\154\163\145", + "\146\151\156\141\154", "\146\151\156\141\154\154\171", "\146\154\157\141\164", "\146\157\162", + "\147\157\164\157", "\151\146", "\151\155\160\154\145\155\145\156\164\163", + "\151\155\160\157\162\164", "\151\156\163\164\141\156\143\145\157\146", "\151\156\164", + "\151\156\164\145\162\146\141\143\145", "\154\157\156\147", "\156\141\164\151\166\145", "\156\145\167", + "\156\165\154\154", "\160\141\143\153\141\147\145", "\160\162\151\166\141\164\145", + "\160\162\157\164\145\143\164\145\144", "\160\165\142\154\151\143", "\162\145\164\165\162\156", + "\163\150\157\162\164", "\163\164\141\164\151\143", "\163\164\162\151\143\164\146\160", + "\163\165\160\145\162", "\163\167\151\164\143\150", + "\163\171\156\143\150\162\157\156\151\172\145\144", "\164\150\151\163", "\164\150\162\157\167", "\164\150\162\157\167\163", + "\164\162\141\156\163\151\145\156\164", "\164\162\165\145", "\164\162\171", "\166\157\151\144", + "\166\157\154\141\164\151\154\145", "\167\150\151\154\145", null, null, null, null, null, null, null, null, null, + null, null, null, null, null, "\50", "\51", "\173", "\175", "\133", "\135", "\73", + "\54", "\56", "\100", "\75", "\74", "\41", "\176", "\77", "\72", "\75\75", "\74\75", + "\76\75", "\41\75", "\174\174", "\46\46", "\53\53", "\55\55", "\53", "\55", "\52", + "\57", "\46", "\174", "\136", "\45", "\74\74", "\53\75", "\55\75", "\52\75", + "\57\75", "\46\75", "\174\75", "\136\75", "\45\75", "\74\74\75", "\76\76\75", + "\76\76\76\75", "\56\56\56", "\76\76\76", "\76\76", "\76", "\32", null,}; + public static final String[] lexStateNames = { + "DEFAULT", + "IN_FORMAL_COMMENT", + "IN_MULTI_LINE_COMMENT", + }; + public static final int[] jjnewLexState = { + -1, 1, 2, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + static final long[] jjtoToken = { + 0x3fffffffffffff01L, 0x1ffffffffffff9c2L, + }; + static final long[] jjtoSkip = { + 0x78L, 0x0L, + }; + static final long[] jjtoSpecial = { + 0x78L, 0x0L, + }; + static final long[] jjtoMore = { + 0x86L, 0x0L, + }; + protected JavaCharStream input_stream; + private final int[] jjrounds = new int[71]; + private final int[] jjstateSet = new int[142]; + StringBuilder image; + int jjimageLen; + int lengthOfMatch; + protected char curChar; + + public JavaParserTokenManager(JavaCharStream stream) { + if (JavaCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; + } + + public JavaParserTokenManager(JavaCharStream stream, int lexState) { + this(stream); + SwitchTo(lexState); + } + + public void ReInit(JavaCharStream stream) { + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); + } + + private void ReInitRounds() { + int i; + jjround = 0x80000001; + for (i = 71; i-- > 0;) + jjrounds[i] = 0x80000000; + } + + public void ReInit(JavaCharStream stream, int lexState) { + ReInit(stream); + SwitchTo(lexState); + } + + public void SwitchTo(int lexState) { + if (lexState >= 3 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; + } + + protected Token jjFillToken() { + Token t = Token.newToken(jjmatchedKind); + t.kind = jjmatchedKind; + String im = jjstrLiteralImages[jjmatchedKind]; + t.image = im == null ? input_stream.GetImage() : im; + t.beginLine = input_stream.getBeginLine(); + t.beginColumn = input_stream.getBeginColumn(); + t.endLine = input_stream.getEndLine(); + t.endColumn = input_stream.getEndColumn(); + return t; + } + + int curLexState = 0; + int defaultLexState = 0; + int jjnewStateCnt; + int jjround; + int jjmatchedPos; + int jjmatchedKind; + + public Token getNextToken() { + int kind; + Token specialToken = null; + Token matchedToken; + int curPos = 0; + + EOFLoop: + for (; ;) { + try { + curChar = input_stream.BeginToken(); + } + catch (IOException e) { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + return matchedToken; + } + image = null; + jjimageLen = 0; + + for (; ;) { + switch (curLexState) { + case 0: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + if (jjmatchedPos == 0 && jjmatchedKind > 124) { + jjmatchedKind = 124; + } + break; + case 1: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + if (jjmatchedPos == 0 && jjmatchedKind > 7) { + jjmatchedKind = 7; + } + break; + case 2: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_2(); + if (jjmatchedPos == 0 && jjmatchedKind > 7) { + jjmatchedKind = 7; + } + break; + } + if (jjmatchedKind != 0x7fffffff) { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { + matchedToken = jjFillToken(); + matchedToken.specialToken = specialToken; + TokenLexicalActions(matchedToken); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } else + if ((jjtoSkip[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { + if ((jjtoSpecial[jjmatchedKind >> 6] & 1L << (jjmatchedKind & 077)) != 0L) { + matchedToken = jjFillToken(); + if (specialToken == null) + specialToken = matchedToken; + else { + matchedToken.specialToken = specialToken; + specialToken = specialToken.next = matchedToken; + } + SkipLexicalActions(matchedToken); + } else + SkipLexicalActions(null); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + MoreLexicalActions(); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + curPos = 0; + jjmatchedKind = 0x7fffffff; + try { + curChar = input_stream.readChar(); + continue; + } + catch (IOException e1) { + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { + input_stream.readChar(); + input_stream.backup(1); + } + catch (IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } + } + } + + void SkipLexicalActions(Token matchedToken) { + switch (jjmatchedKind) { + default: + break; + } + } + + void MoreLexicalActions() { + jjimageLen += lengthOfMatch = jjmatchedPos + 1; + switch (jjmatchedKind) { + case 1: + if (image == null) + image = new StringBuilder(); + image.append(input_stream.GetSuffix(jjimageLen)); + jjimageLen = 0; + input_stream.backup(1); + break; + default: + break; + } + } + + void TokenLexicalActions(Token matchedToken) { + switch (jjmatchedKind) { + case 120: + if (image == null) + image = new StringBuilder(); + image.append(jjstrLiteralImages[120]); + matchedToken.kind = GT; + ((Token.GTToken) matchedToken).realKind = RUNSIGNEDSHIFT; + input_stream.backup(2); + matchedToken.image = ">"; + break; + case 121: + if (image == null) + image = new StringBuilder(); + image.append(jjstrLiteralImages[121]); + matchedToken.kind = GT; + ((Token.GTToken) matchedToken).realKind = RSIGNEDSHIFT; + input_stream.backup(1); + matchedToken.image = ">"; + break; + default: + break; + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTreeConstants.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTreeConstants.java new file mode 100644 index 0000000..09d504e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/JavaParserTreeConstants.java @@ -0,0 +1,255 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. ./JavaParserTreeConstants.java */ + + +package jaxx.compiler.java.parser; + +public interface JavaParserTreeConstants { + int JJTLINE = 0; + int JJTCOMPILATIONUNIT = 1; + int JJTPACKAGEDECLARATION = 2; + int JJTIMPORTDECLARATION = 3; + int JJTMODIFIERS = 4; + int JJTTYPEDECLARATION = 5; + int JJTCLASSORINTERFACEDECLARATION = 6; + int JJTEXTENDSLIST = 7; + int JJTIMPLEMENTSLIST = 8; + int JJTENUMDECLARATION = 9; + int JJTENUMBODY = 10; + int JJTENUMCONSTANT = 11; + int JJTTYPEPARAMETERS = 12; + int JJTTYPEPARAMETER = 13; + int JJTTYPEBOUND = 14; + int JJTCLASSORINTERFACEBODY = 15; + int JJTCLASSORINTERFACEBODYDECLARATION = 16; + int JJTFIELDDECLARATION = 17; + int JJTVARIABLEDECLARATOR = 18; + int JJTVARIABLEDECLARATORID = 19; + int JJTVARIABLEINITIALIZER = 20; + int JJTARRAYINITIALIZER = 21; + int JJTMETHODDECLARATION = 22; + int JJTMETHODDECLARATOR = 23; + int JJTFORMALPARAMETERS = 24; + int JJTFORMALPARAMETER = 25; + int JJTCONSTRUCTORDECLARATION = 26; + int JJTEXPLICITCONSTRUCTORINVOCATION = 27; + int JJTINITIALIZER = 28; + int JJTTYPE = 29; + int JJTREFERENCETYPE = 30; + int JJTCLASSORINTERFACETYPE = 31; + int JJTTYPEARGUMENTS = 32; + int JJTTYPEARGUMENT = 33; + int JJTWILDCARDBOUNDS = 34; + int JJTPRIMITIVETYPE = 35; + int JJTRESULTTYPE = 36; + int JJTNAME = 37; + int JJTNAMELIST = 38; + int JJTEXPRESSION = 39; + int JJTASSIGNMENTOPERATOR = 40; + int JJTASSIGNMENTEXPRESSION = 41; + int JJTCONDITIONALEXPRESSION = 42; + int JJTCONDITIONALOREXPRESSION = 43; + int JJTCONDITIONALANDEXPRESSION = 44; + int JJTINCLUSIVEOREXPRESSION = 45; + int JJTEXCLUSIVEOREXPRESSION = 46; + int JJTANDEXPRESSION = 47; + int JJTEQUALITYEXPRESSION = 48; + int JJTINSTANCEOFEXPRESSION = 49; + int JJTRELATIONALEXPRESSION = 50; + int JJTSHIFTEXPRESSION = 51; + int JJTADDITIVEEXPRESSION = 52; + int JJTMULTIPLICATIVEEXPRESSION = 53; + int JJTUNARYEXPRESSION = 54; + int JJTPREINCREMENTEXPRESSION = 55; + int JJTPREDECREMENTEXPRESSION = 56; + int JJTUNARYEXPRESSIONNOTPLUSMINUS = 57; + int JJTCASTLOOKAHEAD = 58; + int JJTPOSTFIXEXPRESSION = 59; + int JJTPOSTFIXOPERATOR = 60; + int JJTCASTEXPRESSION = 61; + int JJTPRIMARYEXPRESSION = 62; + int JJTMEMBERSELECTOR = 63; + int JJTPRIMARYPREFIX = 64; + int JJTPRIMARYSUFFIX = 65; + int JJTLITERAL = 66; + int JJTBOOLEANLITERAL = 67; + int JJTNULLLITERAL = 68; + int JJTARGUMENTS = 69; + int JJTARGUMENTLIST = 70; + int JJTALLOCATIONEXPRESSION = 71; + int JJTARRAYDIMSANDINITS = 72; + int JJTSTATEMENT = 73; + int JJTASSERTSTATEMENT = 74; + int JJTLABELEDSTATEMENT = 75; + int JJTBLOCK = 76; + int JJTBLOCKSTATEMENT = 77; + int JJTLOCALVARIABLEDECLARATION = 78; + int JJTEMPTYSTATEMENT = 79; + int JJTSTATEMENTEXPRESSION = 80; + int JJTSWITCHSTATEMENT = 81; + int JJTSWITCHLABEL = 82; + int JJTIFSTATEMENT = 83; + int JJTWHILESTATEMENT = 84; + int JJTDOSTATEMENT = 85; + int JJTFORSTATEMENT = 86; + int JJTFORINIT = 87; + int JJTSTATEMENTEXPRESSIONLIST = 88; + int JJTFORUPDATE = 89; + int JJTBREAKSTATEMENT = 90; + int JJTCONTINUESTATEMENT = 91; + int JJTRETURNSTATEMENT = 92; + int JJTTHROWSTATEMENT = 93; + int JJTSYNCHRONIZEDSTATEMENT = 94; + int JJTTRYSTATEMENT = 95; + int JJTRUNSIGNEDSHIFT = 96; + int JJTRSIGNEDSHIFT = 97; + int JJTANNOTATION = 98; + int JJTNORMALANNOTATION = 99; + int JJTMARKERANNOTATION = 100; + int JJTSINGLEMEMBERANNOTATION = 101; + int JJTMEMBERVALUEPAIRS = 102; + int JJTMEMBERVALUEPAIR = 103; + int JJTMEMBERVALUE = 104; + int JJTMEMBERVALUEARRAYINITIALIZER = 105; + int JJTANNOTATIONTYPEDECLARATION = 106; + int JJTANNOTATIONTYPEBODY = 107; + int JJTANNOTATIONTYPEMEMBERDECLARATION = 108; + int JJTDEFAULTVALUE = 109; + + + String[] jjtNodeName = { + "Line", + "CompilationUnit", + "PackageDeclaration", + "ImportDeclaration", + "Modifiers", + "TypeDeclaration", + "ClassOrInterfaceDeclaration", + "ExtendsList", + "ImplementsList", + "EnumDeclaration", + "EnumBody", + "EnumConstant", + "TypeParameters", + "TypeParameter", + "TypeBound", + "ClassOrInterfaceBody", + "ClassOrInterfaceBodyDeclaration", + "FieldDeclaration", + "VariableDeclarator", + "VariableDeclaratorId", + "VariableInitializer", + "ArrayInitializer", + "MethodDeclaration", + "MethodDeclarator", + "FormalParameters", + "FormalParameter", + "ConstructorDeclaration", + "ExplicitConstructorInvocation", + "Initializer", + "Type", + "ReferenceType", + "ClassOrInterfaceType", + "TypeArguments", + "TypeArgument", + "WildcardBounds", + "PrimitiveType", + "ResultType", + "Name", + "NameList", + "Expression", + "AssignmentOperator", + "AssignmentExpression", + "ConditionalExpression", + "ConditionalOrExpression", + "ConditionalAndExpression", + "InclusiveOrExpression", + "ExclusiveOrExpression", + "AndExpression", + "EqualityExpression", + "InstanceOfExpression", + "RelationalExpression", + "ShiftExpression", + "AdditiveExpression", + "MultiplicativeExpression", + "UnaryExpression", + "PreIncrementExpression", + "PreDecrementExpression", + "UnaryExpressionNotPlusMinus", + "CastLookahead", + "PostfixExpression", + "PostfixOperator", + "CastExpression", + "PrimaryExpression", + "MemberSelector", + "PrimaryPrefix", + "PrimarySuffix", + "Literal", + "BooleanLiteral", + "NullLiteral", + "Arguments", + "ArgumentList", + "AllocationExpression", + "ArrayDimsAndInits", + "Statement", + "AssertStatement", + "LabeledStatement", + "Block", + "BlockStatement", + "LocalVariableDeclaration", + "EmptyStatement", + "StatementExpression", + "SwitchStatement", + "SwitchLabel", + "IfStatement", + "WhileStatement", + "DoStatement", + "ForStatement", + "ForInit", + "StatementExpressionList", + "ForUpdate", + "BreakStatement", + "ContinueStatement", + "ReturnStatement", + "ThrowStatement", + "SynchronizedStatement", + "TryStatement", + "RUNSIGNEDSHIFT", + "RSIGNEDSHIFT", + "Annotation", + "NormalAnnotation", + "MarkerAnnotation", + "SingleMemberAnnotation", + "MemberValuePairs", + "MemberValuePair", + "MemberValue", + "MemberValueArrayInitializer", + "AnnotationTypeDeclaration", + "AnnotationTypeBody", + "AnnotationTypeMemberDeclaration", + "DefaultValue", + }; +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Node.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Node.java new file mode 100644 index 0000000..0760963 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Node.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. Node.java */ + + +package jaxx.compiler.java.parser; + +/* All AST nodes must implement this interface. It provides basic + machinery for constructing the parent and child relationships + between nodes. */ + +public interface Node { + + /** + * This method is called after the node has been made the current + * node. It indicates that child nodes can now be added to it. + */ + void jjtOpen(); + + /** + * This method is called after all the child nodes have been + * added. + */ + void jjtClose(); + + /** + * This pair of methods are used to inform the node of its + * parent. + * + * @param n node + */ + void jjtSetParent(Node n); + + Node jjtGetParent(); + + /** + * This method tells the node to add its argument to the node's + * list of children. + * + * @param n node + * @param i index ? + */ + void jjtAddChild(Node n, int i); + + /** + * @param i index of child + * @return a child node. The children are numbered + * from zero, left to right. + */ + Node jjtGetChild(int i); + + /** @return the number of children the node has. */ + int jjtGetNumChildren(); +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/ParseException.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/ParseException.java new file mode 100644 index 0000000..5631a76 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/ParseException.java @@ -0,0 +1,239 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */ + +package jaxx.compiler.java.parser; + +/** + * This exception is thrown when parse errors are encountered. + * You can explicitly create objects of this exception type by + * calling the method generateParseException in the generated + * parser. + * <p/> + * You can modify this class to customize your error reporting + * mechanisms so long as you retain the public fields. + */ +public class ParseException extends jaxx.compiler.CompilerException { + int line; + int column; + private static final long serialVersionUID = 6179854408401024700L; + + /** + * This constructor is used by the method "generateParseException" + * in the generated parser. Calling this constructor generates + * a new object of this type with the fields "currentToken", + * "expectedTokenSequences", and "tokenImage" set. The boolean + * flag "specialConstructor" is also set to true to indicate that + * this constructor was used to create this object. + * This constructor calls its super class with the empty string + * to force the "toString" method of parent class "Throwable" to + * print the error message in the form: + * ParseException: <result of getMessage> + * + * @param currentTokenVal ? + * @param expectedTokenSequencesVal ? + * @param tokenImageVal ? + */ + public ParseException(Token currentTokenVal, + int[][] expectedTokenSequencesVal, + String[] tokenImageVal + ) { + super(""); + specialConstructor = true; + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; + } + + /** + * The following constructors are for use by you for whatever + * purpose you can think of. Constructing the exception in this + * manner makes the exception behave in the normal way - i.e., as + * documented in the class "Throwable". The fields "errorToken", + * "expectedTokenSequences", and "tokenImage" do not contain + * relevant information. The JavaCC generated code does not use + * these constructors. + */ + + public ParseException() { + super(); + specialConstructor = false; + } + + public ParseException(String message) { + super(message); + specialConstructor = false; + } + + public ParseException(String message, int line, int column) { + super(message); + specialConstructor = false; + this.line = line; + this.column = column; + } + + + /** + * This variable determines which constructor was used to create + * this object and thereby affects the semantics of the + * "getMessage" method (see below). + */ + protected boolean specialConstructor; + + /** + * This is the last token that has been consumed successfully. If + * this object has been created due to a parse error, the token + * followng this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array + * of integers represents a sequence of tokens (by their ordinal + * values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated + * parser within which the parse error occurred. This array is + * defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * This method has the standard behavior when this object has been + * created using the standard constructors. Otherwise, it uses + * "currentToken" and "expectedTokenSequences" to generate a parse + * error message and returns it. If this object has been created + * due to a parse error, and you do not catch it (it gets thrown + * from the parser), then this method is called during the printing + * of the final stack trace, and hence the correct error message + * gets displayed. + */ + public String getMessage() { + if (!specialConstructor) { + return super.getMessage(); + } + StringBuilder expected = new StringBuilder(); + int maxSize = 0; + for (int[] expectedTokenSequence : expectedTokenSequences) { + if (maxSize < expectedTokenSequence.length) { + maxSize = expectedTokenSequence.length; + } + for (int anExpectedTokenSequence : expectedTokenSequence) { + expected.append(tokenImage[anExpectedTokenSequence]).append(" "); + } + if (expectedTokenSequence[expectedTokenSequence.length - 1] != 0) { + expected.append("..."); + } + expected.append(eol).append(" "); + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) retval += " "; + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += add_escapes(tok.image); + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + eol; + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + eol + " "; + } else { + retval += "Was expecting one of:" + eol + " "; + } + retval += expected.toString(); + return retval; + } + + + public int getLine() { + return line; + } + + public int getColumn() { + return column; + } + + /** The end of line string for this machine. */ + protected String eol = System.getProperty("line.separator", "\n"); + + /** + * Used to convert raw characters to their escaped version + * when these raw version cannot be used as part of an ASCII + * string literal. + * + * @param str text to treate + * @return the escaped version of text + */ + protected String add_escapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case 0: + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u").append(s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + } + } + return retval.toString(); + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/SimpleNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/SimpleNode.java new file mode 100644 index 0000000..d40904d --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/SimpleNode.java @@ -0,0 +1,160 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JJTree: Do not edit this line. SimpleNode.java */ + + +package jaxx.compiler.java.parser; + +import jaxx.compiler.reflect.ClassDescriptor; + +public class SimpleNode implements Node { + protected Node parent; + protected Node[] children; + protected int id; + protected JavaParser parser; + public Token firstToken; + public Token lastToken; + private ClassDescriptor javaType; + + + public SimpleNode(int i) { + id = i; + } + + public SimpleNode(JavaParser p, int i) { + this(i); + parser = p; + } + + + public int getId() { + return id; + } + + public void jjtOpen() { + } + + public void jjtClose() { + } + + public void jjtSetParent(Node n) { + parent = n; + } + + public Node jjtGetParent() { + return parent; + } + + public SimpleNode getParent() { + return (SimpleNode) parent; + } + + + public ClassDescriptor getJavaType() { + return javaType; + } + + + public void setJavaType(ClassDescriptor javaType) { + this.javaType = javaType; + } + + public void jjtAddChild(Node n, int i) { + if (children == null) { + children = new Node[i + 1]; + } else if (i >= children.length) { + Node c[] = new Node[i + 1]; + System.arraycopy(children, 0, c, 0, children.length); + children = c; + } + children[i] = n; + } + + public Node jjtGetChild(int i) { + return children[i]; + } + + public SimpleNode getChild(int i) { + return (SimpleNode) children[i]; + } + + public int jjtGetNumChildren() { + return (children == null) ? 0 : children.length; + } + + /* You can override these two methods in subclasses of SimpleNode to +customize the way the node appears when the tree is dumped. If +your output uses more than one line you should override +toString(String), otherwise overriding toString() is probably all +you need to do. */ + + @Override + public String toString() { + return getClass().getName() + "[" + getText() + "]"; + } + + public String toString(String prefix) { + return prefix + toString(); + } + + /* Override this method if you want to customize how the node dumps + out its children. */ + + public void dump(String prefix) { + System.out.println(toString(prefix)); + if (children != null) { + for (Node aChildren : children) { + SimpleNode n = (SimpleNode) aChildren; + if (n != null) { + n.dump(prefix + " "); + } + } + } + } + + private void appendSpecialTokens(StringBuilder s, Token st) { + if (st != null) { + appendSpecialTokens(s, st.specialToken); + s.append(st.image); + } + } + + + /** @return the text of the tokens comprising this node. */ + public String getText() { + StringBuilder text = new StringBuilder(); + Token t = firstToken; + while (t != null) { + appendSpecialTokens(text, t.specialToken); + text.append(t.image); + if (t == lastToken) + break; + t = t.next; + } + + return text.toString(); + } +} + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Token.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Token.java new file mode 100644 index 0000000..1f1ac3b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/Token.java @@ -0,0 +1,104 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */ + +package jaxx.compiler.java.parser; + +/** Describes the input token stream. */ + +public class Token { + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** + * beginLine and beginColumn describe the position of the first character + * of this token; endLine and endColumn describe the position of the + * last character of this token. + */ + public int beginLine, beginColumn, endLine, endColumn; + + /** The string image of the token. */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** Returns the image. */ + public String toString() { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simlpy add something like : + * <p/> + * case MyParserConstants.ID : return new IDToken(); + * <p/> + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use it in your lexical actions. + */ + public static final Token newToken(int ofKind) { + switch (ofKind) { + default: + return new Token(); + case JavaParserConstants.RUNSIGNEDSHIFT: + case JavaParserConstants.RSIGNEDSHIFT: + case JavaParserConstants.GT: + return new GTToken(); + } + } + + public static class GTToken extends Token { + int realKind = JavaParserConstants.GT; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/TokenMgrError.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/TokenMgrError.java new file mode 100644 index 0000000..08d7011 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/java/parser/TokenMgrError.java @@ -0,0 +1,151 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */ + +package jaxx.compiler.java.parser; + +public class TokenMgrError extends Error { + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** Lexical error occured. */ + static final int LEXICAL_ERROR = 0; + + /** An attempt wass made to create a second instance of a static token manager. */ + static final int STATIC_LEXER_ERROR = 1; + + /** Tried to change to an invalid lexical state. */ + static final int INVALID_LEXICAL_STATE = 2; + + /** Detected (and bailed out of) an infinite loop in the token manager. */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + private static final long serialVersionUID = -9131500865453532454L; + + /** + * Replaces unprintable characters by their espaced (or unicode escaped) + * equivalents in the given string + * + * @param str text to treate + * @return the treated text + */ + protected static String addEscapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case 0: + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u").append(s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + } + } + return retval.toString(); + } + + /** + * @param EOFSeen : indicates if EOF caused the lexicl error + * @param lexState : lexical state in which this error occured + * @param errorLine : line number when the error occured + * @param errorColumn : column number when the error occured + * @param errorAfter : prefix that was seen before this error occured + * @param curChar : the offending character + * Note: You can customize the lexical error message by modifying this method. + * @return a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return "Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? "<EOF> " : "\"" + addEscapes(String.valueOf(curChar)) + "\"" + " (" + (int) curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""; + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * <p/> + * "Internal Error : Please file a bug report .... " + * <p/> + * from this method for such cases in the release version of your parser. + */ + @Override + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + public TokenMgrError() { + } + + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptor.java new file mode 100644 index 0000000..3c2dfdc --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptor.java @@ -0,0 +1,299 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.reflect; + +import jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Arrays; + +/** + * Mirrors the class <code>java.lang.Class</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 abstract class ClassDescriptor { + + /** Logger. */ + private static final Log log = LogFactory.getLog(ClassDescriptor.class); + + public static final FieldDescriptor[] EMPTY_FIELD_DESCRIPTORS_ARRAY = + new FieldDescriptor[0]; + + private String name; + + private String packageName; + + private String superclass; + + private String[] interfaces; + + private boolean isInterface; + + private boolean isArray; + + private String componentType; + + private JAXXObjectDescriptor jaxxObjectDescriptor; + + private ClassLoader classLoader; + + private MethodDescriptor[] constructorDescriptors; + + private MethodDescriptor[] methodDescriptors; + + private FieldDescriptor[] fieldDescriptors; + + protected FieldDescriptor[] declaredFieldDescriptors; + + protected final ClassDescriptorHelper.ResolverType resolverType; + + public abstract MethodDescriptor getDeclaredMethodDescriptor( + String name, + ClassDescriptor... parameterTypes) throws NoSuchMethodException; + +// public abstract FieldDescriptor getDeclaredFieldDescriptor( +// String name) throws NoSuchFieldException; + + public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { + for (FieldDescriptor descriptor : declaredFieldDescriptors) { + if (name.equals(descriptor.getName())) { + if (log.isDebugEnabled()) { + log.debug("Using a declared field descriptor [" + name + + "] for " + getName()); + } + return descriptor; + } + } + throw new NoSuchFieldException(name); + } + + protected ClassDescriptor(ClassDescriptorHelper.ResolverType resolverType, + String name, + String packageName, + String superclass, + String[] interfaces, + boolean isInterface, + boolean isArray, + String componentType, + JAXXObjectDescriptor jaxxObjectDescriptor, + ClassLoader classLoader, + MethodDescriptor[] constructorDescriptors, + MethodDescriptor[] methodDescriptors, + FieldDescriptor[] fieldDescriptors) { + this( + resolverType, name, + packageName, + superclass, + interfaces, + isInterface, + isArray, + componentType, + jaxxObjectDescriptor, + classLoader, + constructorDescriptors, + methodDescriptors, + fieldDescriptors, + null + ); + } + + protected ClassDescriptor( + ClassDescriptorHelper.ResolverType resolverType, + String name, + String packageName, + String superclass, + String[] interfaces, + boolean isInterface, + boolean isArray, + String componentType, + JAXXObjectDescriptor jaxxObjectDescriptor, + ClassLoader classLoader, + MethodDescriptor[] constructorDescriptors, + MethodDescriptor[] methodDescriptors, + FieldDescriptor[] fieldDescriptors, + FieldDescriptor[] declaredFieldDescriptors) { + this.resolverType = resolverType; + this.name = name; + this.packageName = packageName; + this.superclass = superclass; + this.interfaces = interfaces; + this.isInterface = isInterface; + this.isArray = isArray; + this.componentType = componentType; + this.jaxxObjectDescriptor = jaxxObjectDescriptor; + this.classLoader = classLoader; + this.constructorDescriptors= constructorDescriptors; + this.methodDescriptors = methodDescriptors; + this.fieldDescriptors = fieldDescriptors; + this.declaredFieldDescriptors = declaredFieldDescriptors; + } + + + public ClassDescriptorHelper.ResolverType getResolverType() { + return resolverType; + } + + public String getName() { + return name; + } + + public String getSimpleName() { + int dot = name.lastIndexOf("."); + return dot == -1 ? name : name.substring(dot + 1); + } + + public String getPackageName() { + return packageName; + } + + public ClassDescriptor getSuperclass() { + return getClassDescriptor(superclass); + + } + + public ClassDescriptor[] getInterfaces() { + ClassDescriptor[] result = new ClassDescriptor[interfaces.length]; + for (int i = 0; i < result.length; i++) { + result[i] = getClassDescriptor(interfaces[i]); + } + return result; + } + + public boolean isInterface() { + return isInterface; + } + + public boolean isArray() { + return isArray; + } + + public ClassDescriptor getComponentType() { + return getClassDescriptor(componentType); + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public MethodDescriptor[] getConstructorDescriptors() { + return constructorDescriptors; + } + + public MethodDescriptor[] getMethodDescriptors() { + return methodDescriptors; + } + + public MethodDescriptor getMethodDescriptor(String name, + ClassDescriptor... parameterTypes) throws NoSuchMethodException { + for (MethodDescriptor m : methodDescriptors) { + if (m.getName().equals(name) && + m.getParameterTypes().length == parameterTypes.length && + Arrays.equals(m.getParameterTypes(), parameterTypes)) { + return m; + } + } + throw new NoSuchMethodException( + "Could not find method " + name + "(" + + Arrays.asList(parameterTypes) + ") in " + getName()); + } + + public FieldDescriptor[] getFieldDescriptors() { + return fieldDescriptors; + } + + public FieldDescriptor[] getDeclaredFieldDescriptors() { + return declaredFieldDescriptors==null? EMPTY_FIELD_DESCRIPTORS_ARRAY : declaredFieldDescriptors; + } + + public FieldDescriptor getFieldDescriptor(String name) throws NoSuchFieldException { + for (FieldDescriptor fieldDescriptor : fieldDescriptors) { + if (fieldDescriptor.getName().equals(name)) { + return fieldDescriptor; + } + } + throw new NoSuchFieldException( + "Could not find field " + name + " in " + getName()); + } + + public JAXXObjectDescriptor getJAXXObjectDescriptor() { + return jaxxObjectDescriptor; + } + + public boolean isAssignableFrom(ClassDescriptor descriptor) { + while (descriptor != null) { + if (equals(descriptor)) { + return true; + } + for (ClassDescriptor anInterface : descriptor.getInterfaces()) { + if (equals(anInterface) || isAssignableFrom(anInterface)) { + return true; + } + } + descriptor = descriptor.getSuperclass(); + } + return false; + } + + @Override + public String toString() { + return "ClassDescriptor[" + getName() + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ClassDescriptor)) return false; + + ClassDescriptor that = (ClassDescriptor) o; + + return name.equals(that.name); + + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + protected ClassDescriptor getClassDescriptor(String fqn) { + if (fqn == null) { + return null; + } + + try { + ClassDescriptor result = ClassDescriptorHelper.getClassDescriptor( + fqn, + getClassLoader() + ); + return result; + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorHelper.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorHelper.java new file mode 100644 index 0000000..d3148a9 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorHelper.java @@ -0,0 +1,538 @@ +/* + * #%L + * JAXX :: Compiler + * * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.reflect; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import jaxx.compiler.JAXXFactory; +import jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaClass; +import jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJavaFile; +import jaxx.compiler.reflect.resolvers.ClassDescriptorResolverFromJaxxFile; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; + +/** + * 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). + * <p/> + * <b>Note : </b> Was previously {@code ClassDescriptorLoader}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ClassDescriptorHelper { + + /** Logger */ + private static final Log log = LogFactory.getLog(ClassDescriptorHelper.class); + + /** + * Constants to define who load a {@link ClassDescriptor}. + * <p/> + * This will be usefull in some case (for consturctor for example when some + * descriptors are not fully loaded... + * + * @since 2.4 + */ + public enum ResolverType { + JAVA_CLASS, + JAVA_FILE, + JAXX_FILE + } + + private static boolean SHOW_LOADING = log.isDebugEnabled(); + + private static Map<String, ClassDescriptor> descriptors = + new HashMap<String, ClassDescriptor>(); + + private static Map<ResolverType, ClassDescriptorResolver> descriptorResolvers; + + protected static Map<ResolverType, ClassDescriptorResolver> getDescriptorResolvers() { + if (descriptorResolvers == null) { + descriptorResolvers = new EnumMap<ResolverType, ClassDescriptorResolver>(ResolverType.class); + descriptorResolvers.put(ResolverType.JAVA_CLASS, new ClassDescriptorResolverFromJavaClass()); + descriptorResolvers.put(ResolverType.JAVA_FILE, new ClassDescriptorResolverFromJavaFile()); + descriptorResolvers.put(ResolverType.JAXX_FILE, new ClassDescriptorResolverFromJaxxFile()); + } + return descriptorResolvers; + } + + private ClassDescriptorHelper() { + // on instance + } + + public static boolean isAssignableFrom(ClassDescriptor classDescriptor, + Class<?> awareClass) throws ClassNotFoundException { + ClassDescriptor awareDescriptor = getClassDescriptor(awareClass); + boolean result = awareDescriptor.isAssignableFrom(classDescriptor); + return result; + } + + public static ClassDescriptor getClassDescriptor(String className) throws ClassNotFoundException { + + ClassDescriptor descriptor = getClassDescriptor(className, + Thread.currentThread().getContextClassLoader()); + return descriptor; + } + + public static ClassDescriptor getClassDescriptor(Class<?> javaClass) { + try { + return getClassDescriptor(javaClass.getName(), + javaClass.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + public static URL getURL(ClassLoader classLoader, String className, String clasifier) { + String relativePath = className.replaceAll("\\.", "/"); + String path = relativePath + "." + clasifier; + if (log.isDebugEnabled()) { + log.debug("Path to search : " + path); + } + URL url = classLoader.getResource(path); + return url; + } + + public static ClassDescriptor getClassDescriptor( + String className, + ClassLoader classLoader) throws ClassNotFoundException { + + if (classLoader == null) { + classLoader = ClassDescriptorHelper.class.getClassLoader(); + } + + ClassDescriptor result = descriptors.get(className); + if (result != null) { + + // found in cache + if (log.isTraceEnabled()) { + log.trace("resolved " + result + " from cache."); + } + return result; + } + + JAXXEngine engine = JAXXFactory.isEngineRegistred() ? + JAXXFactory.getEngine() : null; + + String relativePathPattern = ".*";// + className + ".*"; // used to ensure that the located resource has the right character cases + + if (engine != null) { + + JAXXCompilerFile file = engine.getJAXXCompilerFile(className); + + if (file != null) { + + // use the symbole table of this jaxx file on computation + + if (SHOW_LOADING) { + log.info("from JAXXFile " + file.getJaxxFile()); + } + result = getClassDescriptor0( + ResolverType.JAXX_FILE, + className, + file.getJAXXFileURL(), + classLoader + ); + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] loaded"); + } + + return result; + } + } + + // the class is not in this compile set, try to have it from java + // sources or classes. + + // find the most recently updated source for the class -- Java source, JAXX source, or compiled class file + long javaLastModified = -1; + URL javaFile = getURL(classLoader, className, "java"); + if (javaFile != null && + javaFile.toString().startsWith("file:") && + javaFile.toString().matches(relativePathPattern)) { + javaLastModified = JAXXCompiler.URLtoFile(javaFile).lastModified(); + if (log.isTraceEnabled()) { + log.trace("[" + className + "] javaFile lastModified " + javaLastModified); + } + } + + long classLastModified = -1; + URL classFile = getURL(classLoader, className, "class"); + if (classFile != null && + classFile.toString().startsWith("file:") && + classFile.toString().matches(relativePathPattern)) { + classLastModified = JAXXCompiler.URLtoFile(classFile).lastModified(); + if (log.isTraceEnabled()) { + log.trace("[" + className + "] class lastModified " + classLastModified); + } + } + + // there is a java source and is the last modified + if (javaLastModified != -1 && javaLastModified > classLastModified) { + + // java file exist and it is the last modified file, so use it + + if (SHOW_LOADING) { + log.info("from JavaFile " + javaFile); + } + + result = getClassDescriptor0( + ResolverType.JAVA_FILE, + className, + javaFile, + classLoader + ); + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] loaded"); + } + return result; + } + + // use the class ... + + if (SHOW_LOADING) { + log.info("from class " + className); + } + + result = getClassDescriptor0( + ResolverType.JAVA_CLASS, + className, + classFile, + classLoader + ); + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] loaded"); + } + + if (result != null) { + return result; + } + + // can NOT come here, means could not find result... + + throw new IllegalStateException( + "Can not find descriptor for " + className); + } + + protected static ClassDescriptor getClassDescriptor0( + ResolverType resolverType, + String className, + URL source, + ClassLoader classLoader) throws ClassNotFoundException { + + if (log.isDebugEnabled()) { + log.debug("Loading class descriptor for [" + className + + "] with " + resolverType); + } + + Map<ResolverType, ClassDescriptorResolver> resolvers = + getDescriptorResolvers(); + + ClassDescriptorResolver resolver = resolvers.get(resolverType); + + resolver.setClassLoader(classLoader); + + ClassDescriptor result = resolver.resolvDescriptor(className, source); + if (result != null) { + descriptors.put(className, result); + } + return result; + } + + public static Class<?> getPrimitiveBoxedClass(String className) { + 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 Integer.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 Character.class; + } + if (className.equals("void")) { + return Void.class; + } + return null; + } + + public static Class<?> getPrimitiveClass( + String className) 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; + } + if (className.equals("void")) { + return void.class; + } + // detect arrays + int arrayCount = 0; + while (className.endsWith("[]")) { + arrayCount++; + className = className.substring(0, className.length() - 2); + } + Class<?> klass; + if (arrayCount > 0) { + klass = getPrimitiveClass(className); + if (klass == null) { + // none primitive array + return null; + } + // must take the boxed class, other it does not works + // to make a Class.forName("[Lchar;"); but works + // with Class.forName("[LCharacter;"); ... + klass = getPrimitiveBoxedClass(className); + className = klass.getName(); + + className = "L" + className + ";"; + while (arrayCount > 0) { + className = "[" + className; + arrayCount--; + } + //System.out.println("primitive array class "+className); + return Class.forName(className); + } + return null; + } + + public static Class<?> getClass(String className, + ClassLoader classLoader) throws ClassNotFoundException { + Class<?> klass = getPrimitiveClass(className); + if (klass != null) { + return klass; + } + // try an array of none primitive classes + 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) || +// JAXXObject.class.equals(jaxxClass)) { +// return null; +// } +// try { +// Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor"); +// 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); +// } +// } + + 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()); + } + + public static void reset() { + descriptors.clear(); + } + + public 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 + ); + } + + public static MethodDescriptor createMethodDescriptor(Constructor<?> javaMethod, + ClassLoader classLoader) { + String methodName = javaMethod.getName(); + int modifiers = javaMethod.getModifiers(); + String returnType = null; + 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 + ); + } + + public 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); + } + + public static JAXXObjectDescriptor getJAXXObjectDescriptor(Class<?> jaxxClass) { + if (!JAXXObject.class.isAssignableFrom(jaxxClass) || + JAXXObject.class.equals(jaxxClass)) { + return null; + } + try { + Method getJAXXObjectDescriptor = jaxxClass.getMethod("$getJAXXObjectDescriptor"); + 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); + } + } + + public static void setShowLoading(boolean b) { + SHOW_LOADING = b; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorResolver.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorResolver.java new file mode 100644 index 0000000..6804caf --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/ClassDescriptorResolver.java @@ -0,0 +1,70 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +import java.net.URL; + +/** + * Contract of a resolver of class descriptor. + * <p/> + * The unique method {@link #resolvDescriptor(String, URL)} will returns the + * descriptor if can be found. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public abstract class ClassDescriptorResolver { + + private ClassLoader classLoader; + + private ClassDescriptorHelper.ResolverType resolverType; + + protected ClassDescriptorResolver(ClassDescriptorHelper.ResolverType resolverType) { + this.resolverType = resolverType; + } + + public ClassDescriptorHelper.ResolverType getResolverType() { + return resolverType; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * @param className the fully qualified name of the class + * @param source the source of the class (java file, jaxx file, class) + * @return the descriptor of the given class + * @throws ClassNotFoundException if class descriptor could not be found. + */ + public abstract ClassDescriptor resolvDescriptor(String className, + URL source) throws ClassNotFoundException; + + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/FieldDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/FieldDescriptor.java new file mode 100644 index 0000000..ee0df24 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/FieldDescriptor.java @@ -0,0 +1,57 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.reflect; + +/** + * Mirrors the class <code>java.lang.ref.Field</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 FieldDescriptor extends MemberDescriptor { + + private String type; + + public FieldDescriptor(String name, int modifiers, String type, ClassLoader classLoader) { + super(name, modifiers, classLoader); + this.type = type; + } + + public ClassDescriptor getType() { + try { + return ClassDescriptorHelper.getClassDescriptor(type, getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Type not found for field " + this, e); + } catch (Exception e) { + throw new RuntimeException("Type not found for field " + this, e); + } + } + + @Override + public String toString() { + return super.toString() + " type : [" + type + "]"; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MemberDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MemberDescriptor.java new file mode 100644 index 0000000..df560f3 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MemberDescriptor.java @@ -0,0 +1,62 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.reflect; + +/** + * Mirrors the class <code>java.lang.ref.Member</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 abstract class MemberDescriptor { + + private String name; + private int modifiers; + private ClassLoader classLoader; + + MemberDescriptor(String name, int modifiers, ClassLoader classLoader) { + this.name = name; + this.modifiers = modifiers; + this.classLoader = classLoader; + } + + public String getName() { + return name; + } + + public int getModifiers() { + return modifiers; + } + + protected ClassLoader getClassLoader() { + return classLoader; + } + + @Override + public String toString() { + return getClass().getName() + "[" + getName() + "]"; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MethodDescriptor.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MethodDescriptor.java new file mode 100644 index 0000000..c25ce9e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/MethodDescriptor.java @@ -0,0 +1,77 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.reflect; + +import jaxx.compiler.JAXXCompiler; + +import java.util.Arrays; + +/** + * Mirrors the class <code>java.lang.ref.Method</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 MethodDescriptor extends MemberDescriptor { + + private String returnType; + private String[] parameterTypes; + + public MethodDescriptor(String name, int modifiers, String returnType, String[] parameterTypes, ClassLoader classLoader) { + super(name, modifiers, classLoader); + this.returnType = returnType; + this.parameterTypes = parameterTypes; + if (JAXXCompiler.STRICT_CHECKS && Arrays.asList(parameterTypes).contains(null)) { + throw new NullPointerException(name); + } + } + + public ClassDescriptor getReturnType() { + try { + //TC 20090228 : fix bug when no return type defined (constructor method) + if (returnType == null) { + return null; + } + return ClassDescriptorHelper.getClassDescriptor(returnType); + } catch (ClassNotFoundException e) { + throw new RuntimeException("could not find return type " + returnType, e); + } + } + + public ClassDescriptor[] getParameterTypes() { + ClassDescriptor[] result = new ClassDescriptor[parameterTypes.length]; + try { + for (int i = 0; i < result.length; i++) { + if (parameterTypes[i] != null) { + result[i] = ClassDescriptorHelper.getClassDescriptor(parameterTypes[i], getClassLoader()); + } + } + return result; + } catch (ClassNotFoundException e) { + throw new RuntimeException("could not find the parameter types " + Arrays.toString(parameterTypes), e); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java new file mode 100644 index 0000000..5ce858c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaClass.java @@ -0,0 +1,203 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect.resolvers; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.ClassDescriptorResolver; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; + +/** + * To obtain a class descriptor from a java source file. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJavaClass extends ClassDescriptorResolver { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJavaClass.class); + + public ClassDescriptorResolverFromJavaClass() { + super(ClassDescriptorHelper.ResolverType.JAVA_CLASS); + } + + @Override + public ClassDescriptor resolvDescriptor(String className, + URL source) throws ClassNotFoundException { + + if (log.isDebugEnabled()) { + log.debug("for source " + className); + } + + Class<?> javaClass = + ClassDescriptorHelper.getClass(className, getClassLoader()); + + 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; + ClassLoader classLoader = javaClass.getClassLoader(); + Constructor<?>[] javaConstructors = javaClass.getConstructors(); + MethodDescriptor[] constructors = new MethodDescriptor[javaConstructors.length]; + for (int i = 0; i < constructors.length; i++) { + constructors[i] = ClassDescriptorHelper.createMethodDescriptor( + javaConstructors[i], + javaClass.getClassLoader() + ); + } + Method[] javaMethods = javaClass.getMethods(); + MethodDescriptor[] methods = new MethodDescriptor[javaMethods.length]; + for (int i = 0; i < methods.length; i++) { + methods[i] = ClassDescriptorHelper.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] = ClassDescriptorHelper.createFieldDescriptor( + javaFields[i], + javaClass.getClassLoader() + ); + } + + Field[] javaDeclaredFields = javaClass.getDeclaredFields(); + FieldDescriptor[] declaredFields = + new FieldDescriptor[javaDeclaredFields.length]; + for (int i = 0; i < declaredFields .length; i++) { + declaredFields[i] = ClassDescriptorHelper.createFieldDescriptor( + javaDeclaredFields[i], + javaClass.getClassLoader() + ); + } + + JAXXObjectDescriptor jaxxObjectDescriptor = + ClassDescriptorHelper.getJAXXObjectDescriptor(javaClass); + + return new JavaClassClassDescriptor( + javaClass, + name, + packageName, + superclassName, + interfaceNames, + isInterface, + isArray, + componentTypeName, + jaxxObjectDescriptor, + classLoader, + constructors, + methods, + fields, + declaredFields + ); + } + + + private class JavaClassClassDescriptor extends ClassDescriptor { + + private final Class<?> javaClass; + + public JavaClassClassDescriptor( + Class<?> javaClass, + String name, + String packageName, + String superclassName, + String[] interfaceNames, + boolean anInterface, + boolean array, + String componentTypeName, + JAXXObjectDescriptor jaxxObjectDescriptor, + ClassLoader classLoader, + MethodDescriptor[] constructors, + MethodDescriptor[] methods, + FieldDescriptor[] fields, + FieldDescriptor[] declaredFields + ) { + super( + ClassDescriptorResolverFromJavaClass.this.getResolverType(), + name, + packageName, + superclassName, + interfaceNames, + anInterface, + array, + componentTypeName, + jaxxObjectDescriptor, + classLoader, + constructors, + methods, + fields, + declaredFields + ); + this.javaClass = javaClass; + } + +// @Override +// public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { +// return ClassDescriptorHelper.createFieldDescriptor(javaClass.getDeclaredField(name), +// javaClass.getClassLoader() +// ); +// } + + @Override + 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 ClassDescriptorHelper.createMethodDescriptor(javaClass.getDeclaredMethod(name, parameterTypeClasses), javaClass.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + } + + +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java new file mode 100644 index 0000000..4d28a57 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFile.java @@ -0,0 +1,745 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect.resolvers; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXFactory; +import jaxx.compiler.java.parser.JavaParser; +import jaxx.compiler.java.parser.JavaParserTreeConstants; +import jaxx.compiler.java.parser.ParseException; +import jaxx.compiler.java.parser.SimpleNode; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.ClassDescriptorResolver; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.tags.TagManager; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * To obtain a class descriptor from a java source file. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJavaFile extends ClassDescriptorResolver { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJavaFile.class); + + public ClassDescriptorResolverFromJavaFile() { + super(ClassDescriptorHelper.ResolverType.JAVA_FILE); + } + + @Override + public ClassDescriptor resolvDescriptor(String className, + URL source) throws ClassNotFoundException { + + ClassLoader classLoader = getClassLoader(); + + try { + InputStream in = source.openStream(); + ClassDescriptor result; + Reader reader = new InputStreamReader(in, "utf-8"); + try { + + String displayName = source.toString(); + if (log.isDebugEnabled()) { + log.debug("for source " + displayName); + } + JavaFileParser parser = new JavaFileParser(classLoader); + if (log.isDebugEnabled()) { + log.debug("starting parsing : " + displayName); + } + try { + parser.doParse(displayName, reader); + } catch (Exception e) { +// log.error(e.getMessage()); + throw new RuntimeException(e); + } + result = new JavaFileClassDescriptor(parser, classLoader); + + } finally { + + reader.close(); + } + return result; + } catch (IOException e) { + throw new ClassNotFoundException( + "Could not resolv descriptor from source " + source, + e); + } + } + + private class JavaFileClassDescriptor extends ClassDescriptor { + + public JavaFileClassDescriptor(JavaFileParser parser, + ClassLoader classLoader) { + super( + ClassDescriptorResolverFromJavaFile.this.getResolverType(), + parser.className, + parser.packageName, + parser.superclass, + parser.interfaces.toArray(new String[parser.interfaces.size()]), + parser.isInterface, + false, + null, + parser.jaxxObjectDescriptorValue == null ? null : JAXXUtil.decodeCompressedJAXXObjectDescriptor(parser.jaxxObjectDescriptorValue), + classLoader, + parser.constructors.toArray(new MethodDescriptor[parser.constructors.size()]), + parser.methods.toArray(new MethodDescriptor[parser.methods.size()]), + parser.fields.toArray(new FieldDescriptor[parser.fields.size()]), + parser.declaredFields.toArray(new FieldDescriptor[parser.declaredFields.size()]) + ); + + } + +// @Override +// public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { +// for (FieldDescriptor descriptor : declaredFieldDescriptors) { +// if (name.equals(descriptor.getName())) { +// if (log.isDebugEnabled()) { +// log.debug("Using a declared field descriptor [" + name + "] for " + getName()); +// } +// return descriptor; +// } +// } +// throw new NoSuchFieldException(name); +// } + + @Override + public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor... parameterTypes) throws NoSuchMethodException { + throw new NoSuchMethodException(name); + } + + } + + public static class JavaFileParser { + + /** Logger */ + static private final Log log = LogFactory.getLog(JavaFileParser.class); + + /** + * the compiler used (this is a dummy compiler with no link with any file). + * <p/> + * FIXME-TC20100504 We should remove this link : should not need of a + * compiler to parse a java files. + */ + private JAXXCompiler compiler; + + /** fully qualified name of the class */ + private String className; + + /** package of the class */ + private String packageName; + + /** fully qualified name of the super class or {@code null} if no super class. */ + private String superclass; + + /** + * flag to known if we deal with an enum (the state is setted in the + * {@link #doParse(String, Reader)} method). + */ + private boolean isEnum; + + /** + * flag to known if we deal with an interface(the state is setted in the + * {@link #doParse(String, Reader)} method). + */ + private boolean isInterface; + + /** set of fully qualified names of interfaces of the class. */ + private Set<String> interfaces; + + /** public methods of the class */ + private List<MethodDescriptor> methods; + + private List<MethodDescriptor> constructors; + + /** none public methods of the class */ +// private List<MethodDescriptor> declaredMethods; + + /** public fields of the class */ + private List<FieldDescriptor> fields; + + /** none public fields of the class */ + private List<FieldDescriptor> declaredFields; + + /** + * If sets, compressed value of the $jaxxObjectDescriptor field, this means + * the class if a JAXXObject implementation. + */ + private String jaxxObjectDescriptorValue; + + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + + + /** + * To test if a compilation unit was already parsed. If so, then stop + * parsing the java file : one parsing can only give one class + * descriptor. + * + * @since 2.4.2 + */ + private boolean firstTypeScanned; + + protected JavaFileParser(ClassLoader classLoader) { + //FIXME-TC-20100504 : shoudl remove this to make the parser free of jaxx :) + // We could imagine just to offers to the parser a list of namespaces + // (for class resolving)... + compiler = JAXXFactory.newDummyCompiler(classLoader); + methods = new ArrayList<MethodDescriptor>(); + constructors = new ArrayList<MethodDescriptor>(); +// declaredMethods = new ArrayList<MethodDescriptor>(); + interfaces = new HashSet<String>(); + fields = new ArrayList<FieldDescriptor>(); + declaredFields = new ArrayList<FieldDescriptor>(); + superclass = Object.class.getName(); + } + + + public void doParse(String className, Reader src) throws ClassNotFoundException { + + // reset this internal state + firstTypeScanned = false; + + try { + JavaParser p = new JavaParser(src); + p.CompilationUnit(); + SimpleNode node = p.popNode(); + if (node != null) { + scanCompilationUnit(node); + if (isInterface) { + + // remove super class + superclass = null; + + // load all super classes + if (!interfaces.isEmpty()) { + for (String anInterface : interfaces) { + ClassDescriptor superclassDescriptor = ClassDescriptorHelper.getClassDescriptor(anInterface, compiler.getClassLoader()); + methods.addAll(Arrays.asList(superclassDescriptor.getMethodDescriptors())); + fields.addAll(Arrays.asList(superclassDescriptor.getFieldDescriptors())); + } + } + } + + if (isEnum) { + + // super class is always Enum + + superclass = Enum.class.getName(); + } + if (superclass != null) { + //FIXME-TC20100504 This is not good, should add nothing here + // and modify the algorithm of ClassDescriptor to go and seek + // in super classes on interfaces if required. + + ClassDescriptor superclassDescriptor = ClassDescriptorHelper.getClassDescriptor(superclass, compiler.getClassLoader()); + methods.addAll(Arrays.asList(superclassDescriptor.getMethodDescriptors())); + fields.addAll(Arrays.asList(superclassDescriptor.getFieldDescriptors())); + declaredFields.addAll(Arrays.asList(superclassDescriptor.getDeclaredFieldDescriptors())); + } + + return; + } + throw new CompilerException("Internal error: null node parsing Java file from " + src); + } catch (ParseException e) { + throw new CompilerException("Error parsing Java source code " + className + ": " + e.getMessage()); + } + } + + private void scanCompilationUnit(SimpleNode node) { + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + scanCompilationUnitChild(child); + } + } + + private void scanCompilationUnitChild(SimpleNode child) { + if (firstTypeScanned) { + + // already scan the first class of the java file + // for the moment, can not do anything else... + if (log.isWarnEnabled()) { + log.warn("There is more than one type in current file, skip next type..."); + } + return; + } + int nodeType = child.getId(); + switch (nodeType) { + case JavaParserTreeConstants.JJTPACKAGEDECLARATION: + packageName = child.getChild(1).getText().trim(); + compiler.addImport(packageName + ".*"); + + // add implicit java.lnag namespace available + compiler.addImport("java.lang.*"); + break; + case JavaParserTreeConstants.JJTIMPORTDECLARATION: + String text = child.getText().trim(); + if (text.startsWith("import")) { + text = text.substring("import".length()).trim(); + } + if (text.endsWith(";")) { + text = text.substring(0, text.length() - 1); + } + if (log.isDebugEnabled()) { + log.debug("import " + text); + } + compiler.addImport(text); + break; + case JavaParserTreeConstants.JJTTYPEDECLARATION: + scanCompilationUnit(child); + break; + + case JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION: + isInterface = child.firstToken.image.equals("interface"); + scanClass(child); + break; + case JavaParserTreeConstants.JJTENUMDECLARATION: + isEnum = child.firstToken.image.equals("enum"); + scanClass(child); + break; + } + } + + // scans the main ClassOrInterfaceDeclaration + + private void scanClass(SimpleNode node) { + firstTypeScanned = true; +// boolean isInterface = node.firstToken.image.equals("interface"); + className = node.firstToken.next.image; + if (packageName != null) { + className = packageName + "." + className; + } + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + int nodeType = child.getId(); + + if (nodeType == JavaParserTreeConstants.JJTIMPLEMENTSLIST) { + + if (log.isDebugEnabled()) { + log.debug("[" + className + "] Found a implements list " + child + " :: " + child.jjtGetNumChildren()); + } + + // obtain interfaces + for (int j = 0; j < child.jjtGetNumChildren(); j++) { + String rawName = child.getChild(j).getText().trim(); + + addInterface(rawName); + } + continue; + } + if (nodeType == JavaParserTreeConstants.JJTEXTENDSLIST) { + + if (isInterface) { + + // obtain interfaces + for (int j = 0; j < child.jjtGetNumChildren(); j++) { + String rawName = child.getChild(j).getText().trim(); + + addInterface(rawName); + } + continue; + } + + // this is an extends + assert child.jjtGetNumChildren() == 1 : "expected ExtendsList to have exactly one child for a non-interface class"; + String rawName = child.getChild(0).getText().trim(); + superclass = TagManager.resolveClassName(rawName, compiler); + if (superclass == null) { + throw new CompilerException("Could not find class: " + rawName); + } + if (log.isDebugEnabled()) { + log.debug("Set superClass = " + superclass); + } + } else if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEBODY) { + scanClassNode(child); + } + } + } + + // scans class body nodes + + private void scanClassNode(SimpleNode node) { + int nodeType = node.getId(); + + switch (nodeType) { + case JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION: + + // TODO: handle inner classes + break; + + case JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION: + + scanConstructorDeclaration(node); + break; + + case JavaParserTreeConstants.JJTMETHODDECLARATION: + + scanMethodDeclaration(node); + break; + + case JavaParserTreeConstants.JJTFIELDDECLARATION: + + scanFieldDeclaration(node); + break; + + default: + + // go throught it + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + scanClassNode(child); + } + } + } + + + protected void scanFieldDeclaration(SimpleNode node) { + String text = node.getText(); + String declaration = text; + String value = null; + int equals = text.indexOf("="); + if (equals != -1) { + value = declaration.substring(equals + 1).trim(); + declaration = declaration.substring(0, equals); + } + declaration = declaration.trim(); + + // get modifiers of the field + + int modifiers; + if (isInterface) { + modifiers = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; + } else { + modifiers = getModifiers(node); + } + + if (log.isDebugEnabled()) { + log.debug("field [" + declaration + "] modifiers == " + + Modifier.toString(modifiers)); + } + + String[] declarationTokens = declaration.split("\\s"); + String name = declarationTokens[declarationTokens.length - 1]; + if (name.endsWith(";")) { + name = name.substring(0, name.length() - 1).trim(); + } + String cName = declarationTokens[declarationTokens.length - 2]; + String type = TagManager.resolveClassName(cName, compiler); + + FieldDescriptor descriptor = new FieldDescriptor( + name, + modifiers, + type, + compiler.getClassLoader() + ); + + if ("$jaxxObjectDescriptor".equals(name) && value != null) { + + // we are in a jaxx object, save the value of the field + + // value have this form : = "XXX";, we just want the XXX part + int firstIndex = value.indexOf("\""); + int lastIndex = value.lastIndexOf("\""); + + jaxxObjectDescriptorValue = + value.substring(firstIndex + 1, lastIndex); + + if (log.isDebugEnabled()) { + log.debug("detected a $jaxxObjectDescriptor = " + + jaxxObjectDescriptorValue); + } + } + + if (Modifier.isPublic(modifiers)) { + + fields.add(descriptor); + } else { + + declaredFields.add(descriptor); + } + } + + protected void scanConstructorDeclaration(SimpleNode node) { + String name = null; + List<String> parameterTypes = new ArrayList<String>(); + //List<String> parameterNames = new ArrayList<String>(); + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + int type = child.getId(); + + if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { + name = child.firstToken.image.trim(); + SimpleNode formalParameters = child.getChild(0); + assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; + for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { + SimpleNode parameter = formalParameters.getChild(j); + String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); + String parameterType = TagManager.resolveClassName(rawParameterType, compiler); + if (parameterType == null && JAXXCompiler.STRICT_CHECKS) { + throw new CompilerException("could not find class '" + rawParameterType + "'"); + } + parameterTypes.add(parameterType); + //parameterNames.add(parameter.getChild(2).getText().trim()); + } + } + } + + // determine the actual modifiers + + int modifiers = getModifiers(node); + + if (isInterface) { + + modifiers = Modifier.PUBLIC; + } + if (log.isDebugEnabled()) { + log.debug("method [" + name + "] modifiers == " + Modifier.toString(modifiers)); + } + + MethodDescriptor methodDescriptor = new MethodDescriptor( + name, + modifiers, + null, + parameterTypes.toArray(new String[parameterTypes.size()]), + compiler.getClassLoader() + ); + + constructors.add(methodDescriptor); + + } + + protected void scanMethodDeclaration(SimpleNode node) { + String returnType = null; + String name = null; + List<String> parameterTypes = new ArrayList<String>(); + //List<String> parameterNames = new ArrayList<String>(); + for (int i = 0; i < node.jjtGetNumChildren(); i++) { + SimpleNode child = node.getChild(i); + int type = child.getId(); + if (type == JavaParserTreeConstants.JJTRESULTTYPE) { +// returnType = TagManager.resolveClassName(child.getText().trim(), compiler); + //tchemit 2011-04-21 Remove anything before return type (like javadoc and other comments) + returnType = TagManager.resolveClassName(child.firstToken.image.trim(), compiler); + } else if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { + name = child.firstToken.image.trim(); + SimpleNode formalParameters = child.getChild(0); + assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; + for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { + SimpleNode parameter = formalParameters.getChild(j); + String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); + String parameterType = TagManager.resolveClassName(rawParameterType, compiler); + if (parameterType == null && JAXXCompiler.STRICT_CHECKS) { + throw new CompilerException("could not find class '" + rawParameterType + "'"); + } + parameterTypes.add(parameterType); + //parameterNames.add(parameter.getChild(2).getText().trim()); + } + } + } + + // determine the actual modifiers + + int modifiers = getModifiers(node); + + if (isInterface) { + + modifiers = Modifier.PUBLIC; + } + if (log.isDebugEnabled()) { + log.debug("method [" + name + "] modifiers == " + Modifier.toString(modifiers)); + } + + MethodDescriptor methodDescriptor = new MethodDescriptor( + name, + modifiers, + returnType, + parameterTypes.toArray(new String[parameterTypes.size()]), + compiler.getClassLoader() + ); + + if (Modifier.isPublic(modifiers)) { + + methods.add(methodDescriptor); + } else { + + //TODO At the moment, do not deal with it... +// declaredMethods.add(methodDescriptor); + } + } + + protected void addInterface(String rawName) { + if (rawName.contains("<")) { + + // generic type + rawName = rawName.substring(0, rawName.indexOf("<")); + } + if (log.isDebugEnabled()) { + log.debug("[" + className + "] try to obtain type of interface " + rawName); + } + + String myInterface = resolveFullyQualifiedName(rawName); + if (myInterface == null) { + throw new CompilerException("Could not find interface: " + myInterface); + } + if (!interfaces.contains(myInterface)) { + if (log.isDebugEnabled()) { + log.debug("[" + className + "] add interface " + myInterface); + } + interfaces.add(myInterface); + } + } + + protected String resolveFullyQualifiedName(String rawName) { + String result; + + String realRawName = null; + String realParentRawName = null; + if (rawName.contains(".")) { + // this is a inner class + int index = rawName.lastIndexOf("."); + realParentRawName = rawName.substring(0, index); + realRawName = rawName.substring(index + 1); + + if (log.isDebugEnabled()) { + log.debug("inner class detected ? " + realParentRawName + "//" + realRawName); + } + } + + if (log.isDebugEnabled()) { + log.debug("try fqn = " + rawName); + } + result = TagManager.resolveClassName(rawName, compiler); + + if (result != null) { + // interface is detected fine (fqn was used or in good package ?) + return result; + } + + String suffix = "." + rawName; + + if (realParentRawName != null) { + suffix = "." + realParentRawName; + } + + for (String aClass : compiler.getImportedClasses()) { + + if (aClass.endsWith(suffix)) { + + // found the class as an already knwon class + + if (realRawName != null) { + aClass += "." + realRawName; + } + + return aClass; + } + } + + // try on packages + + Set<String> importedPackages = compiler.getImportedPackages(); + + for (String aClass : importedPackages) { + String fqn = aClass + rawName; + + if (log.isDebugEnabled()) { + log.debug("try fqn = " + fqn); + } + result = TagManager.resolveClassName(fqn, compiler); + if (result != null) { + return result; + } + } + + // nothing was found + return null; + } + + protected int getModifiers(SimpleNode node) { + SimpleNode parentNode = node.getParent(); + for (int i = 0; i < parentNode.jjtGetNumChildren(); i++) { + SimpleNode child = parentNode.getChild(i); + if (child.getId() == JavaParserTreeConstants.JJTMODIFIERS) { + String modifiersStr = child.getText().trim(); + int modifiers = scanModifiers(modifiersStr); + return modifiers; + } + } + return 0; + } + + protected int scanModifiers(String modifiersStr) { + int modifiers = 0; + if (modifiersStr.contains("public")) { + modifiers |= Modifier.PUBLIC; + } + if (modifiersStr.contains("protected")) { + modifiers |= Modifier.PROTECTED; + } + if (modifiersStr.contains("private")) { + modifiers |= Modifier.PRIVATE; + } + if (modifiersStr.contains("static")) { + modifiers |= Modifier.STATIC; + } + if (modifiersStr.contains("final")) { + modifiers |= Modifier.FINAL; + } + if (modifiersStr.contains("volatile")) { + modifiers |= Modifier.VOLATILE; + } + if (modifiersStr.contains("transient")) { + modifiers |= Modifier.TRANSIENT; + } + if (modifiersStr.contains("synchronized")) { + modifiers |= Modifier.SYNCHRONIZED; + } + if (modifiersStr.contains("abstract")) { + modifiers |= Modifier.ABSTRACT; + } + return modifiers; + } + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java new file mode 100644 index 0000000..9a11720 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJaxxFile.java @@ -0,0 +1,202 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect.resolvers; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXEngine; +import jaxx.compiler.JAXXFactory; +import jaxx.compiler.SymbolTable; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.ClassDescriptorResolver; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Modifier; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * To obtain a class descriptor from a java source file. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJaxxFile extends ClassDescriptorResolver { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJaxxFile.class); + + public ClassDescriptorResolverFromJaxxFile() { + super(ClassDescriptorHelper.ResolverType.JAXX_FILE); + } + + @Override + public ClassDescriptor resolvDescriptor(String className, URL source) throws ClassNotFoundException { + + JAXXEngine engine = JAXXFactory.getEngine(); + + JAXXCompiler compiler = engine.getJAXXCompiler(className); + + SymbolTable symbolTable = compiler.getSymbolTable(); + + if (symbolTable == null) { + throw new CompilerException("Internal error: no symbol table was generated for class '" + className + "'"); + } + + if (log.isDebugEnabled()) { + log.debug("for compiler " + compiler.getOutputClassName()); + } + + ClassLoader classLoader = getClassLoader(); + + ClassDescriptor superclass = + ClassDescriptorHelper.getClassDescriptor( + symbolTable.getSuperclassName(), classLoader); + // tchemit 2011-02-18 Be ware!!! + // this is nearly impossible to obtain consturctors from symbol table. + // let says for the moment this data is not available here and must be found in other places... + // Anyway, the only reason of finding constructor is when we want to generate a jaxx file + // If it inheritate from another jaxx file, we will mkae sure order is ok for this... + + List<MethodDescriptor> constructors = new ArrayList<MethodDescriptor>(); + 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(); + } + } + Set<String> interfaces = new HashSet<String>(); + if (symbolTable.getInterfaces() != null) { + // having interfaces + for (String anInterface : symbolTable.getInterfaces()) { + int genericIndex = anInterface.indexOf("<"); + if (genericIndex > -1) { + // remove generic type + anInterface = anInterface.substring(0, genericIndex); + } + if (log.isDebugEnabled()) { + log.debug("getting interface " + anInterface + " descriptor for class " + className); + } + interfaces.add(anInterface); + ClassDescriptor interfaceclass = ClassDescriptorHelper.getClassDescriptor(anInterface, classLoader); + publicMethods.addAll(Arrays.asList(interfaceclass.getMethodDescriptors())); + publicFields.addAll(Arrays.asList(interfaceclass.getFieldDescriptors())); + } + } + 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; + + ClassDescriptor[] superclassInterfaces = superclass.getInterfaces(); + for (ClassDescriptor superclassInterface : superclassInterfaces) { + interfaces.add(superclassInterface.getName()); + } + interfaces.add(JAXXObject.class.getName()); + return new JaxxFileClassDescriptor( + compiler, + className, + packageName, + interfaces, + classLoader, + constructors.toArray(new MethodDescriptor[constructors.size()]), + publicMethods.toArray(new MethodDescriptor[publicMethods.size()]), + publicFields.toArray(new FieldDescriptor[publicFields.size()]) + ); + } + + private class JaxxFileClassDescriptor extends ClassDescriptor { + + private final JAXXCompiler compiler; + + public JaxxFileClassDescriptor(JAXXCompiler compiler, + String className, + String packageName, + Set<String> interfaces, + ClassLoader classLoader, + MethodDescriptor[] constructors, + MethodDescriptor[] publicMethods, + FieldDescriptor[] publicFields) { + super(ClassDescriptorResolverFromJaxxFile.this.getResolverType(), + className, + packageName, + compiler.getSymbolTable().getSuperclassName(), + interfaces.toArray(new String[interfaces.size()]), + false, + false, + null, + null, + classLoader, + constructors, + publicMethods, + publicFields + ); + this.compiler = compiler; + } + + @Override + public FieldDescriptor getDeclaredFieldDescriptor(String name) throws NoSuchFieldException { + String type = compiler.getSymbolTable().getClassTagIds().get(name); + if (type != null) { + return new FieldDescriptor(name, Modifier.PROTECTED, type, compiler.getClassLoader()); + } + throw new NoSuchFieldException(name); + } + + @Override + public MethodDescriptor getDeclaredMethodDescriptor(String name, ClassDescriptor... parameterTypes) throws NoSuchMethodException { + throw new NoSuchMethodException(name); + } + + @Override + public JAXXObjectDescriptor getJAXXObjectDescriptor() { + return compiler.getJAXXObjectDescriptor(); + } + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptInitializer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptInitializer.java new file mode 100644 index 0000000..1ef33b5 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptInitializer.java @@ -0,0 +1,45 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.script; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptorHelper; + +/** + * A dummy CompiledObject which serves to initialize scripted field. This is handled by + * a CompiledObject rather than (say) simply inlining the initialization code in order to + * ensure that the field is initialized in document order. + */ +public class ScriptInitializer extends CompiledObject { + + public ScriptInitializer(String initializer, JAXXCompiler compiler) { +// super(compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(ScriptInitializer.class)), + super(compiler.getAutoId(ScriptInitializer.class.getSimpleName()), + ClassDescriptorHelper.getClassDescriptor(ScriptInitializer.class), compiler, false); + appendInitializationCode(initializer); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptManager.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptManager.java new file mode 100644 index 0000000..04dccb6 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/script/ScriptManager.java @@ -0,0 +1,485 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.script; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.java.JavaArgument; +import jaxx.compiler.java.JavaConstructor; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.parser.JavaParser; +import jaxx.compiler.java.parser.JavaParserTreeConstants; +import jaxx.compiler.java.parser.SimpleNode; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.tags.TagManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.StringReader; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ScriptManager { + + private JAXXCompiler compiler; + + public ScriptManager(JAXXCompiler compiler) { + this.compiler = compiler; + } + + /** + * Strips unnecessary curly braces from around the script, generating a warning if they are found. + * + * @param script script to trim + * @return the trimed script + */ + public String trimScript(String script) { + script = script.trim(); + if (script.startsWith("{") && script.endsWith("}")) { + compiler.reportWarning("curly braces are unnecessary for script '" + script + "'"); + script = script.substring(1, script.length() - 1); + } + return script; + } + + public void checkParse(String script) throws CompilerException { + script = trimScript(script); + JavaParser p = new JavaParser(new StringReader(script)); + while (!p.Line()) { + // ??? + } + } + + public String preprocessScript(String script) throws CompilerException { + script = trimScript(script); + StringBuilder result = new StringBuilder(); + JavaParser p = new JavaParser(new StringReader(script)); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + preprocessScriptNode(node, false); + result.append(node.getText()); + } + } + return result.toString(); + } + + /** + * Scans through a compound symbol (foo.bar.baz) to identify and compile + * the JAXX class it refers to, if any. + * + * @param symbol symbol to scan + */ + private void scanCompoundSymbol(String symbol) { + String[] tokens = symbol.split("\\."); + StringBuilder currentSymbol = new StringBuilder(); + for (String token : tokens) { + if (currentSymbol.length() > 0) { + currentSymbol.append('.'); + } + currentSymbol.append(token.trim()); + + String contextClass = TagManager.resolveClassName( + currentSymbol.toString(), compiler); + if (contextClass != null) { + compiler.addDependencyClass(contextClass); + } + } + } + + private void preprocessScriptNode(SimpleNode node, + boolean staticContext) throws CompilerException { + // identify static methods and initializers -- we can't fire events statically + if (node.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION) { + if (node.getParent().getChild(0).getText().contains("static")) { + staticContext = true; + } + } else if (node.getId() == JavaParserTreeConstants.JJTINITIALIZER) { + if (node.getText().trim().startsWith("static")) { + staticContext = true; + } + } + + int count = node.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + preprocessScriptNode(node.getChild(i), staticContext); + } + + int id = node.getId(); + if (id == JavaParserTreeConstants.JJTNAME || + id == JavaParserTreeConstants.JJTCLASSORINTERFACETYPE) { + scanCompoundSymbol(node.getText()); + } + //tchemit 2011-02-02 I never understand this code + //Doing at each assignment a ifre with a called "dummy value" is a none sense + // Since JAXX can handle pretty well with javaBeans I remove this code +// if (!staticContext) { +// String lhs = null; +// if (id == JavaParserTreeConstants.JJTASSIGNMENTEXPRESSION || +// id == JavaParserTreeConstants.JJTPOSTFIXEXPRESSION && node.jjtGetNumChildren() == 2) { +// lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); +// } else if (id == JavaParserTreeConstants.JJTPREINCREMENTEXPRESSION || +// id == JavaParserTreeConstants.JJTPREDECREMENTEXPRESSION) { +// lhs = ((SimpleNode) node.jjtGetChild(0)).getText().trim(); +// } +// if (lhs != null) { +// FieldDescriptor[] fields = compiler.getScriptFields(); +// for (FieldDescriptor field : fields) { +// if (field.getName().equals(lhs)) { +// //lhs.substring(lhs.lastIndexOf(".") + 1); +// String prefix = compiler.getImportedType(JAXXUtil.class); +// node.firstToken.image = prefix + ".assignment(" + node.firstToken.image; +// String outputClassName = compiler.getImportedType(compiler.getOutputClassName()); +// node.lastToken.image = node.lastToken.image + ", \"" + lhs + "\", " + outputClassName + ".this)"; +// } +// } +// } +// } + } + + /** + * Examines a Line to determine its real type. As all tokens returned by the parser are Lines, and + * they are just a tiny wrapper around the real node, this method strips off the wrapper layers to identify + * the real type of a node. + * + * @param line line to scan + * @return the line type + */ + private int getLineType(SimpleNode line) { + if (line.jjtGetNumChildren() == 1) { + SimpleNode node = line.getChild(0); + if (node.getId() == JavaParserTreeConstants.JJTBLOCKSTATEMENT) { + if (node.jjtGetNumChildren() == 1) { + return node.getChild(0).getId(); + } + } else if (node.getId() == JavaParserTreeConstants.JJTCLASSORINTERFACEBODYDECLARATION) { + int id = node.getChild(0).getId(); + if (id == JavaParserTreeConstants.JJTMODIFIERS) { + return node.getChild(1).getId(); + } + if (id == JavaParserTreeConstants.JJTINITIALIZER) { + return id; + } + } + return node.getId(); + } + return JavaParserTreeConstants.JJTLINE; // generic value implying that it's okay to put into the initializer block + } + + private SimpleNode findExplicitConstructorInvocation(SimpleNode parent) { + if (parent.getId() == JavaParserTreeConstants.JJTEXPLICITCONSTRUCTORINVOCATION) { + return parent; + } + + int count = parent.jjtGetNumChildren(); + for (int i = 0; i < count; i++) { + SimpleNode result = findExplicitConstructorInvocation(parent.getChild(i)); + if (result != null) { + return result; + } + } + return null; + } + + private void processConstructor(String modifiers, SimpleNode node) { + assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; + assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; + String code = ""; + if (node.getChild(0).jjtGetNumChildren() == 0) { + compiler.reportError("The default no-argument constructor may not be redefined"); + } else { + SimpleNode explicitConstructorInvocation = findExplicitConstructorInvocation(node); + if (explicitConstructorInvocation == null || explicitConstructorInvocation.getText().trim().startsWith("super(")) { + code = "$initialize();" + JAXXCompiler.getLineSeparator(); + if (explicitConstructorInvocation == null) { + node.getChild(1).firstToken.image = node.getChild(1).firstToken.image; + } else { + explicitConstructorInvocation.lastToken.image += code; + } + } + } + + compiler.appendBodyCode(modifiers + " " + node.getText().substring(0, node.getText().length() - 1) + code + "}"); + } + + private void processConstructor(SimpleNode mainNode) { + + compiler.registerInitializer(new RegisterConstructor(mainNode)); + } + + + /** Logger */ + static private final Log log = LogFactory.getLog(ScriptManager.class); + + private void scanScriptNode(SimpleNode node) throws CompilerException { + int nodeType = getLineType(node); + if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { + // have to handle imports early so the preprocessing takes them into account + String text = node.getChild(0).getText().trim(); + if (text.startsWith("import")) { + text = text.substring("import".length()).trim(); + } + if (text.endsWith(";")) { + text = text.substring(0, text.length() - 1); + } + compiler.addImport(text); + } + + preprocessScriptNode(node, false); + + if (nodeType == JavaParserTreeConstants.JJTIMPORTDECLARATION) { + // do nothing, already handled above + } else if (nodeType == JavaParserTreeConstants.JJTMETHODDECLARATION) { + String returnType = null; + String name = null; + List<String> parameterTypes = new ArrayList<String>(); + //List<String> parameterNames = new ArrayList<String>(); + SimpleNode methodDeclaration = node.getChild(0).getChild(1); + assert methodDeclaration.getId() == JavaParserTreeConstants.JJTMETHODDECLARATION; + for (int i = 0; i < methodDeclaration.jjtGetNumChildren(); i++) { + SimpleNode child = methodDeclaration.getChild(i); + int type = child.getId(); + if (type == JavaParserTreeConstants.JJTRESULTTYPE) { + String rawReturnType = child.getText().trim(); + returnType = TagManager.resolveClassName(rawReturnType, compiler); + // FIXME: this check fails for inner classes defined in this file + //if (returnType == null) + // throw new CompilerException("could not find class '" + rawReturnType + "'"); + } else if (type == JavaParserTreeConstants.JJTMETHODDECLARATOR) { + name = child.firstToken.image.trim(); + SimpleNode formalParameters = child.getChild(0); + assert formalParameters.getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS; + for (int j = 0; j < formalParameters.jjtGetNumChildren(); j++) { + SimpleNode parameter = formalParameters.getChild(j); + String rawParameterType = parameter.getChild(1).getText().trim().replaceAll("\\.\\.\\.", "[]"); + String parameterType = TagManager.resolveClassName(rawParameterType, compiler); + // FIXME: this check fails for inner classes defined in this file + //if (parameterType == null) + // throw new CompilerException("could not find class '" + rawParameterType + "'"); + parameterTypes.add(parameterType); + //parameterNames.add(parameter.getChild(2).getText().trim()); + } + } + } + compiler.appendBodyCode(node.getText()); + compiler.addScriptMethod(new MethodDescriptor(name, Modifier.PUBLIC, returnType, parameterTypes.toArray(new String[parameterTypes.size()]), compiler.getClassLoader())); + } else if (nodeType == JavaParserTreeConstants.JJTCLASSORINTERFACEDECLARATION || + nodeType == JavaParserTreeConstants.JJTINITIALIZER) { + String str = node.getText().trim(); + if (str.endsWith(";")) { + str += ";"; + } + compiler.appendBodyCode(str); + } else if (nodeType == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION) { + processConstructor(node); +// processConstructor(node.getChild(0).getChild(0).getText(), node.getChild(0).getChild(1)); + } else if (nodeType == JavaParserTreeConstants.JJTLOCALVARIABLEDECLARATION || nodeType == JavaParserTreeConstants.JJTFIELDDECLARATION) { + // the "local" variable declarations in this expression aren't actually local -- they are flagged local + // just because there isn't an enclosing class scope visible to the parser. "Real" local variable + // declarations won't show up here, because they will be buried inside of methods. + String text = node.getText().trim(); + if (!text.endsWith(";")) { + text += ";"; + } + String declaration = text; + int equals = text.indexOf("="); + if (equals != -1) { + declaration = declaration.substring(0, equals); + } + declaration = declaration.trim(); + if (declaration.contains("<")) { + + // generic declaration detected + + if (log.isDebugEnabled()) { + log.debug("Found a declaration with generics : " + declaration); + } + + int last = declaration.lastIndexOf('>'); + + // copy everything before first '<' + String newDeclaration = declaration.substring(0, declaration.indexOf('<')); + if (last < declaration.length()) { + + // copy everithing after last '>' + newDeclaration += declaration.substring(last + 1); + } + + if (log.isDebugEnabled()) { + log.debug("==> declaration without generics : " + newDeclaration); + } + declaration = newDeclaration; + } + + String[] declarationTokens = declaration.split("\\s"); + boolean isFinal = Arrays.asList(declarationTokens).contains("final"); + boolean isStatic = Arrays.asList(declarationTokens).contains("static"); + String name = declarationTokens[declarationTokens.length - 1]; + if (name.endsWith(";")) { + name = name.substring(0, name.length() - 1).trim(); + } + String className = declarationTokens[declarationTokens.length - 2]; + if (log.isDebugEnabled()) { + log.debug("Found type : " + className + " : " + + Arrays.toString(declarationTokens)); + } + String type = TagManager.resolveClassName(className, compiler); + if (type == null) { + + throw new CompilerException( + "Could not find type of " + className + + " for expression " + text); + } + compiler.addScriptField(new FieldDescriptor(name, + Modifier.PUBLIC, + type, + compiler.getClassLoader()) + ); + // TODO: determine the actual modifiers + if (equals != -1 && !isFinal && !isStatic) { + + // declare the field in the class body, but wait to actually initialize it + compiler.appendBodyCode(text.substring(0, equals).trim() + ";"); + String initializer = text.substring(equals + 1).trim(); + if (type.endsWith("[]")) { + initializer = "new " + type + " " + initializer; + } + final String finalInitializer = name + " = " + initializer; + compiler.registerInitializer(new Runnable() { + + @Override + public void run() { + compiler.registerCompiledObject(new ScriptInitializer( + finalInitializer, compiler)); + } + }); + } else { + compiler.appendBodyCode(text); + } + compiler.appendBodyCode("\n"); + } else { + String text = node.getText().trim(); + if (text.length() > 0) { + if (!text.endsWith(";")) { + text += ";"; + } + compiler.appendInitializerCode(text); + } + } + } + + public void registerScript(String script) throws CompilerException { + JavaParser p = new JavaParser(new StringReader(script)); + while (!p.Line()) { + SimpleNode node = p.popNode(); + if (node != null) { + scanScriptNode(node); + } + } + } + + class RegisterConstructor implements Runnable { + + final SimpleNode mainNode; + + public RegisterConstructor(SimpleNode mainNode) { + this.mainNode = mainNode; + } + + @Override + public void run() { + + String className = mainNode.getChild(0).getChild(1).firstToken.image; + String modifiers = mainNode.getChild(0).getChild(0).getText(); + + SimpleNode node = mainNode.getChild(0).getChild(1); + int nbArguments = node.getChild(0).jjtGetNumChildren(); + if (log.isDebugEnabled()) { + log.debug("Constructor found with " + nbArguments + " arguments : " + node.getText()); + } + assert node.getId() == JavaParserTreeConstants.JJTCONSTRUCTORDECLARATION : "expected node to be ConstructorDeclaration, found " + JavaParserTreeConstants.jjtNodeName[node.getId()] + " instead"; + assert node.getChild(0).getId() == JavaParserTreeConstants.JJTFORMALPARAMETERS : "expected node 0 to be FormalParameters, found " + JavaParserTreeConstants.jjtNodeName[node.getChild(1).getId()] + " instead"; + SimpleNode params = node.getChild(0); + StringBuilder bodyC = new StringBuilder(); + for (int i = 1; i < node.jjtGetNumChildren(); i++) { + bodyC.append(node.getChild(i).getText()); + } + String bodyContent = bodyC.toString().trim(); + JavaArgument[] arguments = new JavaArgument[nbArguments]; + for (int i = 0; i < nbArguments; i++) { + SimpleNode param = params.getChild(i); + String paramType = param.getChild(0).firstToken.image; + ClassDescriptor type = TagManager.resolveClass(paramType, compiler); + String paramName = param.getChild(2).firstToken.image; + if (log.isDebugEnabled()) { + log.debug("Parameter n°" + i + " --> [" + type + " : " + paramName + "]"); + } + JavaArgument arg = JavaElementFactory.newArgument(type.getName(), paramName); + arguments[i] = arg; + } + String[] modifierSplit = modifiers.trim().split("\\s"); + if (log.isDebugEnabled()) { + log.debug("Modifiers = " + Arrays.toString(modifierSplit)); + } + int finalModifiers = 0; + for (String mod : modifierSplit) { + mod = mod.trim(); + if ("public".equals(mod)) { + finalModifiers = Modifier.PUBLIC; + break; + } + if ("protected".equals(mod)) { + finalModifiers = Modifier.PROTECTED; + break; + } + if ("private".equals(mod)) { + finalModifiers = Modifier.PRIVATE; + break; + } + } + + if (!bodyContent.endsWith("$initialize();")) { + bodyContent += JAXXCompiler.getLineSeparator() + " $initialize();"; + } + if (log.isDebugEnabled()) { + log.debug("Final modifier to use : " + Modifier.toString(finalModifiers)); + log.debug("Constructor body :\n" + bodyContent); + } + JavaConstructor constructorMethod = JavaElementFactory.newConstructor( + finalModifiers, + className, + bodyContent, + arguments + ); + + compiler.getJavaFile().addConstructor(constructorMethod); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/spi/DefaultInitializer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/spi/DefaultInitializer.java new file mode 100644 index 0000000..d68052b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/spi/DefaultInitializer.java @@ -0,0 +1,237 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.spi; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.beans.BeanInfoUtil; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.tags.DefaultObjectHandler; +import jaxx.compiler.tags.ImportHandler; +import jaxx.compiler.tags.ScriptHandler; +import jaxx.compiler.tags.StyleHandler; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.tags.TagManager; +import jaxx.compiler.tags.swing.ApplicationHandler; +import jaxx.compiler.tags.swing.CellHandler; +import jaxx.compiler.tags.swing.ItemHandler; +import jaxx.compiler.tags.swing.JAXXComboBoxHandler; +import jaxx.compiler.tags.swing.JAXXListHandler; +import jaxx.compiler.tags.swing.JAXXTabHandler; +import jaxx.compiler.tags.swing.JAXXTreeHandler; +import jaxx.compiler.tags.swing.JCheckBoxHandler; +import jaxx.compiler.tags.swing.JComboBoxHandler; +import jaxx.compiler.tags.swing.JInternalFrameHandler; +import jaxx.compiler.tags.swing.JListHandler; +import jaxx.compiler.tags.swing.JMenuHandler; +import jaxx.compiler.tags.swing.JPasswordFieldHandler; +import jaxx.compiler.tags.swing.JPopupMenuHandler; +import jaxx.compiler.tags.swing.JProgressBarHandler; +import jaxx.compiler.tags.swing.JRadioButtonHandler; +import jaxx.compiler.tags.swing.JScrollPaneHandler; +import jaxx.compiler.tags.swing.JSliderHandler; +import jaxx.compiler.tags.swing.JSpinnerHandler; +import jaxx.compiler.tags.swing.JSplitPaneHandler; +import jaxx.compiler.tags.swing.JTabbedPaneHandler; +import jaxx.compiler.tags.swing.JTextComponentHandler; +import jaxx.compiler.tags.swing.JToolBarHandler; +import jaxx.compiler.tags.swing.JTreeHandler; +import jaxx.compiler.tags.swing.JWindowHandler; +import jaxx.compiler.tags.swing.JXLayerHandler; +import jaxx.compiler.tags.swing.RowHandler; +import jaxx.compiler.tags.swing.TabHandler; +import jaxx.compiler.tags.swing.TableHandler; +import jaxx.compiler.tags.validator.BeanValidatorHandler; +import jaxx.compiler.tags.validator.ExcludeFieldValidatorHandler; +import jaxx.compiler.tags.validator.FieldValidatorHandler; +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.swing.editor.EnumEditor; +import jaxx.runtime.swing.editor.LocaleEditor; +import jaxx.runtime.validator.swing.SwingValidator; +import org.jdesktop.jxlayer.JXLayer; + +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JEditorPane; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JPasswordField; +import javax.swing.JPopupMenu; +import javax.swing.JProgressBar; +import javax.swing.JRadioButton; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JScrollPane; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.JTextPane; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.JTree; +import javax.swing.JWindow; +import javax.swing.text.JTextComponent; +import java.awt.Component; + +/** + * Initializes support provided from JAXX (java, swing and validation). + * + * @plexus.component role-hint="default" role="jaxx.compiler.spi.Initializer" + */ +public class DefaultInitializer implements Initializer { + + @Override + public void initialize() { + + BeanInfoUtil.addJaxxBeanInfoPath("jaxx.runtime.swing"); + + registerDefaultNamespace("javax.swing.*", + JEditorPane.class, + JFormattedTextField.class, + JPasswordField.class, + JTextArea.class, + JTextField.class, + JTextPane.class + ); + + // + // Register tags + // + + registerTag(JAXXCompiler.JAXX_NAMESPACE, ScriptHandler.TAG_NAME, new ScriptHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, StyleHandler.TAG_NAME, new StyleHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, ImportHandler.TAG_NAME, new ImportHandler()); + + //TC-20091005 why the namespace was on awt ? ButtonGroup is from javax.swing + registerTag("javax.swing.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class))); +// TagManager.registerTag("java.awt.*", "ButtonGroup", new DefaultObjectHandler(ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class))); + + registerTag(JAXXCompiler.JAXX_NAMESPACE, TabHandler.TAG_NAME, new TabHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, RowHandler.TAG_NAME, new RowHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, CellHandler.TAG_NAME, new CellHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, ItemHandler.TAG_NAME, new ItemHandler()); + + + registerTag(JAXXCompiler.JAXX_NAMESPACE, BeanValidatorHandler.TAG, new BeanValidatorHandler(ClassDescriptorHelper.getClassDescriptor(SwingValidator.class))); + registerTag(JAXXCompiler.JAXX_NAMESPACE, FieldValidatorHandler.TAG, new FieldValidatorHandler()); + registerTag(JAXXCompiler.JAXX_NAMESPACE, ExcludeFieldValidatorHandler.TAG, new FieldValidatorHandler()); + + // + // Register beans + // + + registerBean(Object.class, DefaultObjectHandler.class); + registerBean(Component.class, DefaultComponentHandler.class); + + // check boxes + registerBean(JCheckBox.class, JCheckBoxHandler.class); + registerBean(JCheckBoxMenuItem.class, JCheckBoxHandler.class); + + // combo boxes + registerBean(JComboBox.class, JComboBoxHandler.class); + registerBean(EnumEditor.class, JComboBoxHandler.class); + registerBean(LocaleEditor.class, JComboBoxHandler.class); + registerBean(JAXXComboBox.class, JAXXComboBoxHandler.class); + + // radio boxes + registerBean(JRadioButton.class, JRadioButtonHandler.class); + registerBean(JRadioButtonMenuItem.class, JRadioButtonHandler.class); + registerBean(JToggleButton.class, JRadioButtonHandler.class); + + // Lists + registerBean(JList.class, JListHandler.class); + registerBean(JAXXList.class, JAXXListHandler.class); + + // Trees + registerBean(JTree.class, JTreeHandler.class); + registerBean(JAXXTree.class, JAXXTreeHandler.class); + + // Windows + registerBean(JDialog.class, JWindowHandler.class); + registerBean(JFrame.class, JWindowHandler.class); + registerBean(JWindow.class, JWindowHandler.class); + + // JXLayer + registerBean(JXLayer.class, JXLayerHandler.class); + + registerBean(Application.class, ApplicationHandler.class); + + registerBean(JInternalFrame.class, JInternalFrameHandler.class); + registerBean(JMenu.class, JMenuHandler.class); + registerBean(JPasswordField.class, JPasswordFieldHandler.class); + registerBean(JPopupMenu.class, JPopupMenuHandler.class); + registerBean(JProgressBar.class, JProgressBarHandler.class); + registerBean(JScrollPane.class, JScrollPaneHandler.class); + registerBean(JSlider.class, JSliderHandler.class); + registerBean(JSpinner.class, JSpinnerHandler.class); + registerBean(JSplitPane.class, JSplitPaneHandler.class); + registerBean(JTabbedPane.class, JTabbedPaneHandler.class); + registerBean(JTextComponent.class, JTextComponentHandler.class); + registerBean(JToolBar.class, JToolBarHandler.class); + + registerBean(Table.class, TableHandler.class); + registerBean(JAXXTab.class, JAXXTabHandler.class); + + registerBean(SwingValidator.class, BeanValidatorHandler.class); + + } + + protected void registerBean(Class<?> beanClass, + Class<? extends TagHandler> handlerClass) { + ClassDescriptor classDescriptor = + ClassDescriptorHelper.getClassDescriptor(beanClass); + + TagManager.registerBean(classDescriptor, handlerClass); + } + + protected void registerTag(String namespace, + String tagName, + TagHandler handler) { + TagManager.registerTag(namespace, tagName, handler); + } + + protected void registerDefaultNamespace(String namespace, + Class<?>... beanClass) { + + for (Class<?> c : beanClass) { + TagManager.registerDefaultNamespace(c.getSimpleName(), namespace); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/spi/Initializer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/spi/Initializer.java new file mode 100644 index 0000000..88b814b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/spi/Initializer.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.spi; + +import java.util.ServiceLoader; + +/** + * Performs SPI initialization, typically to register new tags, beans and converter. + * <p/> + * <b>Note:</b> To load such Initializer, we use the {@link ServiceLoader} mecanism. + * + * @see DefaultInitializer + */ +public interface Initializer { + + /** + * Performs SPI initialization, typically to register new + * tags, beans and converter. + */ + void initialize(); +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultComponentHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultComponentHandler.java new file mode 100644 index 0000000..1c97866 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultComponentHandler.java @@ -0,0 +1,458 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.I18nHelper; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; + +import javax.swing.BorderFactory; +import javax.swing.border.TitledBorder; +import java.awt.Component; +import java.awt.Container; +import java.awt.Font; +import java.awt.event.ComponentListener; +import java.awt.event.ContainerListener; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.beans.IntrospectionException; +import java.io.IOException; +import java.lang.reflect.Field; + +public class DefaultComponentHandler extends DefaultObjectHandler { + + + public static final String BORDER_ATTRIBUTE = "border"; + + public static final String ACTION_ICON_ATTRIBUTE = "actionIcon"; + + public static final String CONTAINER_DELEGATE_ATTRIBUTE = "containerDelegate"; + + public static final String FONT_FACE_ATTRIBUTE = "font-face"; + + public static final String FONT_SIZE_ATTRIBUTE = "font-size"; + + public static final String FONT_STYLE_ATTRIBUTE = "font-style"; + + public static final String FONT_WEIGHT_ATTRIBUTE = "font-weight"; + + public static final String HEIGHT_ATTRIBUTE = "height"; + + public static final String ICON_ATTRIBUTE = "icon"; + + public static final String ICON_IMAGE_ATTRIBUTE = "iconImage"; + + public static final String NAME_ATTRIBUTE = "name"; + + public static final String WIDTH_ATTRIBUTE = "width"; + + public static final String X_ATTRIBUTE = "x"; + + public static final String Y_ATTRIBUTE = "y"; + + /** Logger */ + protected static final Log log = + LogFactory.getLog(DefaultComponentHandler.class); + + public static final String BORDER_FACTORY_PREFIX = BorderFactory.class.getSimpleName() + "."; + + public static final String TITLED_BORDER_PREFIX = TitledBorder.class.getSimpleName() + "("; + + /** container delegate (if any) */ + private String containerDelegate; + + public DefaultComponentHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, Component.class); + } + + @Override + protected void init() throws IntrospectionException { + if (jaxxBeanInfo == null) { + super.init(); + + containerDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue(CONTAINER_DELEGATE_ATTRIBUTE); + if (containerDelegate == null && ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass().getSuperclass())) { + containerDelegate = ((DefaultComponentHandler) TagManager.getTagHandler(getBeanClass().getSuperclass())).getContainerDelegate(); + } + } + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("hasFocus", FocusListener.class); + addProxyEventInfo("isVisible", ComponentListener.class); + addProxyEventInfo("getBounds", ComponentListener.class); + addProxyEventInfo("getLocation", ComponentListener.class); + addProxyEventInfo("getLocationOnScreen", ComponentListener.class); + addProxyEventInfo("getSize", ComponentListener.class); + addProxyEventInfo("getX", ComponentListener.class); + addProxyEventInfo("getY", ComponentListener.class); + addProxyEventInfo("getWidth", ComponentListener.class); + addProxyEventInfo("getHeight", ComponentListener.class); + if (ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass())) { + addProxyEventInfo("getComponentCount", ContainerListener.class); + } + } + + @Override + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, NAME_ATTRIBUTE, object.getId(), false, compiler); + openComponent(object, tag, compiler); + } + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + super.compileFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + super.compileSecondPass(tag, compiler); + closeComponent(compiler.getOpenComponent(), tag, compiler); + } + + protected void openComponent(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + String constraints = tag.getAttribute(CONSTRAINTS_ATTRIBUTE); + if (constraints != null && constraints.length() > 0) { + compiler.openComponent(object, constraints); + } else { + compiler.openComponent(object); + } + } + + protected void closeComponent(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + compiler.closeComponent(object); + } + + @Override + public boolean isPropertyInherited(String property) throws UnsupportedAttributeException { + return property.equals("font") || property.startsWith("font-") || property.equals("foreground") || property.equals("enabled"); + } + + @Override + public ClassDescriptor getPropertyType(CompiledObject object, + String propertyName, + JAXXCompiler compiler) throws CompilerException { + if (X_ATTRIBUTE.equals(propertyName) || + Y_ATTRIBUTE.equals(propertyName) || + WIDTH_ATTRIBUTE.equals(propertyName) || + HEIGHT_ATTRIBUTE.equals(propertyName) || + FONT_SIZE_ATTRIBUTE.equals(propertyName)) { + return ClassDescriptorHelper.getClassDescriptor(Integer.class); + } + if (FONT_FACE_ATTRIBUTE.equals(propertyName) || + FONT_STYLE_ATTRIBUTE.equals(propertyName) || + FONT_WEIGHT_ATTRIBUTE.equals(propertyName)) { + return ClassDescriptorHelper.getClassDescriptor(String.class); + } + return super.getPropertyType(object, propertyName, compiler); + } + + @Override + public String getGetPropertyCode(String id, + String name, + JAXXCompiler compiler) throws CompilerException { + if (FONT_FACE_ATTRIBUTE.equals(name)) { + return id + ".getFont().getFontName()"; + } + if (FONT_SIZE_ATTRIBUTE.equals(name)) { + return id + ".getFont().getSize()"; + } + if (FONT_WEIGHT_ATTRIBUTE.equals(name)) { + compiler.addImport(Font.class); + return "(" + id + ".getFont().getStyle() & Font.BOLD) != 0 ? \"bold\" : \"normal\""; + } + if (FONT_STYLE_ATTRIBUTE.equals(name)) { + compiler.addImport(Font.class); + return "(" + id + ".getFont().getStyle() & Font.ITALIC) != 0 ? \"italic\" : \"normal\""; + } + return super.getGetPropertyCode(id, name, compiler); + } + + @Override + public String getSetPropertyCode(String id, + String name, + String valueCode, + JAXXCompiler compiler) throws CompilerException { + if (X_ATTRIBUTE.equals(name)) { + return id + ".setLocation(" + valueCode + ", " + id + ".getY());"; + } + if (Y_ATTRIBUTE.equals(name)) { + return id + ".setLocation(" + id + ".getX(), " + valueCode + ");"; + } + if (WIDTH_ATTRIBUTE.equals(name)) { + String type = compiler.getImportedType(SwingUtil.class); +// compiler.setNeedSwingUtil(true); + // need to optimize case when both width and height are being assigned + return type + ".setComponentWidth(" + id + "," + valueCode + ");"; + } + if (HEIGHT_ATTRIBUTE.equals(name)) { +// compiler.setNeedSwingUtil(true); + String type = compiler.getImportedType(SwingUtil.class); + return type + ".setComponentHeight(" + id + "," + valueCode + ");"; + } + if (FONT_FACE_ATTRIBUTE.equals(name)) { + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(new Font(" + valueCode + ", " + id + ".getFont().getStyle(), " + id + ".getFont().getSize()));\n}"; + } + if (FONT_SIZE_ATTRIBUTE.equals(name)) { + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont((float) " + valueCode + "));\n}"; + } + if (FONT_WEIGHT_ATTRIBUTE.equals(name)) { + if (valueCode.equals("\"bold\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | "+type+".BOLD));\n}"; + } + if (valueCode.equals("\"normal\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~"+type+".BOLD));\n}"; + } + if (!valueCode.startsWith("\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n if ((" + valueCode + ").equals(\"bold\")) {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | "+type+".BOLD));\n } else {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~"+type+".BOLD));\n }\n}"; + } + compiler.reportError("font-weight must be either \"normal\" or \"bold\", found " + valueCode); + return ""; + } + if (FONT_STYLE_ATTRIBUTE.equals(name)) { + if (valueCode.equals("\"italic\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | "+type+".ITALIC));\n}"; + } + if (valueCode.equals("\"normal\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n " + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~"+type+".ITALIC));\n}"; + } + if (!valueCode.startsWith("\"")) { + String type = compiler.getImportedType(Font.class); + return "if (" + id + ".getFont() != null) {\n if ((" + valueCode + ").equals(\"italic\")) {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() | "+type+".ITALIC));\n } else {\n " + + id + ".setFont(" + id + ".getFont().deriveFont(" + id + ".getFont().getStyle() & ~"+type+".ITALIC));\n }\n}"; + } + compiler.reportError("font-style must be either \"normal\" or \"italic\", found " + valueCode); + return ""; + } + if (ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()) && name.equals(LAYOUT_ATTRIBUTE)) { + // handle containerDelegate (e.g. contentPane on JFrame) + String cDelegate = (String) getJAXXBeanInfo().getJAXXBeanDescriptor().getValue(CONTAINER_DELEGATE_ATTRIBUTE); + if (cDelegate != null) { + return id + '.' + cDelegate + "().setLayout(" + valueCode + ");"; + } + } + // ajout du support i18n + if (I18nHelper.isI18nableAttribute(name, compiler)) { + valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); + } + + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + + @Override + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) { + + if (propertyName.startsWith("_")) { + // client property + if (stringValue.startsWith("{")) { + stringValue = stringValue.substring(1, stringValue.length() - 1); + } + object.addClientProperty(propertyName.substring(1), stringValue); + //TC-20090327 rather not generating code here + //object.appendAdditionCode(object.getJavaCode() + ".putClientProperty(\"" + propertyName.substring(1) + "\", " + stringValue + ");"); + return; + } + if (BORDER_ATTRIBUTE.equals(propertyName)) { + if (stringValue.contains(BORDER_FACTORY_PREFIX)) { + compiler.addImport(BorderFactory.class); + } else if (stringValue.contains(TITLED_BORDER_PREFIX)) { + compiler.addImport(TitledBorder.class); + } + } + if (ICON_ATTRIBUTE.equals(propertyName)) { + if (!(stringValue.startsWith("{") || stringValue.endsWith("}"))) { + // this is a customized icon, add the icon creation code +// compiler.setNeedSwingUtil(true); + String type = + compiler.getImportedType(SwingUtil.class); + + if (compiler.getConfiguration().isUseUIManagerForIcon()) { + stringValue = "{" + type + ".getUIManagerIcon(\"" + stringValue + "\")}"; + } else { + stringValue = "{" + type + ".createImageIcon(\"" + stringValue + "\")}"; + } + } + } else if (ICON_IMAGE_ATTRIBUTE.equals(propertyName)) { + if (!(stringValue.startsWith("{") || stringValue.endsWith("}"))) { + // this is a customized icon, add the icon creation code +// compiler.setNeedSwingUtil(true); + String type = + compiler.getImportedType(SwingUtil.class); + + if (compiler.getConfiguration().isUseUIManagerForIcon()) { + stringValue = "{" + type + ".getUIManagerIcon(\"" + stringValue + "\").getImage()}"; + } else { + stringValue = "{" + type + ".createImageIcon(\"" + stringValue + "\").getImage()}"; + } + } + } else if (ACTION_ICON_ATTRIBUTE.equals(propertyName)) { + // customized actionIcon property + if (stringValue.startsWith("{") && stringValue.endsWith("}")) { + // there is a script to define the action icon, this is forbidden + compiler.reportError("the actionIcon does not support script, remove braces..., fix the file " + compiler.getOutputClassName()); + return; + } + propertyName = ICON_ATTRIBUTE; +// compiler.setNeedSwingUtil(true); + String type = compiler.getImportedType(SwingUtil.class); + if (compiler.getConfiguration().isUseUIManagerForIcon()) { + stringValue = "{" + type + ".getUIManagerActionIcon(\"" + stringValue + "\")}"; + } else { + stringValue = "{" + type + ".createActionIcon(\"" + stringValue + "\")}"; + } + } + super.setAttribute(object, propertyName, stringValue, inline, compiler); + } + + @Override + protected void scanAttributesForDependencies(Element tag, + JAXXCompiler compiler) { + super.scanAttributesForDependencies(tag, compiler); + // check for clientProperty attributes + //FIXME make this works,... it seems jaxx compiler does not come here ? + //FIXME see the the firstPassHandler in JAXXCompiler ? + NamedNodeMap children = tag.getAttributes(); + for (int i = 0, max = children.getLength(); i < max; i++) { + Attr attr = (Attr) children.item(i); + String name = attr.getName(); + if (!name.startsWith("_")) { + continue; + } + String value = attr.getValue(); + if (value.startsWith("{")) { + compiler.reportWarning(tag, "an clientProperty attribute " + name.substring(1) + " does not required curly value but was : " + value, 0); + } + } + + } + + /** + * Maps string values onto integers, so that int-valued enumeration properties can be specified by strings. For + * example, when passed a key of 'alignment', this method should normally map the values 'left', 'center', and + * 'right' onto SwingConstants.LEFT, SwingConstants.CENTER, and SwingConstants.RIGHT respectively. + * <p/> + * You do not normally need to call this method yourself; it is invoked by {@link #convertFromString} when an + * int-valued property has a value which is not a valid number. By default, this method looks at the + * <code>enumerationValues</code> value of the <code>JAXXPropertyDescriptor</code>. + * + * @param key the name of the int-typed property + * @param value the non-numeric value that was specified for the property + * @throws IllegalArgumentException if the property is an enumeration, but the value is not valid + * @throws NumberFormatException if the property is not an enumeration + */ + @Override + protected int constantValue(String key, String value) { + if (key.equals(MNEMONIC_ATTRIBUTE) || + key.equals(DISPLAYED_MNEMONIC_ATTRIBUTE)) { + if (value.length() == 1) { + return value.charAt(0); + } + try { + Field vk = KeyEvent.class.getField(value); + return (Integer) vk.get(null); + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException("mnemonics must be either a single character or the name of a field in KeyEvent (found: '" + value + "')"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + return super.constantValue(key, value); + } + + /** + * Returns <code>true</code> if this component can contain other components. For children to be + * allowed, the component must be a subclass of <code>Container</code> and its <code>JAXXBeanInfo</code> + * must not have the value <code>false</code> for its <code>isContainer</code> value. + * + * @return <code>true</code> if children are allowed + */ + public boolean isContainer() { + boolean container = ClassDescriptorHelper.getClassDescriptor(Container.class).isAssignableFrom(getBeanClass()); +// if (container) { +// try { +// init(); +// if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { +// container = false; +// } +// } catch (IntrospectionException e) { +// throw new RuntimeException(e); +// } +// } + safeInit(); + if (container) { + if (Boolean.FALSE.equals(getJAXXBeanInfo().getJAXXBeanDescriptor().getValue("isContainer"))) { + container = false; + } + } + return container; + } + + public String getContainerDelegate() { +// try { +// init(); +// return containerDelegate; +// } catch (IntrospectionException e) { +// throw new RuntimeException(e); +// } + safeInit(); + return containerDelegate; + + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java new file mode 100644 index 0000000..ff25f06 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/DefaultObjectHandler.java @@ -0,0 +1,1240 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompiledObjectDecorator; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.beans.JAXXBeanInfo; +import jaxx.compiler.beans.JAXXEventSetDescriptor; +import jaxx.compiler.beans.JAXXIntrospector; +import jaxx.compiler.beans.JAXXPropertyDescriptor; +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.css.StylesheetHelper; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.ComponentDescriptor; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.runtime.css.Stylesheet; +import org.apache.commons.lang3.StringUtils; +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.awt.BorderLayout; +import java.awt.GridLayout; +import java.beans.IntrospectionException; +import java.beans.Introspector; +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 { + + public static final String ABSTRACT_ATTRIBUTE = "abstract"; + + public static final String CONSTRAINTS_ATTRIBUTE = "constraints"; + + public static final String CONSTRUCTOR_PARAMS_ATTRIBUTE = "constructorParams"; + + public static final String DECORATOR_ATTRIBUTE = "decorator"; + + public static final String DISPLAYED_MNEMONIC_ATTRIBUTE = "displayedMnemonic"; + + public static final String DISPLAYED_MNEMONIC_INDEX_ATTRIBUTE = "displayedMnemonicIndex"; + + public static final String GENERICTYPE_ATTRIBUTE = "genericType"; + + public static final String ID_ATTRIBUTE = "id"; + + public static final String IMPLEMENTS_ATTRIBUTE = "implements"; + + public static final String INITIALIZER_ATTRIBUTE = "initializer"; + + public static final String JAVA_BEAN_ATTRIBUTE = "javaBean"; + + public static final String LAYOUT_ATTRIBUTE = "layout"; + + public static final String MNEMONIC_ATTRIBUTE = "mnemonic"; + + public static final String STYLE_CLASS_ATTRIBUTE = "styleClass"; + + public static final String SUPER_GENERIC_TYPE_ATTRIBUTE = "superGenericType"; + + public static final String GRID_LAYOUT_PREFIX = GridLayout.class.getSimpleName() + "("; + + public static final String BORDER_LAYOUT_PREFIX = BorderLayout.class.getSimpleName() + "("; + + /** 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>(); + + public ProxyEventInfo getEventInfo(String memberName) { + return eventInfos != null ? eventInfos.get(memberName) : null; + } + + /** + * 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>. + */ + public static 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; + + public String getAddMethod() { + return addMethod; + } + + public ClassDescriptor getListenerClass() { + return listenerClass; + } + + public String getMemberName() { + return memberName; + } + + public String getModelName() { + return modelName; + } + + public String getRemoveMethod() { + return 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 IntrospectionException if any pb + */ + 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(); + } + } + + /** @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 IntrospectionException if any pb + */ + 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) { + safeInit(); + + JAXXPropertyDescriptor property = properties.get(propertyName); + if (property != null) { + return property.getPropertyType(); + } + throw new UnsupportedAttributeException( + "property '" + propertyName + "' not found in " + object); + } + + /** + * @param name name of the property + * @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 UnsupportedAttributeException if attribute is not supported + */ + public boolean isMemberBound(String name) throws UnsupportedAttributeException { + safeInit(); + + 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()); + } + } + + public static ClassDescriptor getEventClass(ClassDescriptor listenerClass) { + return listenerClass.getMethodDescriptors()[0].getParameterTypes()[0]; + } + + /** + * 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 { + ClassDescriptor classDescriptor = + ClassDescriptorHelper.getClassDescriptor( + listenerClass.getName() + ); + + addProxyEventInfo(memberName, + classDescriptor, + 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); + } + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + scanAttributesForDependencies(tag, compiler); + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + safeInit(); + 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(CONSTRUCTOR_PARAMS_ATTRIBUTE); + if (StringUtils.isNotEmpty(constructorParams)) { + object.setConstructorParams( + compiler.getScriptManager().trimScript(constructorParams)); + } + + setDefaults(object, tag, compiler); + setAttributes(object, tag, compiler); + //TC-20091105, can apply genericType everyWhere, should just test that class is generic (not possible actually) +// if (object.getGenericTypesLength() > 0 && !(object == compiler.getRootObject() || object.isJavaBean())) { +// // can ony be apply to root object or javaBean object +// compiler.reportWarning("'genericType' attribute can only be found on root, or a javaBean object tag but was found on tag " + tag); +// object.setGenericTypes(null); +// return; +// } + compileChildrenSecondPass(tag, compiler); + } + + public void registerCompiledObject(Element tag, JAXXCompiler compiler) { + String id = tag.getAttribute(ID_ATTRIBUTE); + if (id == null || id.length() == 0) { + id = compiler.getAutoId(getBeanClass().getSimpleName()); +// id = compiler.getAutoId(getBeanClass()); + } + CompiledObject object = createCompiledObject(id, compiler); + objectMap.put(tag, object); + String styleClass = tag.getAttribute(STYLE_CLASS_ATTRIBUTE).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 UnsupportedAttributeException if attribute is not supported + */ + 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(JAVA_BEAN_ATTRIBUTE)) { + //compiler.preprocessScript(value); + continue; + } + if (name.equals(CONSTRAINTS_ATTRIBUTE) || + isEventHandlerName(name)) { + // adds dependencies as a side effect + compiler.preprocessScript(value); + } else if (name.equals(CONSTRUCTOR_PARAMS_ATTRIBUTE)) { + //fix bug 178 : if a constructor parameter contains a comma + // the split will not works. + // using this hack will always works :) (but still a hack) + compiler.preprocessScript("java.util.Arrays.toString(" + value + ")"); +// 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_ATTRIBUTE) || + name.equals(CONSTRAINTS_ATTRIBUTE) || + name.equals(CONSTRUCTOR_PARAMS_ATTRIBUTE) || + name.equals(STYLE_CLASS_ATTRIBUTE) || + name.startsWith(XMLNS_ATTRIBUTE) || + JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + // ignore, already handled + continue; + } + if (name.equals(JAVA_BEAN_ATTRIBUTE)) { + object.setJavaBean(true); + if (!value.isEmpty()) { + object.setJavaBeanInitCode(value); + } + continue; + } + if (name.equals(INITIALIZER_ATTRIBUTE)) { + if (!value.isEmpty()) { + object.setInitializer(value); + } else { + object.setInitializer("null"); + } + continue; + } + CompiledObject rootObject = compiler.getRootObject(); + if (name.equals(IMPLEMENTS_ATTRIBUTE)) { + if (object != rootObject) { + // can ony be apply to root object + compiler.reportError("'" + IMPLEMENTS_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); + return; + } + //tchemit 2011-01-29 reuse what was filled in symbols table + String[] interfaces = compiler.getSymbolTable().getInterfaces(); +// String[] interfaces = value.split(","); + compiler.setExtraInterfaces(interfaces); + continue; + } + + if (name.equals(ABSTRACT_ATTRIBUTE)) { + if (object != rootObject) { + // can ony be apply to root object + compiler.reportError("'" + ABSTRACT_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); + return; + } + compiler.setAbstractClass(true); + continue; + } + + if (name.equals(GENERICTYPE_ATTRIBUTE)) { + //TC-20090313 check after all atributes been processed + if (object == rootObject) { + compiler.setGenericType(value); + } else { + object.setGenericTypes(value.split(",")); + if (object.getSimpleType() != null) { + + // reload the simpleType + object.setSimpleType(object.getSimpleType() + "<" + value + ">"); + } + } + continue; + } + + if (name.equals(SUPER_GENERIC_TYPE_ATTRIBUTE)) { + if (object != rootObject) { + // can ony be apply to root object + compiler.reportError("'" + SUPER_GENERIC_TYPE_ATTRIBUTE + "' attribute can only be found on root tag but was found on tag " + tag); + return; + } + compiler.setSuperGenericType(value); + continue; + } + + if (name.equals(DECORATOR_ATTRIBUTE)) { + if (!value.isEmpty()) { + CompiledObjectDecorator decorator = + compiler.getEngine().getDecorator(value); + object.setDecorator(decorator); + } + continue; + } + + if (isEventHandlerName(name)) { + // event handler + if (!value.endsWith(";") && !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>() { + + @Override + 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(DISPLAYED_MNEMONIC_INDEX_ATTRIBUTE) || + attr.getName().equals(DISPLAYED_MNEMONIC_ATTRIBUTE) || + attr.getName().equals(MNEMONIC_ATTRIBUTE)) { + return 1; + } + return 0; + } + + /** + * 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(String, String, Class)}. + * + * @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 { + //--------------------------------------------------------------------- + // BE WARE, Test if removing this code hurts..., anyway we have a bug on it: + // For some component (example : jaxx.runtime.swing.editor.NumberEditor) we do not have one component + // This is disturbing, must find how why... And this happens only on a mvn clean install on all project + // Everything is fine otherwise... + // + // With new binding design, we will know if there is a binding on the property + // of the jaxxObject, and could add it only if required... + //--------------------------------------------------------------------- + //FIXME TC-20091105 we should to this later when all binding are compiled + // because we don't know yet if this is a databinding +// if (ClassDescriptorHelper.getClassDescriptor(JAXXObject.class).isAssignableFrom(object.getObjectClass())) { +// // check for data binding & remove if found +// JAXXObjectDescriptor jaxxObjectDescriptor = object.getObjectClass().getJAXXObjectDescriptor(); +// if (jaxxObjectDescriptor.getComponentDescriptors().length == 0) { +// compiler.reportWarning("JAXXObject component " + object.getObjectClass() + " should have at least one component!"); +//// throw new IllegalStateException("JAXXObject component " + object.getObjectClass() + " should have at least one component!"); +// } else { +// ComponentDescriptor root = jaxxObjectDescriptor.getComponentDescriptors()[0]; +// //TC-20091026 do not prefix binding by object id if on root object +// String prefix; +// if (object == compiler.getRootObject()) { +// prefix = ""; +// } else { +// prefix = object.getJavaCode() + "."; +// } +// object.appendInitializationCode(prefix + "removeDataBinding(" + compiler.getJavaCode(root.getId() + "." + propertyName) + ");"); +// } +// } + object.addProperty(propertyName, stringValue); + ClassDescriptor type = getPropertyType(object, propertyName, compiler); + String binding = DataBindingHelper.processDataBindings(stringValue); + boolean withBinding = binding != null; + + if (inline) { + compiler.addInlineStyle(object, propertyName, withBinding); + } + if (!withBinding) { + // no bindings, convert from string + try { + Class<?> typeClass = type != null ? + ClassDescriptorHelper.getClass(type.getName(), type.getClassLoader()) : + null; + Object value = convertFromString(propertyName, + stringValue, + typeClass + ); + setProperty(object, propertyName, value, compiler); + return; + } 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()); + } + } + String setPropertyCode = getSetPropertyCode(object.getJavaCode(), propertyName, binding, compiler); + if (propertyName.equals(LAYOUT_ATTRIBUTE)) { + + // try to add the layout class in imports + if (setPropertyCode.contains(BORDER_LAYOUT_PREFIX)) { + compiler.addImport(BorderLayout.class); + } else if (setPropertyCode.contains(GRID_LAYOUT_PREFIX)) { + compiler.addImport(GridLayout.class); + } + // handle containerDelegate (e.g. contentPane on JFrame) + // have to set layout early, before children are added + object.appendInitializationCode(setPropertyCode); + } + compiler.getBindingHelper().registerDataBinding( + object.getId() + "." + propertyName, + binding, + setPropertyCode + ); + } 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(CompiledObject object, + JAXXCompiler compiler, + Stylesheet overrides) { + applyStylesheets(object, compiler, overrides, true); + } + + private void applyStylesheets(CompiledObject object, + JAXXCompiler compiler, + Stylesheet overrides, + boolean recurse) { + + Stylesheet stylesheet = compiler.getStylesheet(); + + ClassDescriptor objectClass = object.getObjectClass(); + ClassDescriptor jaxxObjectClassDescriptor = + ClassDescriptorHelper.getClassDescriptor(JAXXObject.class); + + // to apply styleSheet to a jaxx object, + // since 2.0.2, this process can be skip if configuration + // autoRecurseInCss is set to false since this does not work + boolean applyInside = + recurse && + jaxxObjectClassDescriptor.isAssignableFrom(objectClass) && + // new since 2.0.2 to skip old buggy mode + compiler.getConfiguration().isAutoRecurseInCss(); + + try { + + if (!applyInside) { + + // this is the safe mode to use, just apply stlySheet to object + if (stylesheet != null) { + StylesheetHelper.applyTo(object, + compiler, + stylesheet, + overrides + ); + } + return; + } + + //FIXME TC-20100430 This is an old mode which try to apply inside a + // detected jaxx object stysheets (cascade) : + // It does not work in fact and must be repair... + + JAXXObjectDescriptor jaxxObjectDescriptor = + objectClass.getJAXXObjectDescriptor(); + ComponentDescriptor[] descriptors = + jaxxObjectDescriptor.getComponentDescriptors(); + for (ComponentDescriptor descriptor : descriptors) { + ClassDescriptor classDescriptor = + ClassDescriptorHelper.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", ClassDescriptorHelper.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)); + } + } 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 descriptorSet = events.get(name); + if (descriptorSet != null) { + MethodDescriptor[] listenerMethods = + descriptorSet.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, + descriptorSet.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) { + safeInit(); + + 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) { + //TC-20091026 do not prefix by javaCode if on root object + String prefix; + if (compiler.getRootObject().getJavaCode().equals(javaCode)) { + prefix = ""; + } else { + prefix = javaCode + "."; + } + return prefix + 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[] props = + JAXXBeanInfo.getJAXXPropertyDescriptors(); + String lowercaseValue = value.toLowerCase(); + for (JAXXPropertyDescriptor property : props) { + 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]; + } + } + + StringBuilder message = + new StringBuilder("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 || Object.class.equals(type)) { + return value; + } + + try { + return TypeManager.convertFromString(value, type); + } catch (NumberFormatException e) { + if (int.class.equals(type) || Integer.class.equals(type)) { + 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 run + * @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 run + * @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 run + * @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 run + * @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() + "]"; + } + + protected void safeInit() { + try { + init(); + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/ImportHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/ImportHandler.java new file mode 100644 index 0000000..9de5a42 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/ImportHandler.java @@ -0,0 +1,104 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.JAXXCompiler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.StringReader; + +/** + * Handles the <code><import></code> tag. + * + * @author tchemit <chemit@codelutin.com> + * @version $Id$ + * @since 2.1 + */ +public class ImportHandler implements TagHandler { + + /** Logger */ + protected static final Log log = LogFactory.getLog(ImportHandler.class); + + public static final String TAG_NAME = "import"; + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws IOException { + + StringBuilder script = new StringBuilder(); + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.ELEMENT_NODE: + compiler.reportError( + "<import> tag may not contain child elements: " + + tag); + case Node.TEXT_NODE: // fall through + case Node.CDATA_SECTION_NODE: + String txt = ((Text) child).getData(); + if (log.isDebugEnabled()) { + log.debug("Will treate imports :[\n" + txt + "\n]"); + } + String eol = JAXXCompiler.getLineSeparator(); + LineNumberReader reader = new LineNumberReader(new StringReader(txt.trim())); + try { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.isEmpty()) { + continue; + } + script.append("import ").append(line); + if (!line.endsWith(";")) { + script.append(';'); + } + script.append(eol); + } + } finally { + reader.close(); + } + } + } + + String scriptString = script.toString().trim(); + if (!scriptString.isEmpty()) { + compiler.registerScript(script.toString()); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) { + // nothing to do + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/ScriptHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/ScriptHandler.java new file mode 100644 index 0000000..5fb7160 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/ScriptHandler.java @@ -0,0 +1,118 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.File; +import java.io.IOException; + +/** + * Handles the <code><script></code> tag. + * + * @author Ethan Nicholas + */ +public class ScriptHandler implements TagHandler { + + public static final String TAG_NAME = "script"; + + public static final String SOURCE_ATTRIBUTE = "source"; + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + File scriptFile = null; + NamedNodeMap attributes = tag.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attribute = (Attr) attributes.item(i); + String name = attribute.getName(); + String attrValue = attribute.getValue(); + if (name.equals(SOURCE_ATTRIBUTE)) { + String filename = attrValue.replace('/', File.separatorChar); + scriptFile = new File(compiler.getBaseDir(), filename); + String content = compiler.loadFile(scriptFile); + compiler.registerScript(content, scriptFile); +// StringWriter scriptBuffer = new StringWriter(); +// FileReader in = new FileReader(scriptFile); +// try { +// char[] readBuffer = new char[2048]; +// int c; +// while ((c = in.read(readBuffer)) > 0) { +// scriptBuffer.write(readBuffer, 0, c); +// } +// } catch (FileNotFoundException e) { +// compiler.reportError( +// "script file not found: " + scriptFile); +// } finally { +// in.close(); +// } +// compiler.registerScript(scriptBuffer.toString(), scriptFile); + } else if (!name.startsWith(XMLNS_ATTRIBUTE) && + !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals( + attribute.getNamespaceURI())) { + throw new UnsupportedAttributeException(name); + } + } + + StringBuilder script = new StringBuilder(); + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.ELEMENT_NODE: + compiler.reportError( + "<script> tag may not contain child elements: " + + tag); + case Node.TEXT_NODE: // fall through + case Node.CDATA_SECTION_NODE: + script.append(((Text) child).getData()); + } + } + + String scriptString = script.toString().trim(); + if (scriptString.length() > 0) { + if (scriptFile != null) { + compiler.reportError( + "<script> tag has both a source attribute and an " + + "inline script"); + } + compiler.registerScript(script.toString()); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + // nothing to do + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/StyleHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/StyleHandler.java new file mode 100644 index 0000000..9b22c75 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/StyleHandler.java @@ -0,0 +1,120 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.css.StylesheetHelper; +import jaxx.runtime.css.Stylesheet; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.File; +import java.io.IOException; + +/** + * Handles the <code><style></code> tag. + * + * @author Ethan Nicholas + */ +public class StyleHandler implements TagHandler { + + public static final String TAG_NAME = "style"; + + public static final String SOURCE_ATTRIBUTE = "source"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + boolean source = false; + NamedNodeMap attributes = tag.getAttributes(); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attribute = (Attr) attributes.item(i); + String name = attribute.getName(); + String attrValue = attribute.getValue(); + if (name.equals(SOURCE_ATTRIBUTE)) { + source = true; + File styleFile = new File(compiler.getBaseDir(), attrValue.replace('/', File.separatorChar)); + if (!styleFile.exists()) { + compiler.reportError("stylesheet file not found: " + styleFile); + } else { + compiler.registerStyleSheetFile(styleFile); + } +// StringWriter styleBuffer = new StringWriter(); +// FileReader in = new FileReader(styleFile); +// try { +// char[] readBuffer = new char[2048]; +// int c; +// while ((c = in.read(readBuffer)) > 0) { +// styleBuffer.write(readBuffer, 0, c); +// } +// } catch (FileNotFoundException e) { +// compiler.reportError("stylesheet file not found: " + styleFile); +// } finally { +// in.close(); +// } +// compiler.getSourceFiles().push(styleFile); +// compiler.registerStylesheet(StylesheetHelper.processStylesheet(styleBuffer.toString())); +// compiler.getSourceFiles().pop(); + } else if (!name.startsWith(XMLNS_ATTRIBUTE) && + !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + throw new UnsupportedAttributeException(name); + } + } + + StringBuilder style = new StringBuilder(); + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.ELEMENT_NODE: + compiler.reportError("<style> tag may not contain child elements: " + tag); + case Node.TEXT_NODE: // fall through + case Node.CDATA_SECTION_NODE: + style.append(((Text) child).getData()); + } + } + + String styleString = style.toString().trim(); + if (styleString.length() > 0) { + if (source) { + compiler.reportError("<style> tag has both a source attribute and an inline stylesheet"); + } + Stylesheet stylesheet = + StylesheetHelper.processStylesheet(style.toString()); + compiler.registerStylesheet(stylesheet); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + } + +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagHandler.java new file mode 100644 index 0000000..481e6ea --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagHandler.java @@ -0,0 +1,71 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import org.w3c.dom.Element; + +import java.io.IOException; + +/** + * Implementations of <code>TagHandler</code> produce Java source code from XML tags. + * <code>TagHandlers</code> are mapped to particular XML tags (such as <JFrame>) in {@link JAXXCompiler}. + * There is only one <code>TagHandler</code> for any given XML tag, and therefore implementations must be + * stateless. + * + * @author Ethan Nicholas + */ +public interface TagHandler { + + String XMLNS_ATTRIBUTE = "xmlns"; + + /** + * Performs the first pass of compilation on an XML tag from a JAXX source file. + * <code>TagHandler</code> implementations affect the generated <code>.java</code> + * file by calling methods in the <code>JAXXCompiler</code>. + * + * @param tag the XML tag to compile + * @param compiler the active JAXXCompiler + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException; + + /** + * Performs the second pass of compilation on an XML tag from a JAXX source file. + * <code>TagHandler</code> implementations affect the generated <code>.java</code> + * file by calling methods in the <code>JAXXCompiler</code>. + * + * @param tag the XML tag to compile + * @param compiler the active JAXXCompiler + * @throws CompilerException if a compilation error occurs + * @throws IOException if an I/O error occurs + */ + void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException; +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagManager.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagManager.java new file mode 100644 index 0000000..0d5a267 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/TagManager.java @@ -0,0 +1,650 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.ClassMap; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Manages TagHandlers, including automatically compiling .jaxx files + * corresponding to class tags. + */ +public class TagManager { + + /** Logger */ + protected static final Log log = LogFactory.getLog(TagManager.class); + + /** Maps simple tag names to their default namespaces (package names). */ + private static Map<String, String> defaultNamespaces = + new HashMap<String, String>(); + + /** Maps qualified tag names to the TagHandlers responsible for processing them. */ + private static Map<QName, TagHandler> registeredTags = + new HashMap<QName, TagHandler>(); + + /** Keeps track of whether or not named classes exist. */ + private static Map<String, Boolean> classExistenceCache = + new HashMap<String, Boolean>(); + + /** + * Maps bean classes to their TagHandler classes. The mapping is to + * TagHandler classes, rather than to TagHandler instances, + * because subclasses of the bean class should be handled by the same + * TagHandler (assuming no more specific mappings exist), which requires + * creating a new instance of the TagHandler. + */ + private static ClassMap<Class<? extends TagHandler>> registeredBeans = + new ClassMap<Class<? extends TagHandler>>(); + + // still targeting 1.4, so I can't use javax.xml.namespace.QName + + private static class QName { + + private String namespaceURI; + + private String localPart; + + public QName(String namespaceURI, String localPart) { + if (localPart == null) { + throw new NullPointerException(); + } + this.namespaceURI = namespaceURI; + this.localPart = localPart; + } + + public String getNamespaceURI() { + return namespaceURI; + } + + public String getLocalPart() { + return localPart; + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof QName)) { + return false; + } + QName qname = (QName) o; + return qname.getNamespaceURI().equals(getNamespaceURI()) && + qname.getLocalPart().equals(getLocalPart()); + } + + @Override + public int hashCode() { + return (namespaceURI != null ? namespaceURI.hashCode() : 0) ^ + getLocalPart().hashCode(); + } + } + + private TagManager() { /* not instantiable */ } + + public static void reset() { + registeredBeans.clear(); + registeredTags.clear(); + defaultNamespaces.clear(); + } + + /** + * Maps a class tag to a specific <code>TagHandler</code>. + * <p/> + * When a tag representing the bean class is encountered (either the + * class' simple name, if it is unambiguous, or its fully-qualified name), + * the specified <code>TagHandler</code> will be invoked to run it. + * + * @param <T> type of handler + * @param beanClass the class to associate with a <code>TagHandler</code> + * @param handler the <code>TagHandler</code> class, which must descend + * from <code>DefaultObjectHandler</code> + * @throws IllegalArgumentException if the handler class does not descend + * from <code>DefaultObjectHandler</code> + */ + public static <T extends TagHandler> void registerBean(ClassDescriptor beanClass, + Class<T> handler) { + if (!DefaultObjectHandler.class.isAssignableFrom(handler)) { + throw new IllegalArgumentException( + "handler class must be a subclass of DefaultObjectHandler"); + } + registeredBeans.put(beanClass, handler); + if (log.isDebugEnabled()) { + log.debug(beanClass + " : " + handler); + } + String name = beanClass.getName(); + int dotPos = name.lastIndexOf("."); + String namespace = name.substring(0, dotPos + 1) + "*"; + name = name.substring(dotPos + 1); + registerDefaultNamespace(name, namespace); + } + + /** + * Sets the default namespace for a tag. + * <p/> + * When the tag is encountered with no namespace specified, the specified + * namespace will be assumed. Mapping the same tag to two or more default + * namespaces removes the mapping and marks the entry as being ambiguous + * (by putting a <code>null</code> value into the map); this causes an + * error to be thrown if the tag is used without a namespace being specified. + * <p/> + * Java package names on tags are automatically converted into namespaces + * (e.g. <javax.swing.JButton/> and + * <JButton xmlns="javax.swing.*"/> are equivalent), so tags with + * package names are considered to have namespaces specified. + * + * @param tag tag name + * @param namespace namespace + */ + public static void registerDefaultNamespace(String tag, String namespace) { + if (defaultNamespaces.containsKey(tag) && + !defaultNamespaces.get(tag).equals(namespace)) { + defaultNamespaces.put(tag, null); // tag name is now ambiguous + } else { + defaultNamespaces.put(tag, namespace); + } + } + + /** + * Registers a <code>TagHandler</code> for a tag. + * <p/> + * When a tag with the given name and namespace is encountered, the + * <code>TagHandler's compileFirstPass</code> and <code>compileSecondPass</code> + * methods will be invoked to handle it. + * <p/> + * It is not an error to register an already-registered tag and namespace + * combination. The new mapping will replace the old mapping. + * + * @param <T> type of handler + * @param namespace the tag's namespace + * @param tag the simple name of the tag + * @param handler the <code>TagHandler</code> which should process the tag + */ + public static <T extends TagHandler> void registerTag(String namespace, + String tag, + T handler) { + if (namespace == null) { + namespace = "*"; + } + //System.out.println("registerTag "+namespace+" : "+tag+" : "+handler); + if (log.isDebugEnabled()) { + log.debug(tag + " : " + handler); + } + registeredTags.put(new QName(namespace, tag), handler); + registerDefaultNamespace(tag, namespace); + } + + /** + * Returns the <code>TagHandler</code> that should be used to process the + * specified tag. + * <p/> + * If the tag represents the class name of an uncompiled <code>.jaxx</code> + * file, the <code>.jaxx</code> is first compiled. + * + * @param namespace the tag's namespace (may be <code>null</code>) + * @param tag the tag's simple name + * @param compiler the current <code>JAXXCompiler</code> + * @return the <code>TagHandler</code> for the tag + * @throws CompilerException ? + */ + public static TagHandler getTagHandler(String namespace, + String tag, + JAXXCompiler compiler) throws CompilerException { + return getTagHandler(namespace, tag, false, compiler); + } + + private static String getNamespace(ClassDescriptor beanClass) { + String packageName = beanClass.getPackageName(); + return packageName != null ? packageName + ".*" : "*"; + + } + + private static String getSimpleName(ClassDescriptor beanClass) { + String packageName = beanClass.getPackageName(); + if (packageName != null) { + assert beanClass.getName().startsWith(packageName); + return beanClass.getName().substring(packageName.length() + 1); + } + return beanClass.getName(); + } + + /** + * @param klass the java class + * @return the <code>TagHandler</code> that should be used to process the + * specified class. + * Only <code>TagHandlers</code> previously registered with + * <code>registerBean</code> are considered. + * @throws CompilerException ? + */ + public static DefaultObjectHandler getTagHandler(Class<?> klass) throws CompilerException { + + ClassDescriptor beanClass = ClassDescriptorHelper.getClassDescriptor(klass); + DefaultObjectHandler tagHandler = getTagHandler(beanClass); + return tagHandler; + } + + /** + * @param beanClass the tag class + * @return the <code>TagHandler</code> that should be used to process the + * specified class. + * <p/> + * Only <code>TagHandlers</code> previously registered with + * <code>registerBean</code> are considered. + * @throws CompilerException ? + */ + public static DefaultObjectHandler getTagHandler(ClassDescriptor beanClass) throws CompilerException { + try { + if (beanClass == null) { + throw new NullPointerException( + "beanClass parameter can not be null"); + } + if (beanClass.getName() == null) { + throw new NullPointerException( + "beanClass name can not be null : " + beanClass); + } + + String namespace = getNamespace(beanClass); + String tag = getSimpleName(beanClass); + DefaultObjectHandler handler = (DefaultObjectHandler) + registeredTags.get(new QName(namespace, tag)); + if (handler == null) { + Class<? extends TagHandler> handlerClass = + registeredBeans.get(beanClass); + if (handlerClass == null) { + if (beanClass.isInterface()) { + + // if an interface is a tag, avoid big problems... + + return null; + } + throw new CompilerException( + "unable to find handler for " + beanClass); + } + Constructor<? extends TagHandler> constructor = + handlerClass.getConstructor(ClassDescriptor.class); + handler = (DefaultObjectHandler) + constructor.newInstance(beanClass); + registerTag(namespace, tag, handler); + } + return handler; + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + private static boolean classExists(String className, JAXXCompiler compiler) { + if (classExistenceCache.containsKey(className)) { + return classExistenceCache.get(className); + } + + boolean found = false; + ClassLoader classLoader = compiler.getClassLoader(); + try { + Class.forName(className, true, classLoader); + found = true; + } catch (ClassNotFoundException e) { + // ignore ? + } catch (NoClassDefFoundError e) { + // we obtain this instead of ClassNotFoundException on + // case-insensitive file systems when looking up a class with the + // wrong case + } + + if (!found) { + // couldn't find .class, check for .java + URL javaURL = classLoader.getResource(className.replace('.', '/') + ".java"); + found = javaURL != null; + } + + if (!found) { + // couldn't find .java, check for .jaxx + URL jaxxURL = classLoader.getResource(className.replace('.', '/') + ".jaxx"); + found = jaxxURL != null; + } + + classExistenceCache.put(className, found); + + return found; + } + + private static String determinePackage(String simpleClassName, + String defaultPackage, + JAXXCompiler compiler) { + String namespace = null; + Set<String> classes = compiler.getImportedClasses(); + for (String className : classes) { + // search class imports (e.g. import java.util.Date;) + if (className.equals(simpleClassName) || + className.endsWith("." + simpleClassName)) { + namespace = className.substring(0, className.lastIndexOf(".") + 1) + "*"; + } + } + if (namespace == null) { + // search package imports (e.g. import java.util.*;) + Set<String> searchList = compiler.getImportedPackages(); + if (defaultPackage != null) { + if (!defaultPackage.endsWith("*")) { + throw new IllegalArgumentException( + "defaultPackage must end in '*', found '" + + defaultPackage + "'"); + } + String fqn = defaultPackage.substring( + 0, defaultPackage.length() - 1) + simpleClassName; + if (classExists(fqn, compiler)) { + return defaultPackage; + } + } + for (String currentPackage : searchList) { + String className = currentPackage + simpleClassName; + if (classExists(className, compiler)) { + if (namespace != null) { + // we've already found the same name in another package + compiler.reportError( + "symbol '" + simpleClassName + + "' is ambiguous, found matching classes " + + namespace.substring(0, namespace.length() - 1) + + simpleClassName + " and " + currentPackage + + simpleClassName + + ". Use fully-qualified name to disambiguate." + ); + return null; + } + namespace = currentPackage + "*"; + } + } + } + + return namespace; + } + + /** + * Returns the <code>TagHandler</code> that should be used to process the + * specified tag. + * <p/> + * The <code>namespacePrefix</code> parameter is used only for error + * checking, as it is an error to specify conflicting package names using + * both a fully-qualified tag name and a namespace prefix, but it is not + * an error to specify conflicting package names using a fully-qualified + * tag name and a <i>default</i> namespace (i.e. + * <awt:javax.swing.JButton xmlns:awt='java.awt.*'/> + * is an error, whereas <javax.swing.JButton xmlns='java.awt.*'/> is not). + * + * @param namespace the tag's namespace (may be <code>null</code>) + * @param tag the tag's simple name (which can include + * fully-qualified Java class names) + * @param namespacePrefix <code>true</code> if the namespace was specified + * by means of a namespace prefix (as opposed to a + * default namespace) + * @param compiler the current <code>JAXXCompiler</code> + * @return the <code>TagHandler</code> for the tag + * @throws CompilerException ? + */ + public static TagHandler getTagHandler(String namespace, + String tag, + boolean namespacePrefix, + JAXXCompiler compiler) throws CompilerException { + if (tag == null) { + throw new NullPointerException("tag parameter can not be null"); + } + if (namespace == null && defaultNamespaces.containsKey(tag)) { + namespace = defaultNamespaces.get(tag); + if (namespace == null) { + + // defaultNamespaces map contains a null value, which is put + // there to indicate ambiguity + compiler.reportError( + "tag '" + tag + "' is ambiguous; specify " + + "fully-qualified name (package and class) to " + + "disambiguate" + ); + return null; + } + } + + TagHandler handler = registeredTags.get(new QName(namespace, tag)); + if (handler == null) { + if (namespace == null || namespace.endsWith("*")) { + String className; + if (namespace != null) { + className = resolveClassName( + namespace.substring(0, namespace.length() - 1) + tag, + compiler + ); + if (className == null) { + className = resolveClassName(tag, compiler); + if (namespacePrefix && + !className.startsWith( + namespace.substring( + 0, + namespace.length() - 1))) { + + // namespace was specified, but we found it in a + // different package - ignore + className = null; + } + } + } else { + className = resolveClassName(tag, compiler); + } + if (className != null) { + int dotPos = className.lastIndexOf("."); + namespace = className.substring(0, dotPos + 1) + "*"; + tag = className.substring(dotPos + 1); + handler = registeredTags.get(new QName(namespace, tag)); + if (handler == null) { + try { + ClassDescriptor beanClass = + ClassDescriptorHelper.getClassDescriptor( + className, + compiler.getClassLoader() + ); + handler = getTagHandler(beanClass); + } catch (ClassNotFoundException e) { + log.error(e); +// e.printStackTrace(); + } + } + } + } + } + return handler; + } + + /** + * Resolves a simple class name (like <code>Object</code> or + * <code>String</code>) to its fully-qualified name. + * <p/> + * Inner classes should be represented as they would appear in Java source + * code (e.g. JPopupMenu.Separator). Fully-qualified names, such as + * <code>java.lang.Object</code> are legal and will be returned unmodified + * (and in fact it is generally impossible to even know whether a given + * reference is fully qualified until it has been resolved). + * <p/> + * Returns <code>null</code> if no matching class could be found. + * + * @param name name to resolve + * @param compiler run to use + * @return the resolved fqn class name + */ + public static String resolveClassName(String name, JAXXCompiler compiler) { + if (name.endsWith("[]")) { + return resolveClassName( + name.substring(0, name.length() - 2), compiler) + "[]"; + } + if (name.contains("<")) { + + // strip off generic types + name = name.substring(0, name.indexOf("<")); + } + + name = name.intern(); + if (name.equals("boolean") || + name.equals("byte") || + name.equals("short") || + name.equals("int") || + name.equals("long") || + name.equals("float") || + name.equals("double") || + name.equals("char")) { + return name; + } + + String result = null; + String originalName = name; + String defaultNamespace = null; + if (defaultNamespaces.containsKey(name)) { + defaultNamespace = defaultNamespaces.get(name); + if (defaultNamespace == null) { + + // defaultNamespaces map contains a null value, which is put + // there to indicate ambiguity + compiler.reportError( + "class '" + name + "' is ambiguous; specify " + + "fully-qualified name (package and class) to " + + "disambiguate" + ); + return null; + } + } + if (defaultNamespace != null && defaultNamespace.endsWith("*")) { + result = defaultNamespace.substring( + 0, defaultNamespace.length() - 1) + name; + } + + if (result == null) { + // Inner class names (like JPopupMenu.Separator) present a special + // challenge. The name before the dot might be a package name, + // or it might be a class name. + // + // If it's a class name, it might be fully qualified, or it might + // not. And it's also not actually the correct name of the class, + // as far as the JVM is concerned -- the correct name uses a dollar + // sign instead of a dot (javax.swing.JPopupMenu$Separator). + // And there could be more than one inner class -- it's possible to + // have com.mycompany.Outer$Inner$Innerer$Innerest. + // + // The basic strategy is to run by treating the part before the + // last dot as a package name, as that is by far the most likely case. + // + // If we don't find the class there, change the last dot to a + // dollar sign and try again. + + // Suppose we have the tag + // <com.mycompany.Outer.Inner.Innerer.Innerest/>, + // matching the class above. Resolution proceeds like this: + // com.mycompany.Outer.Inner.Innerer.* : Innerest + // com.mycompany.Outer.Inner.* : Innerer$Innerest + // com.mycompany.Outer.* : Inner$Innerer$Innerest + // com.mycompany.* : Outer$Inner$Innerer$Innerest + // And at this point we have a match with the class Outer$Inner$Innerer$Innerest in package com.mycompany. + int dotPos = originalName.lastIndexOf('.'); + for (; ;) { + String namespace = dotPos != -1 ? originalName.substring(0, dotPos) + ".*" : "*"; + name = originalName.substring(dotPos + 1).replace('.', '$'); + String packageName = determinePackage(name, namespace, compiler); + if (packageName != null) { + assert packageName.endsWith("*"); + if (packageName.equals(namespace) || + namespace.equals("*")) { + // check for an alias (like javax.swing.JComboBox actually being jaxx.runtime.swing.JAXXComboBox) + TagHandler handler = + registeredTags.get(new QName(namespace, name)); + + if (handler != null) { + + // determine alias by looking at handler + ClassDescriptor alias = + ((DefaultObjectHandler) handler).getBeanClass(); + + // make sure the same handler is used for both the + // aliased and non-aliased names, in order to avoid + // "no CompiledObject has been registered" error + // the line below doesn't bother to handle the case + // where the aliased class name doesn't have a + // package, since it's a pretty safe assumption that + // that will never happen + assert alias.getPackageName() != null && alias.getPackageName().length() > 0 : "aliasing with no package name has not been implemented"; + registeredTags.put( + new QName(alias.getPackageName() + ".*", alias.getName().substring(alias.getPackageName().length() + 1)), + handler + ); + result = alias.getName(); + break; + } else { // no alias + result = packageName.substring(0, packageName.length() - 1) + name; + break; + } + } + // else we found a class by the same name, but in the wrong package + } + + if (dotPos <= 0) { + break; + } + dotPos = originalName.lastIndexOf('.', dotPos - 1); + } + } + + if (result != null && !result.equals(originalName)) { + + // check for aliases against the new name as well + result = resolveClassName(result, compiler); + } + + return result; + } + + public static ClassDescriptor resolveClass(String className, + JAXXCompiler compiler) { + try { + className = resolveClassName(className, compiler); + if (className == null) { + return null; + } + return ClassDescriptorHelper.getClassDescriptor( + className, + compiler.getClassLoader() + ); + } catch (ClassNotFoundException e) { + return null; + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ApplicationHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ApplicationHandler.java new file mode 100644 index 0000000..407aa7c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ApplicationHandler.java @@ -0,0 +1,85 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.Application; +import org.w3c.dom.Element; + +import javax.swing.WindowConstants; + +public class ApplicationHandler extends JWindowHandler { + + public static final String ATTRIBUTE_LOOK_AND_FEEL = "lookAndFeel"; + + public static final String ATTRIBUTE_DEFAULT_CLOSE_OPERATION = "defaultCloseOperation"; + + public ApplicationHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + Application.class + ); + } + + @Override + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) throws CompilerException { + if (propertyName.equals(ATTRIBUTE_LOOK_AND_FEEL) && + stringValue != null && + !stringValue.trim().startsWith("{")) { + compiler.appendBodyCode("{ " + object.getJavaCode() + ".setLookAndFeel(" + TypeManager.getJavaCode(stringValue) + "); }" + JAXXCompiler.getLineSeparator()); + } else { + super.setAttribute(object, + propertyName, + stringValue, + inline, + compiler + ); + } + } + + @Override + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, + ATTRIBUTE_DEFAULT_CLOSE_OPERATION, + String.valueOf(WindowConstants.EXIT_ON_CLOSE), + false, + compiler + ); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CellHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CellHandler.java new file mode 100644 index 0000000..0f1c915 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CellHandler.java @@ -0,0 +1,224 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.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.awt.GridBagConstraints; +import java.awt.Insets; +import java.io.IOException; + +public class CellHandler implements TagHandler { + + public static final String TAG_NAME = "cell"; + + public static final String ATTRIBUTE_INSETS = "insets"; + + public static final String ATTRIBUTE_WEIGHTX = "weightx"; + + public static final String ATTRIBUTE_WEIGHTY = "weighty"; + + public static final String ATTRIBUTE_COLUMNS = "columns"; + + public static final String ATTRIBUTE_ROWS = "rows"; + + public static final String ATTRIBUTE_FILL = "fill"; + + enum Fill { + none(GridBagConstraints.NONE), + horizontal(GridBagConstraints.HORIZONTAL), + vertical(GridBagConstraints.VERTICAL), + both(GridBagConstraints.BOTH); + + private final int intValue; + + Fill(int intValue) { + this.intValue = intValue; + } + + public int getIntValue() { + return intValue; + } + } + + public static final String ATTRIBUTE_ANCHOR = "anchor"; + + enum Anchor { + north(GridBagConstraints.NORTH), + northeast(GridBagConstraints.NORTHEAST), + east(GridBagConstraints.EAST), + southeast(GridBagConstraints.SOUTHEAST), + south(GridBagConstraints.SOUTH), + southwest(GridBagConstraints.SOUTHEAST), + west(GridBagConstraints.WEST), + northwest(GridBagConstraints.NORTHWEST), + center(GridBagConstraints.CENTER); + + private final int intValue; + + Anchor(int intValue) { + this.intValue = intValue; + } + + public int getIntValue() { + return intValue; + } + } + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + Node parent = tag.getParentNode(); + if (parent.getNodeType() != Node.ELEMENT_NODE || !parent.getLocalName().equals("row")) { + compiler.reportError("cell tag may only appear within row tag"); + return; + } + + TableHandler.CompiledTable table = (TableHandler.CompiledTable) compiler.getOpenComponent(); + table.newCell(); + GridBagConstraints c = table.getCellConstraints(); + setAttributes(c, tag); + compileChildrenSecondPass(tag, compiler); + } + + public static void setAttribute(GridBagConstraints c, String name, String value) throws CompilerException { + value = value.trim(); + if (name.equals(ATTRIBUTE_INSETS)) { + c.insets = (Insets) TypeManager.convertFromString(value, Insets.class); + } else if (name.equals(ATTRIBUTE_WEIGHTX)) { + c.weightx = Double.parseDouble(value); + } else if (name.equals(ATTRIBUTE_WEIGHTY)) { + c.weighty = Double.parseDouble(value); + } else if (name.equals(ATTRIBUTE_COLUMNS)) { + c.gridwidth = Integer.parseInt(value); + } else if (name.equals(ATTRIBUTE_ROWS)) { + c.gridheight = Integer.parseInt(value); + } else if (name.equals(ATTRIBUTE_FILL)) { + Fill fill = Fill.valueOf(value); + if (fill == null) { + throw new CompilerException("invalid value for fill attribute: '" + value + "'"); + } + c.fill = fill.getIntValue(); + } else if (name.equals(ATTRIBUTE_ANCHOR)) { + Anchor anchor = Anchor.valueOf(value); + if (anchor == null) { + throw new CompilerException("invalid value for anchor attribute: '" + value + "'"); + } + c.anchor = anchor.getIntValue(); +// if (value.equals(ANCHOR_VALUE_NORTH)) { +// c.anchor = GridBagConstraints.NORTH; +// } else if (value.equals(ANCHOR_VALUE_NORTHEAST)) { +// c.anchor = GridBagConstraints.NORTHEAST; +// } else if (value.equals(ANCHOR_VALUE_EAST)) { +// c.anchor = GridBagConstraints.EAST; +// } else if (value.equals(ANCHOR_VALUE_SOUTHEAST)) { +// c.anchor = GridBagConstraints.SOUTHEAST; +// } else if (value.equals(ANCHOR_VALUE_SOUTH)) { +// c.anchor = GridBagConstraints.SOUTH; +// } else if (value.equals(ANCHOR_VALUE_SOUTHWEST)) { +// c.anchor = GridBagConstraints.SOUTHWEST; +// } else if (value.equals(ANCHOR_VALUE_WEST)) { +// c.anchor = GridBagConstraints.WEST; +// } else if (value.equals(ANCHOR_VALUE_NORTHWEST)) { +// c.anchor = GridBagConstraints.NORTHWEST; +// } else if (value.equals(ANCHOR_VALUE_CENTER)) { +// c.anchor = GridBagConstraints.CENTER; +// } else { +// throw new IllegalArgumentException("invalid value for anchor attribute: '" + value + "'"); +// } + } else { + throw new UnsupportedAttributeException(name); + } + } + + public static void setAttributes(GridBagConstraints c, Element tag) throws CompilerException { + NamedNodeMap children = tag.getAttributes(); + for (int i = 0; i < children.getLength(); i++) { + Attr attribute = (Attr) children.item(i); + String name = attribute.getName(); + String value = attribute.getValue(); + if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + setAttribute(c, name, value); + } + } + } + + 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); + } 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() + "')"); + } + } + } + } + + 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() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CompiledItemContainer.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CompiledItemContainer.java new file mode 100644 index 0000000..ba37dbe --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/CompiledItemContainer.java @@ -0,0 +1,71 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.runtime.swing.Item; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** Compiled representation of a class that contains Items arranged in a list or tree structure (JComboBox, JList, JTree). */ +class CompiledItemContainer extends CompiledObject { + + private List<Item> items = new ArrayList<Item>(); + private Stack<Item> openNodes = new Stack<Item>(); + + public CompiledItemContainer(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + } + + public void openItem(Item item) { + if (openNodes.isEmpty()) { + items.add(item); + } else { + Item openNode = openNodes.peek(); + openNode.addChild(item); + } + openNodes.add(item); + } + + public void closeItem(Item item) { + if (!item.equals(openNodes.pop())) { + throw new IllegalArgumentException(item + " was not at the top of the item stack"); + } + } + + public List<Item> getItems() { + return items; + } + + public void setItems(List<Item> items) { + this.items = items; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ItemHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ItemHandler.java new file mode 100644 index 0000000..c1d7227 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/ItemHandler.java @@ -0,0 +1,177 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.Item; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.io.IOException; +import java.util.List; + +public class ItemHandler implements TagHandler { + + public static final String TAG_NAME = "item"; + + private String DATA_BINDING = "<data binding has not been processed yet>"; + + public static final String ATTRIBUTE_ID = "id"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + String id = tag.getAttribute(ATTRIBUTE_ID); + if (id == null || id.length() == 0) { + id = compiler.getAutoId(Item.class.getSimpleName()); +// id = compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(Item.class)); + } + String label = null; + String value = null; + boolean selected = false; + NamedNodeMap children = tag.getAttributes(); + + for (int i = 0; i < children.getLength(); i++) { + Attr attribute = (Attr) children.item(i); + String name = attribute.getName(); + String attrValue = attribute.getValue(); + if (name.equals(ATTRIBUTE_ID)) { + // already handled + continue; + } + DataBindingHelper bindingHelper = compiler.getBindingHelper(); + if (name.equals(Item.LABEL_PROPERTY)) { + String labelBinding = DataBindingHelper.processDataBindings(attrValue); + if (labelBinding != null) { + bindingHelper.registerDataBinding(id + ".label", labelBinding, id + ".setLabel(" + labelBinding + ");"); +// bindingHelper.registerDataBinding(labelBinding, id + ".label", id + ".setLabel(" + labelBinding + ");"); + } else { + label = attrValue; + } + continue; + } + if (name.equals(Item.VALUE_PROPERTY)) { + String valueBinding = DataBindingHelper.processDataBindings(attrValue); + if (valueBinding != null) { + value = DATA_BINDING; + bindingHelper.registerDataBinding(id + ".value", valueBinding, id + ".setValue(" + valueBinding + ");"); +// bindingHelper.registerDataBinding(valueBinding, id + ".value", id + ".setValue(" + valueBinding + ");"); + } else { + value = attrValue; + } + continue; + } + if (name.equals(Item.SELECTED_PROPERTY)) { + String selectedBinding = DataBindingHelper.processDataBindings(attrValue); + if (selectedBinding != null) { + bindingHelper.registerDataBinding(id + ".selected", selectedBinding, id + ".setSelected(" + selectedBinding + ");"); +// bindingHelper.registerDataBinding(selectedBinding, id + ".selected", id + ".setSelected(" + selectedBinding + ");"); + } else { + selected = (Boolean) TypeManager.convertFromString(attrValue, Boolean.class); + } + continue; + } + + if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + throw new UnsupportedAttributeException(name); + } + } + + Item item = new Item(id, label, value, selected); + CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); + if (value == null) { + compiler.reportError("<item> tag is missing required 'value' attribute"); + } else { + if (!value.equals(DATA_BINDING)) { + List<Item> items = list.getItems(); + for (Item item1 : items) { + if (item1.getValue().equals(value)) { + compiler.reportError("This container already has an <item> tag with the value '" + value + "'"); + break; + } + } + } + list.openItem(item); + compileChildrenSecondPass(tag, compiler); + list.closeItem(item); + } + } + + 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); + } 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() + "')"); + } + } + } + } + + 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() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java new file mode 100644 index 0000000..968e44e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXComboBoxHandler.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.JAXXComboBox; +import jaxx.runtime.swing.Item; +import org.w3c.dom.Element; + +import java.awt.event.ItemListener; +import java.io.IOException; +import java.util.List; + +public class JAXXComboBoxHandler extends DefaultComponentHandler { + + public JAXXComboBoxHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXComboBox.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ItemListener.class); + addProxyEventInfo("getSelectedItem", ItemListener.class); + } + + @Override + protected CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledItemContainer(id, getBeanClass(), compiler); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileChildrenSecondPass(tag, compiler); + CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); + List<Item> items = list.getItems(); + if (items != null && !items.isEmpty()) { + String listName = list.getId() + "$items"; + list.appendAdditionCode("java.util.List<jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<jaxx.runtime.swing.Item>();"); + for (Item item : items) { + String id = item.getId(); + CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); + compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); + compiler.registerCompiledObject(compiledItem); + list.appendAdditionCode(listName + ".add(" + id + ");"); + } + list.appendAdditionCode(list.getId() + ".setItems(" + listName + ");"); + } + } +} + + + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXListHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXListHandler.java new file mode 100644 index 0000000..4f1cfae --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXListHandler.java @@ -0,0 +1,86 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.JAXXList; +import jaxx.runtime.swing.Item; +import org.w3c.dom.Element; + +import javax.swing.event.ListSelectionListener; +import java.io.IOException; +import java.util.List; + +public class JAXXListHandler extends DefaultComponentHandler { + + public JAXXListHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXList.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedIndices", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValue", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValues", ListSelectionListener.class, "selectionModel"); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledItemContainer(id, getBeanClass(), compiler); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileChildrenSecondPass(tag, compiler); + CompiledItemContainer list = (CompiledItemContainer) compiler.getOpenComponent(); + List<Item> items = list.getItems(); + if (items != null && !items.isEmpty()) { + String listName = list.getId() + "$items"; + //TODO Add the correct generic type + list.appendAdditionCode("java.util.List<jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<jaxx.runtime.swing.Item>();"); + for (Item item : items) { + String id = item.getId(); + CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); + compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); + compiler.registerCompiledObject(compiledItem); + list.appendAdditionCode(listName + ".add(" + id + ");"); + } + list.appendAdditionCode(list.getId() + ".setItems(" + listName + ");"); + } + } +} + + + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTabHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTabHandler.java new file mode 100644 index 0000000..6b6eca9 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTabHandler.java @@ -0,0 +1,36 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.reflect.ClassDescriptor; + +/** @author tchemit <chemit@codelutin.com> */ +public class JAXXTabHandler extends TableHandler { + + public JAXXTabHandler(ClassDescriptor beanClass) { + super(beanClass); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTreeHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTreeHandler.java new file mode 100644 index 0000000..8eb2b0b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JAXXTreeHandler.java @@ -0,0 +1,91 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.Item; +import jaxx.runtime.swing.JAXXTree; +import org.w3c.dom.Element; + +import javax.swing.event.TreeSelectionListener; +import java.io.IOException; +import java.util.List; + +public class JAXXTreeHandler extends DefaultComponentHandler { + + public JAXXTreeHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JAXXTree.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectionCount", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPath", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPaths", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionRows", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionValue", TreeSelectionListener.class, "selectionModel"); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledItemContainer(id, getBeanClass(), compiler); + } + + private void createItems(CompiledObject tree, List<Item> items, String addMethod, JAXXCompiler compiler) throws CompilerException { + for (Item item : items) { + String id = item.getId(); + CompiledObject compiledItem = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(Item.class), compiler); + compiledItem.setConstructorParams(TypeManager.getJavaCode(id) + ", " + TypeManager.getJavaCode(item.getLabel()) + ", " + TypeManager.getJavaCode(item.getValue()) + ", " + item.isSelected()); + compiler.registerCompiledObject(compiledItem); + tree.appendAdditionCode(addMethod + "(" + id + ");"); + createItems(tree, item.getChildren(), id + ".addChild", compiler); + } + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileChildrenSecondPass(tag, compiler); + CompiledItemContainer tree = (CompiledItemContainer) compiler.getOpenComponent(); + List<Item> items = tree.getItems(); + if (items != null && !items.isEmpty()) { + String listName = tree.getId() + "$items"; + tree.appendAdditionCode("java.util.List<jaxx.runtime.swing.Item> " + listName + " = new java.util.ArrayList<jaxx.runtime.swing.Item>();"); + createItems(tree, items, listName + ".add", compiler); + tree.appendAdditionCode(tree.getId() + ".setItems(" + listName + ");"); + } + } +} + + + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JCheckBoxHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JCheckBoxHandler.java new file mode 100644 index 0000000..286ec40 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JCheckBoxHandler.java @@ -0,0 +1,47 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.AbstractButton; +import javax.swing.event.ChangeListener; + +public class JCheckBoxHandler extends DefaultComponentHandler { + + public JCheckBoxHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, AbstractButton.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("isSelected", ChangeListener.class, "model"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JComboBoxHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JComboBoxHandler.java new file mode 100644 index 0000000..7ed129a --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JComboBoxHandler.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import java.io.IOException; +import java.awt.event.ItemListener; +import javax.swing.JComboBox; + +public class JComboBoxHandler extends DefaultComponentHandler { + + public JComboBoxHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JComboBox.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ItemListener.class); + addProxyEventInfo("getSelectedItem", ItemListener.class); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + if (children.getLength() > 0) { + compiler.reportError("JComboBox does not accept childs"); + throw new CompilerException("JComboBox does not accept childs"); + } + } +} + + + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JInternalFrameHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JInternalFrameHandler.java new file mode 100644 index 0000000..8f7fbaa --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JInternalFrameHandler.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JInternalFrame; +import javax.swing.JMenuBar; +import javax.swing.WindowConstants; + +public class JInternalFrameHandler extends DefaultComponentHandler { + + public JInternalFrameHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JInternalFrame.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (ClassDescriptorHelper.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) { + appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); + } else { + super.addChild(child, constraints, compiler); + } + } + }; + } + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, "visible", "true", false, compiler); + setAttribute(object, "closable", "true", false, compiler); + setAttribute(object, "defaultCloseOperation", String.valueOf(WindowConstants.DISPOSE_ON_CLOSE), false, compiler); + } + + @Override + public void setAttributes(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setAttributes(object, tag, compiler); + compiler.appendInitializerCode(object.getId() + ".pack();\n"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JListHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JListHandler.java new file mode 100644 index 0000000..b442bb1 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JListHandler.java @@ -0,0 +1,67 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import java.io.IOException; +import javax.swing.event.ListSelectionListener; +import javax.swing.JList; + +public class JListHandler extends DefaultComponentHandler { + + public JListHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JList.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedIndices", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValue", ListSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectedValues", ListSelectionListener.class, "selectionModel"); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + if (children.getLength() > 0) { + compiler.reportError("JList does not accept childs"); + throw new CompilerException("JList does not accept childs"); + } + } +} + + + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JMenuHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JMenuHandler.java new file mode 100644 index 0000000..035aa90 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JMenuHandler.java @@ -0,0 +1,47 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JMenu; +import javax.swing.event.MenuListener; + +public class JMenuHandler extends DefaultComponentHandler { + + public JMenuHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JMenu.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("isSelected", MenuListener.class); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPasswordFieldHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPasswordFieldHandler.java new file mode 100644 index 0000000..76ea124 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPasswordFieldHandler.java @@ -0,0 +1,46 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; + +import javax.swing.JPasswordField; +import javax.swing.event.DocumentListener; + +public class JPasswordFieldHandler extends JTextComponentHandler { + + public JPasswordFieldHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JPasswordField.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getPassword", DocumentListener.class, "document"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPopupMenuHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPopupMenuHandler.java new file mode 100644 index 0000000..fbca021 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JPopupMenuHandler.java @@ -0,0 +1,53 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JPopupMenu; + +public class JPopupMenuHandler extends DefaultComponentHandler { + + public JPopupMenuHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JPopupMenu.class); + } + + @Override + public boolean isContainer() { + return true; + } + + @Override + protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) { + compiler.openInvisibleComponent(object); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JProgressBarHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JProgressBarHandler.java new file mode 100644 index 0000000..18e4658 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JProgressBarHandler.java @@ -0,0 +1,47 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JProgressBar; +import javax.swing.event.ChangeListener; + +public class JProgressBarHandler extends DefaultComponentHandler { + + public JProgressBarHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JProgressBar.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getValue", ChangeListener.class, "change"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JRadioButtonHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JRadioButtonHandler.java new file mode 100644 index 0000000..4026e2a --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JRadioButtonHandler.java @@ -0,0 +1,109 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.JAXXButtonGroup; + +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; +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); + ClassDescriptorHelper.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 ClassDescriptorHelper.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, ClassDescriptorHelper.getClassDescriptor(JAXXButtonGroup.class), compiler); + compiler.registerCompiledObject(buttonGroup); + } + } + String type = compiler.getImportedType( + ButtonGroup.class.getName()); + + return "{ " + type + " $buttonGroup = " + valueCode + "; " + id + ".putClientProperty(\"$buttonGroup\", $buttonGroup); $buttonGroup.add(" + id + "); }\n"; + } else if (name.equals(VALUE_PROPERTY)) { + String type = compiler.getImportedType( + JAXXButtonGroup.class.getName()); + return "{ " + id + ".putClientProperty(\"" + JAXXButtonGroup.VALUE_CLIENT_PROPERTY + "\", " + valueCode + "); Object $buttonGroup = " + id + ".getClientProperty(\"" + JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY + "\");" + + " if ($buttonGroup instanceof " + type + ") { ((" + type + ") $buttonGroup).updateSelectedValue(); } }\n"; + } else { + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JScrollPaneHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JScrollPaneHandler.java new file mode 100644 index 0000000..a5aeaa0 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JScrollPaneHandler.java @@ -0,0 +1,104 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.apache.commons.lang3.StringUtils; + +import javax.swing.JScrollPane; + +public class JScrollPaneHandler extends DefaultComponentHandler { + + public static class JScrollPaneCompiledObject extends CompiledObject { + + boolean hasChild; + + boolean hasColumnViewHeader; + + public static final String COLUMN_HEADER_VIEW = "columnHeaderView"; + + public JScrollPaneCompiledObject(String id, + ClassDescriptor beanclass, + JAXXCompiler compiler) { + super(id, beanclass, compiler); + } + + @Override + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("JScrollPane does not accept constraints"); + } + + if (!hasChild) { + // first child is always the view port component + super.addChild(child, constraints, compiler); + hasChild = true; + return; + } + + if (!hasColumnViewHeader) { + + // try to add a column view header + String property = + (String) getProperties().get(COLUMN_HEADER_VIEW); + + if (log.isDebugEnabled()) { + log.info("property to match " + property + " against child " + child.getId()); + } + if (!StringUtils.isEmpty(property) && + ("{" + child.getId() + "}").equals(property)) { + hasColumnViewHeader = true; + return; + } + } + + compiler.reportError( + "JScrollPane may only have one child (found another child : " + child.getId() + ")."); + + } + } + + public JScrollPaneHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + JScrollPane.class + ); + } + + @Override + public CompiledObject createCompiledObject(String id, + JAXXCompiler compiler) throws CompilerException { + return new JScrollPaneCompiledObject(id, getBeanClass(), compiler); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSliderHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSliderHandler.java new file mode 100644 index 0000000..740dafd --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSliderHandler.java @@ -0,0 +1,70 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +import javax.swing.JSlider; +import javax.swing.event.ChangeListener; + +public class JSliderHandler extends DefaultComponentHandler { + public static final String ATTRIBUTE_VALUE = "value"; + + public JSliderHandler(ClassDescriptor beanClass) { + super(beanClass); + if (!ClassDescriptorHelper.getClassDescriptor(JSlider.class).isAssignableFrom(beanClass)) { + throw new IllegalArgumentException(getClass().getName() + " does not support the class " + beanClass.getName()); + } + } + + @Override + protected int getAttributeOrdering(Attr attr) { + if (attr.getName().equals(ATTRIBUTE_VALUE)) { + return 1; + } else { + return super.getAttributeOrdering(attr); + } + } + + @Override + protected void setDefaults(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + setAttribute(object, ATTRIBUTE_VALUE, "0", false, compiler); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getValue", ChangeListener.class, "model"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSpinnerHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSpinnerHandler.java new file mode 100644 index 0000000..60bf9a6 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSpinnerHandler.java @@ -0,0 +1,124 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeListener; + +public class JSpinnerHandler extends DefaultComponentHandler { + + public static String MINIMUM_PROPERTY = "minimum"; + + public static String MAXIMUM_PROPERTY = "maximum"; + + public static String VALUE_PROPERTY = "value"; + + public JSpinnerHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JSpinner.class); + } + + public static class CompiledSpinner extends CompiledObject { + + Integer minimum; + + Integer maximum; + + Integer value; + + public CompiledSpinner(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + } + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledSpinner(id, getBeanClass(), compiler); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getValue", ChangeListener.class, "model"); + } + + @Override + public ClassDescriptor getPropertyType(CompiledObject object, String propertyName, JAXXCompiler compiler) throws CompilerException { + if (propertyName.equals(MINIMUM_PROPERTY) || propertyName.equals(MAXIMUM_PROPERTY) || + propertyName.equals(VALUE_PROPERTY)) { + return ClassDescriptorHelper.getClassDescriptor(Integer.class); + } + return super.getPropertyType(object, propertyName, compiler); + } + + @Override + public void setProperty(CompiledObject object, String name, Object value, JAXXCompiler compiler) throws CompilerException { + if (name.equals(MINIMUM_PROPERTY)) { + ((CompiledSpinner) object).minimum = (Integer) value; + } else if (name.equals(MAXIMUM_PROPERTY)) { + ((CompiledSpinner) object).maximum = (Integer) value; + } else if (name.equals(VALUE_PROPERTY)) { + ((CompiledSpinner) object).value = (Integer) value; + } else { + super.setProperty(object, name, value, compiler); + } + } + + @Override + protected void closeComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + CompiledSpinner spinner = (CompiledSpinner) object; + if (spinner.minimum != null || + spinner.maximum != null || + spinner.value != null) { + if (spinner.getConstructorParams() != null) { + compiler.reportError("constructorParams and minimum/maximum may not both be specified for the same JSpinner"); + } + if (spinner.minimum == null) { + spinner.minimum = Math.min(0, spinner.maximum != null ? spinner.maximum : 0); + } + if (spinner.maximum == null) { + spinner.maximum = Math.max(100, spinner.minimum.intValue()); + } + if (spinner.value == null) { + spinner.value = spinner.minimum; + } + String type = compiler.getImportedType(SpinnerNumberModel.class); + + spinner.setConstructorParams("new " + type + "(" + spinner.value + ", " + spinner.minimum + ", " + spinner.maximum + ", 1)"); + } + + super.closeComponent(object, tag, compiler); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSplitPaneHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSplitPaneHandler.java new file mode 100644 index 0000000..d5ae19a --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JSplitPaneHandler.java @@ -0,0 +1,102 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JSplitPane; + +public class JSplitPaneHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_ORIENTATION = "orientation"; + + public static final String ORIENTATION_VALUE_HORIZONTAL = "horizontal"; + + public static final String ORIENTATION_VALUE_VERTICAL = "vertical"; + + public static final String ORIENTATION_VALUE_VERTICAL_SPLIT = "vertical_split"; + + public static final String ORIENTATION_VALUE_HORIZONTAL_SPLIT = "horizontal_split"; + + public JSplitPaneHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JSplitPane.class); + } + +// protected Component createRawComponent(Element tag) { +// return new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); +// } + + /** + * Add support for <code>orientation="vertical"</code> and <code>orientation="horizontal"</code>. The + * values required by the JAXXBeanInfo are the unwieldy <code>vertical_split</code> and <code>horizontal_split</code> + * (which are also recognized). + */ + @Override + protected int constantValue(String key, String value) { + if (key.equals(ATTRIBUTE_ORIENTATION)) { + value = value.trim().toLowerCase(); + if (value.equals(ORIENTATION_VALUE_HORIZONTAL) || + value.equals(ORIENTATION_VALUE_HORIZONTAL_SPLIT)) { + return JSplitPane.HORIZONTAL_SPLIT; + } + if (value.equals(ORIENTATION_VALUE_VERTICAL) || + value.equals(ORIENTATION_VALUE_VERTICAL_SPLIT)) { + return JSplitPane.VERTICAL_SPLIT; + } + throw new IllegalArgumentException("orientation must be 'horizontal' or 'vertical', found '" + value + "'"); + } + return super.constantValue(key, value); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + private int count; + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("JSplitPane does not accept constraints"); + } + if (count == 0) { + super.addChild(child, "JSplitPane.LEFT", compiler); + } else if (count == 1) { + super.addChild(child, "JSplitPane.RIGHT", compiler); + } else { + compiler.reportError("JSplitPane is limited to two children"); + } + count++; + } + }; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTabbedPaneHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTabbedPaneHandler.java new file mode 100644 index 0000000..4fc2bdc --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTabbedPaneHandler.java @@ -0,0 +1,171 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.I18nHelper; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.TabInfo; +import jaxx.runtime.swing.TabInfoPropertyChangeListener; + +import javax.swing.Icon; +import javax.swing.JTabbedPane; +import javax.swing.event.ChangeListener; +import java.awt.Color; +import java.awt.event.ContainerListener; + +public class JTabbedPaneHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_TITLE = "title"; + + public static final String ATTRIBUTE_TOOL_TIP_TEXT = "toolTipText"; + + public JTabbedPaneHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JTabbedPane.class); + } + + public static class CompiledTabbedPane extends CompiledObject { + + private static final TabInfo USED = new TabInfo("ALREADY USED"); + + int tabCount; + + TabInfo tabInfo; + + + public CompiledTabbedPane(String id, ClassDescriptor objectClass, JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + } + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("JTabbedPane tabs may not have constraints"); + } + + super.addChild(child, constraints, compiler); + + if (tabInfo == null) { + compiler.reportError("JTabbedPaneHandler may only have 'tab' tags as children (found " + child.getObjectClass() + ")"); + return; + } else if (USED.equals(tabInfo)) { + compiler.reportError("<tab> tags may only have one child component"); + return; + } + + int tabIndex = ++tabCount - 1; + String type = compiler.getImportedType(TabInfoPropertyChangeListener.class); + appendAdditionCode(tabInfo.getId() + ".addPropertyChangeListener(new " + type + "(" + getId() + ", " + tabIndex + "));"); + + String title = tabInfo.getTitle(); + if (title != null) { + if (I18nHelper.isI18nAttribute(ATTRIBUTE_TITLE)) { + if (!title.startsWith("_(\"")) { + // we did not have the invocation code, add it + title = I18nHelper.addI18nInvocation(getId(), ATTRIBUTE_TITLE, TypeManager.getJavaCode(title), compiler); + } + } else { + title = TypeManager.getJavaCode(title); + } + appendAdditionCode(getId() + ".setTitleAt(" + tabIndex + ", " + title + ");"); + } + + String toolTipText = tabInfo.getToolTipText(); + if (toolTipText != null) { + if (I18nHelper.isI18nAttribute(ATTRIBUTE_TOOL_TIP_TEXT)) { + if (!toolTipText.startsWith("_(\"")) { + // we did not have the invocation code, add it + toolTipText = I18nHelper.addI18nInvocation(getId(), ATTRIBUTE_TOOL_TIP_TEXT, TypeManager.getJavaCode(toolTipText), compiler); + } + } else { + toolTipText = TypeManager.getJavaCode(toolTipText); + } + appendAdditionCode(getId() + ".setToolTipTextAt(" + tabIndex + ", " + toolTipText + ");"); + } + + boolean enabled = tabInfo.isEnabled(); + if (!enabled) { + appendAdditionCode(getId() + ".setEnabledAt(" + tabIndex + ", false);"); + } + + Color foreground = tabInfo.getForeground(); + if (foreground != null) { + appendAdditionCode(getId() + ".setForegroundAt(" + tabIndex + ", " + TypeManager.getJavaCode(foreground) + ");"); + } + + Color background = tabInfo.getBackground(); + if (background != null) { + appendAdditionCode(getId() + ".setBackgroundAt(" + tabIndex + ", " + TypeManager.getJavaCode(background) + ");"); + } + + int mnemonic = tabInfo.getMnemonic(); + if (mnemonic != -1) { + appendAdditionCode(getId() + ".setMnemonicAt(" + tabIndex + ", " + mnemonic + ");"); + } + + int displayedMnemonicIndex = tabInfo.getDisplayedMnemonicIndex(); + if (displayedMnemonicIndex != -1) { + appendAdditionCode(getId() + ".setDisplayedMnemonicIndexAt(" + tabIndex + ", " + displayedMnemonicIndex + ");"); + } + + Icon icon = tabInfo.getIcon(); + if (icon != null) { + appendAdditionCode(getId() + ".setIconAt(" + tabIndex + ", " + icon + ");"); + } + + Icon disabledIcon = tabInfo.getDisabledIcon(); + if (disabledIcon != null) { + appendAdditionCode(getId() + ".setDisabledIconAt(" + tabIndex + ", " + disabledIcon + ");"); + } + + String tabComponent = tabInfo.getTabComponentStr(); + if (tabComponent != null) { + appendAdditionCode(getId() + ".setTabComponentAt(" + tabIndex + ", " + tabComponent + ");"); + } + + tabInfo = USED; + } + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledTabbedPane(id, getBeanClass(), compiler); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectedIndex", ChangeListener.class); + addProxyEventInfo("getSelectedComponent", ChangeListener.class); + addProxyEventInfo("getTabCount", ContainerListener.class); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTextComponentHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTextComponentHandler.java new file mode 100644 index 0000000..1812305 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTextComponentHandler.java @@ -0,0 +1,115 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.runtime.SwingUtil; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +import javax.swing.JTextArea; +import javax.swing.event.DocumentListener; +import javax.swing.text.JTextComponent; + +public class JTextComponentHandler extends DefaultComponentHandler { + + private static final int DEFAULT_COLUMNS = 15; + + public static final String ATTRIBUTE_LINE_WRAP = "lineWrap"; + + public static final String ATTRIBUTE_WRAP_STYLE_WORD = "wrapStyleWord"; + + public static final String ATTRIBUTE_COLUMNS = "columns"; + + public static final String ATTRIBUTE_TEXT = "text"; + + public JTextComponentHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + JTextComponent.class); + } + + @Override + protected void setDefaults(CompiledObject object, + Element tag, + JAXXCompiler compiler) throws CompilerException { + super.setDefaults(object, tag, compiler); + try { + object.getObjectClass().getMethodDescriptor("setColumns", + ClassDescriptorHelper.getClassDescriptor(int.class) + ); + setAttribute(object, + ATTRIBUTE_COLUMNS, + String.valueOf(DEFAULT_COLUMNS), + false, + compiler + ); + } catch (NoSuchMethodException e) { + // ignore ? + } + + if (ClassDescriptorHelper.getClassDescriptor(JTextArea.class).isAssignableFrom(object.getObjectClass())) { + setAttribute(object, ATTRIBUTE_LINE_WRAP, "true", false, compiler); + setAttribute(object, ATTRIBUTE_WRAP_STYLE_WORD, "true", false, compiler); + } + } + + @Override + public String getSetPropertyCode(String id, + String name, + String valueCode, + JAXXCompiler compiler) throws CompilerException { + if (name.equals(ATTRIBUTE_TEXT)) { + String prefix = compiler.getImportedType(SwingUtil.class); + return prefix + ".setText(" + + id + ", " + valueCode + ");" + + JAXXCompiler.getLineSeparator(); + } + return super.getSetPropertyCode(id, name, valueCode, compiler); + } + + @Override + protected int getAttributeOrdering(Attr attr) { + // delay text in case other attributes affect how it's processed, as is the case + // with JEditorPane's contentType + if (ATTRIBUTE_TEXT.equals(attr.getName())) { + return 1; + } + return super.getAttributeOrdering(attr); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getText", DocumentListener.class, "document"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JToolBarHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JToolBarHandler.java new file mode 100644 index 0000000..cba04d6 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JToolBarHandler.java @@ -0,0 +1,81 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; + +import javax.swing.JToolBar; + +public class JToolBarHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_ORIENTATION = "orientation"; + + enum Orientation { + horizontal(JToolBar.HORIZONTAL), + vertical(JToolBar.VERTICAL); + + private final int intValue; + + Orientation(int intValue) { + this.intValue = intValue; + } + + public int getIntValue() { + return intValue; + } + } + + public JToolBarHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + JToolBar.class + ); + } + + /** + * Add support for <code>orientation="vertical"</code> and <code>orientation="horizontal"</code>. These values should + * have been supported without any special effort on my part, but JToolBar's BeanInfo doesn't contain the enum attribute + * for the orientation property. + */ + @Override + protected int constantValue(String key, String value) { + if (ATTRIBUTE_ORIENTATION.equals(key)) { + value = value.trim().toLowerCase(); + Orientation fill = Orientation.valueOf(value); + if (fill == null) { + throw new CompilerException( + "invalid value for orientation attribute: '" + value + + "'"); + } + return fill.getIntValue(); + } + return super.constantValue(key, value); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTreeHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTreeHandler.java new file mode 100644 index 0000000..c56b5f0 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JTreeHandler.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.event.TreeSelectionListener; +import java.io.IOException; +import javax.swing.JTree; +import org.w3c.dom.NodeList; + +public class JTreeHandler extends DefaultComponentHandler { + + public JTreeHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JTree.class); + } + + @Override + protected void configureProxyEventInfo() { + super.configureProxyEventInfo(); + addProxyEventInfo("getSelectionCount", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPath", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionPaths", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionRows", TreeSelectionListener.class, "selectionModel"); + addProxyEventInfo("getSelectionValue", TreeSelectionListener.class, "selectionModel"); + } + + @Override + public void compileChildrenSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + NodeList children = tag.getChildNodes(); + if (children.getLength() > 0) { + compiler.reportError("JTree does not accept childs"); + throw new CompilerException("JTree does not accept childs"); + } + } +} + + + diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JWindowHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JWindowHandler.java new file mode 100644 index 0000000..57166ed --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JWindowHandler.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.w3c.dom.Element; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JWindow; +import java.io.IOException; +import java.util.Map; + +public class JWindowHandler extends DefaultComponentHandler { + + public JWindowHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JWindow.class, JFrame.class, JDialog.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + @Override + public void addChild(CompiledObject child, String constraints, JAXXCompiler compiler) throws CompilerException { + if (ClassDescriptorHelper.getClassDescriptor(JMenuBar.class).isAssignableFrom(child.getObjectClass())) { + appendAdditionCode(getId() + ".setJMenuBar(" + child.getId() + ");"); + } else { + super.addChild(child, constraints, compiler); + } + } + }; + } + + @Override + protected void openComponent(CompiledObject object, Element tag, JAXXCompiler compiler) throws CompilerException { + if (compiler.getOpenComponent() != null) { + compiler.openInvisibleComponent(object); + } else { + super.openComponent(object, tag, compiler); + } + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + super.compileSecondPass(tag, compiler); + CompiledObject object = objectMap.get(tag); + Map<?, ?> properties = object.getProperties(); + if (!properties.containsKey("width") && !properties.containsKey("height")) { + compiler.appendLateInitializer(object.getId() + ".pack();\n"); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JXLayerHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JXLayerHandler.java new file mode 100644 index 0000000..5653473 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/JXLayerHandler.java @@ -0,0 +1,111 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import org.apache.commons.collections.CollectionUtils; +import org.jdesktop.jxlayer.JXLayer; + +import java.awt.Component; + +/** + * To deal with JXLayer, since from version 3.0.4, we can not use any longer + * the {@link JXLayer#add(Component)} ! but must now use the + * method {@link JXLayer#setView(Component)}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4 + */ +public class JXLayerHandler extends DefaultComponentHandler { + + public static final String ATTRIBUTE_ORIENTATION = "orientation"; + + public static final String ORIENTATION_VALUE_HORIZONTAL = "horizontal"; + + public static final String ORIENTATION_VALUE_VERTICAL = "vertical"; + + public static final String ORIENTATION_VALUE_VERTICAL_SPLIT = "vertical_split"; + + public static final String ORIENTATION_VALUE_HORIZONTAL_SPLIT = "horizontal_split"; + + public JXLayerHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), beanClass, JXLayer.class); + } + + @Override + public CompiledObject createCompiledObject(String id, JAXXCompiler compiler) throws CompilerException { + return new CompiledObject(id, getBeanClass(), compiler) { + + @Override + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + + if (constraints != null) { + compiler.reportError("JXLayer does not accept constraints"); + return; + } + if (CollectionUtils.isNotEmpty(getChilds())) { + + // already one child, authrozied only one child... + compiler.reportError("JXLayer is limited to one children"); + return; + } + super.addChild(child, constraints, compiler); + + } + + @Override + protected ChildRef newChildRef(CompiledObject child, String constraints, String delegateCode) { + return new ChildRef(child, + constraints, + child.getJavaCode(), + delegateCode) { + @Override + public void addToAdditionCode(StringBuilder buffer, boolean isRootObject) { + //TC-20091026 do not prefix if on root object + String prefix; + if (isRootObject) { + prefix = ""; + } else { + prefix = getJavaCode() + getDelegateCode() + "."; + } + buffer.append(prefix); + buffer.append("setView("); + buffer.append(getChildJavaCode()); + buffer.append(");"); + buffer.append(JAXXCompiler.getLineSeparator()); + } + }; + } + }; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/RowHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/RowHandler.java new file mode 100644 index 0000000..60a78ad --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/RowHandler.java @@ -0,0 +1,111 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.TagHandler; +import jaxx.runtime.swing.Table; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import java.awt.GridBagConstraints; +import java.io.IOException; + +public class RowHandler implements TagHandler { + + public static final String TAG_NAME = "row"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + if (!ClassDescriptorHelper.getClassDescriptor(Table.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { + compiler.reportError("row tag may only appear within Table tag"); + return; + } + + TableHandler.CompiledTable table = (TableHandler.CompiledTable) compiler.getOpenComponent(); + table.newRow(); + GridBagConstraints c = table.getRowConstraints(); + CellHandler.setAttributes(c, tag); + compileChildrenSecondPass(tag, compiler); + } + + public 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; + if (!child.getLocalName().equals(CellHandler.TAG_NAME)) { + compiler.reportError("tag '" + tag.getLocalName() + "' may only contain cell tags as children"); + } + compileChildTagFirstPass(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() + "')"); + } + } + } + } + + public 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; + if (!child.getLocalName().equals(CellHandler.TAG_NAME)) { + compiler.reportError("tag '" + tag.getLocalName() + "' may only contain cell tags as children"); + } + 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() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TabHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TabHandler.java new file mode 100644 index 0000000..a1bdfbf --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TabHandler.java @@ -0,0 +1,221 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.I18nHelper; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.TabInfo; +import org.apache.commons.lang3.StringUtils; +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 javax.swing.Icon; +import javax.swing.JTabbedPane; +import java.awt.Color; +import java.io.IOException; + +public class TabHandler implements TagHandler { + + public static final String TAG_NAME = "tab"; + + public static final String ATTRIBUTE_ID = "id"; + + public static final String ATTRIBUTE_TITLE = "title"; + + public static final String ATTRIBUTE_TOOL_TIP_TEXT = "toolTipText"; + + public static final String ATTRIBUTE_ICON = "icon"; + + public static final String ATTRIBUTE_ENABLED = "enabled"; + + public static final String ATTRIBUTE_DISABLED_ICON = "disabledIcon"; + + public static final String ATTRIBUTE_MNEMONIC = "mnemonic"; + + public static final String ATTRIBUTE_DISPLAYED_MNEMONIC_INDEX = "displayedMnemonicIndex"; + + public static final String ATTRIBUTE_FOREGROUND = "foreground"; + + public static final String ATTRIBUTE_BACKGROUND = "background"; + + public static final String ATTRIBUTE_TAB_COMPONENT = "tabComponent"; + + @Override + public void compileFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compileChildrenFirstPass(tag, compiler); + } + + @Override + public void compileSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + if (!ClassDescriptorHelper.getClassDescriptor(JTabbedPane.class).isAssignableFrom(compiler.getOpenComponent().getObjectClass())) { + compiler.reportError("tab tag may only appear within JTabbedPane tag"); + return; + } + + JTabbedPaneHandler.CompiledTabbedPane tabs = (JTabbedPaneHandler.CompiledTabbedPane) compiler.getOpenComponent(); + + String id = tag.getAttribute(ATTRIBUTE_ID); + if (id == null || id.length() == 0) { + id = compiler.getAutoId(TabInfo.class.getSimpleName()); +// id = compiler.getAutoId(ClassDescriptorHelper.getClassDescriptor(TabInfo.class)); + } + TabInfo tabInfo = new TabInfo(id); + CompiledObject compiledTabInfo = new CompiledObject(id, ClassDescriptorHelper.getClassDescriptor(TabInfo.class), compiler); + compiler.registerCompiledObject(compiledTabInfo); + //id = tabInfo.getId(); + tabs.tabInfo = tabInfo; + setAttributes(compiledTabInfo, tabs, tag, compiler); + compileChildrenSecondPass(tag, compiler); + tabs.tabInfo = null; + } + + public static void setAttribute(CompiledObject compiledTabInfo, JTabbedPaneHandler.CompiledTabbedPane tabs, String name, String value, JAXXCompiler compiler) throws CompilerException { + value = value.trim(); + TabInfo tabInfo = tabs.tabInfo; + String id = tabInfo.getId(); + String binding = DataBindingHelper.processDataBindings(value); + if (binding != null) { + compiler.getBindingHelper().registerDataBinding(id + "." + name, binding, id + ".set" + StringUtils.capitalize(name) + "(" + binding + ");"); +// compiler.getBindingHelper().registerDataBinding(binding, id + "." + name, id + ".set" + StringUtils.capitalize(name) + "(" + binding + ");"); + return; + } + + String valueCode = TypeManager.getJavaCode(value); + + // add i18n support + if (I18nHelper.isI18nableAttribute(name, compiler)) { + value = valueCode = I18nHelper.addI18nInvocation(id, name, valueCode, compiler); + } + if (name.equals(ATTRIBUTE_ID)) { + // ignore, already handled + } else if (name.equals(ATTRIBUTE_TITLE)) { + tabInfo.setTitle(value); + compiledTabInfo.appendInitializationCode(id + ".setTitle(" + valueCode + ");"); + //compiledTabInfo.appendInitializationCode(id + ".setTitle(" + TypeManager.getJavaCode(value) + ");"); + } else if (name.equals(ATTRIBUTE_TOOL_TIP_TEXT)) { + tabInfo.setToolTipText(value); + compiledTabInfo.appendInitializationCode(id + ".setToolTipText(" + valueCode + ");"); + //compiledTabInfo.appendInitializationCode(id + ".setToolTipText(" + TypeManager.getJavaCode(value) + ");"); + } else if (name.equals(ATTRIBUTE_ICON)) { + Icon icon = (Icon) TypeManager.convertFromString(value, Icon.class); + tabInfo.setIcon(icon); + compiledTabInfo.appendInitializationCode(id + ".setIcon(" + TypeManager.getJavaCode(icon) + ");"); + } else if (name.equals(ATTRIBUTE_ENABLED)) { + boolean enabled = (Boolean) TypeManager.convertFromString(value, Boolean.class); + tabInfo.setEnabled(enabled); + compiledTabInfo.appendInitializationCode(id + ".setEnabled(" + enabled + ");"); + } else if (name.equals(ATTRIBUTE_DISABLED_ICON)) { + Icon disabledIcon = (Icon) TypeManager.convertFromString(value, Icon.class); + tabInfo.setDisabledIcon(disabledIcon); + compiledTabInfo.appendInitializationCode(id + ".setDisabledIcon(" + TypeManager.getJavaCode(disabledIcon) + ");"); + } else if (name.equals(ATTRIBUTE_MNEMONIC)) { + int mnemonic = (Character) TypeManager.convertFromString(value, char.class); + tabInfo.setMnemonic(mnemonic); + compiledTabInfo.appendInitializationCode(id + ".setMnemonic(" + mnemonic + ");"); + } else if (name.equals(ATTRIBUTE_DISPLAYED_MNEMONIC_INDEX)) { + int displayedMnemonicIndex = (Integer) TypeManager.convertFromString(value, int.class); + tabInfo.setDisplayedMnemonicIndex(displayedMnemonicIndex); + compiledTabInfo.appendInitializationCode(id + ".setDisplayedMnemonicIndex(" + displayedMnemonicIndex + ");"); + } else if (name.equals(ATTRIBUTE_FOREGROUND)) { + Color foreground = (Color) TypeManager.convertFromString(value, Color.class); + tabInfo.setForeground(foreground); + compiledTabInfo.appendInitializationCode(id + ".setForeground(" + TypeManager.getJavaCode(foreground) + ");"); + } else if (name.equals(ATTRIBUTE_BACKGROUND)) { + Color background = (Color) TypeManager.convertFromString(value, Color.class); + tabInfo.setBackground(background); + compiledTabInfo.appendInitializationCode(id + ".setBackground(" + TypeManager.getJavaCode(background) + ");"); + } else if (name.equals(ATTRIBUTE_TAB_COMPONENT)) { + tabInfo.setTabComponentStr(TypeManager.getJavaCode(value)); + compiledTabInfo.appendInitializationCode(id + ".setTabComponent(" + TypeManager.getJavaCode(value) + ");"); + } else { + compiler.reportError("The <tab> tag does not support the attribute '" + name + "'"); + } + } + + public void setAttributes(CompiledObject compiledTabInfo, JTabbedPaneHandler.CompiledTabbedPane tabs, Element tag, JAXXCompiler compiler) throws CompilerException { + NamedNodeMap children = tag.getAttributes(); + for (int i = 0; i < children.getLength(); i++) { + Attr attribute = (Attr) children.item(i); + String name = attribute.getName(); + String value = attribute.getValue(); + if (!name.startsWith("xmlns") && !JAXXCompiler.JAXX_INTERNAL_NAMESPACE.equals(attribute.getNamespaceURI())) { + setAttribute(compiledTabInfo, tabs, name, value, compiler); + } + } + } + + 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); + } 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() + "')"); + } + } + } + } + + protected void compileChildTagFirstPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileFirstPass(tag); + } + + 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() + "')"); + } + } + } + } + + protected void compileChildTagSecondPass(Element tag, JAXXCompiler compiler) throws CompilerException, IOException { + compiler.compileSecondPass(tag); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TableHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TableHandler.java new file mode 100644 index 0000000..e5ac432 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/swing/TableHandler.java @@ -0,0 +1,178 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.swing; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.UnsupportedAttributeException; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultComponentHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.swing.Table; + +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.util.ArrayList; +import java.util.List; + +public class TableHandler extends DefaultComponentHandler { + + public static final Insets DEFAULT_INSETS = new Insets(3, 3, 3, 3); + + public TableHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass(getClass(), + beanClass, + Table.class); + } + + @Override + public void setAttribute(CompiledObject object, + String propertyName, + String stringValue, + boolean inline, + JAXXCompiler compiler) throws CompilerException { + try { + if (object instanceof CompiledTable) { + CellHandler.setAttribute( + ((CompiledTable) object).getTableConstraints(), + propertyName, + stringValue + ); + } else { + super.setAttribute(object, + propertyName, + stringValue, + inline, + compiler); + } + } catch (UnsupportedAttributeException e) { + super.setAttribute(object, + propertyName, + stringValue, + inline, + compiler + ); + } + } + + class CompiledTable extends CompiledObject { + + private List<Integer> rowSpans = new ArrayList<Integer>(); + + private GridBagConstraints tableConstraints; + + private GridBagConstraints rowConstraints; + + private GridBagConstraints cellConstraints; + + private boolean emptyCell; + + public CompiledTable(String id, + ClassDescriptor objectClass, + JAXXCompiler compiler) throws CompilerException { + super(id, objectClass, compiler); + tableConstraints = new GridBagConstraints(); + tableConstraints.gridx = -1; + tableConstraints.gridy = -1; + tableConstraints.insets = DEFAULT_INSETS; + } + + @Override + public void addChild(CompiledObject child, + String constraints, + JAXXCompiler compiler) throws CompilerException { + if (constraints != null) { + compiler.reportError("Table does not accept constraints"); + } + GridBagConstraints c = getCellConstraints(); + if (c == null) { + compiler.reportError("Table tag may only contain row tags"); + return; + } + if (!emptyCell) { + compiler.reportError( + "Table cells may only have one child component"); + } + while (rowSpans.size() < c.gridx + c.gridwidth) { + rowSpans.add(null); + } + for (int x = c.gridx; x < c.gridx + c.gridwidth; x++) { + rowSpans.set(x, c.gridheight); + } + + super.addChild(child, TypeManager.getJavaCode(c), compiler); + + emptyCell = false; + + compiler.addImport(GridBagConstraints.class); + compiler.addImport(Insets.class); + } + + public GridBagConstraints getTableConstraints() { + return tableConstraints; + } + + public GridBagConstraints getRowConstraints() { + return rowConstraints; + } + + public GridBagConstraints getCellConstraints() { + return cellConstraints; + } + + public void newRow() { + tableConstraints.gridy++; + tableConstraints.gridx = -1; + rowConstraints = (GridBagConstraints) tableConstraints.clone(); + + for (int x = 0; x < rowSpans.size(); x++) { + int rowSpan = rowSpans.get(x); + if (rowSpan > 0) { + rowSpans.set(x, rowSpan - 1); + } + } + } + + public void newCell() { + emptyCell = true; + rowConstraints.gridx++; + while (rowConstraints.gridx < rowSpans.size() && + rowSpans.get(rowConstraints.gridx) > 0) { + rowConstraints.gridx++; + } + cellConstraints = (GridBagConstraints) rowConstraints.clone(); + } + } + + @Override + public CompiledObject createCompiledObject(String id, + JAXXCompiler compiler) throws CompilerException { + return new CompiledTable(id, getBeanClass(), compiler); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/BeanValidatorHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/BeanValidatorHandler.java new file mode 100644 index 0000000..86c508b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/BeanValidatorHandler.java @@ -0,0 +1,1002 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.validator; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.beans.JAXXBeanInfo; +import jaxx.compiler.beans.JAXXPropertyDescriptor; +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.java.JavaField; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.DefaultObjectHandler; +import jaxx.compiler.types.TypeManager; +import jaxx.runtime.JAXXValidator; +import jaxx.runtime.validator.swing.SwingValidator; +import jaxx.runtime.validator.swing.SwingValidatorUtil; +import jaxx.runtime.validator.swing.meta.ValidatorField; +import jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +public class BeanValidatorHandler extends DefaultObjectHandler { + + public static final String TAG = "BeanValidator"; + + 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 = "errorListModel"; + + public static final String ERROR_TABLE_MODEL_DEFAULT = "errorTableModel"; + + 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_ATTRIBUTE = "context"; + + /** + * @deprecated since 2.4.1, now use the {@link #CONTEXT_ATTRIBUTE}. + */ + @Deprecated + public static final String CONTEXT_NAME_ATTRIBUTE = "contextName"; + //public static final String SCOPE_ATTRIBUTE = "scope"; + + public static final String PARENT_VALIDATOR_ATTRIBUTE = "parentValidator"; + + /** Logger */ + static Log log = LogFactory.getLog(BeanValidatorHandler.class); + + protected static Map<JAXXCompiler, List<CompiledBeanValidator>> validators = + new HashMap<JAXXCompiler, List<CompiledBeanValidator>>(); + + protected static Map<JAXXCompiler, List<String>> validatedComponents = + new HashMap<JAXXCompiler, List<String>>(); + + public BeanValidatorHandler(ClassDescriptor beanClass) { + super(beanClass); + ClassDescriptorHelper.checkSupportClass( + getClass(), + beanClass, + SwingValidator.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 (log.isDebugEnabled()) { + log.debug(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.addParentValidator(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 (log.isDebugEnabled()) { + log.debug(propertyName + " : " + stringValue + " for " + object); + } + if (CONTEXT_NAME_ATTRIBUTE.equals(propertyName)) { + if (stringValue != null && !stringValue.trim().isEmpty()) { + // usage of a deprecated contextName, says it to user... + compiler.reportWarning("You are using a validator attribute named 'contextName' which is deprecated, prefer use now a context attribute."); + } + } + // 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 tchemit <chemit@codelutin.com> + */ + public static class CompiledBeanValidator extends CompiledObject { + + protected Map<String, String> fields; + + protected Map<String, String> excludeFields; + + protected String bean; + + protected String beanClass; + + protected String context; + + 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 String parentValidator; + + public CompiledBeanValidator(String id, + ClassDescriptor objectClass, + JAXXCompiler compiler) { + //TC-20090524 Use the real class descriptor, not the one by default, + //TC-20090524 otherwise can not override the validator class while generation + //super(id, objectClass, compiler); + super(id, getDescriptor(objectClass, compiler), compiler); + fields = new TreeMap<String, String>(); + excludeFields = new TreeMap<String, String>(); + if (log.isDebugEnabled()) { + log.debug("validator objectClass " + getObjectClass()); + } + } + + protected static ClassDescriptor getDescriptor( + ClassDescriptor objectClass, + JAXXCompiler compiler) { + Class<?> validatorClass = SwingValidator.class; +// compiler.getConfiguration().getValidatorClass(); + ClassDescriptor result = + ClassDescriptorHelper.getClassDescriptor(validatorClass); + return result; + } + + 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()) { + context= value.trim(); + } + + return; + } + + if (CONTEXT_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + context = 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 (PARENT_VALIDATOR_ATTRIBUTE.equals(property)) { + if (value != null && !value.trim().isEmpty()) { + parentValidator = value.trim(); + } + return; + } + + throw new CompilerException("property " + property + + " is not allowed on object " + this); + } + + 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 getContext() { + return context; + } + + public String getParentValidator() { + return parentValidator; + } + + public JAXXBeanInfo getBeanDescriptor(JAXXCompiler compiler) { + if (beanDescriptor == null && foundBean()) { + + String beanClassName = null; + try { + //TC-20090111 beanClass is mandatory + // 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 = + ClassDescriptorHelper.getClassDescriptor(beanClass); + beanDescriptor = DefaultObjectHandler.getJAXXBeanInfo( + beanClassDescriptor); + + } catch (Exception 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 !(beanClass == null || beanClass.isEmpty()); + } + + protected boolean addUiClass(BeanValidatorHandler handler, + JAXXCompiler compiler) { + boolean withError = false; + if (uiClass == null && + compiler.getConfiguration().getDefaultErrorUI() != null) { + uiClass = compiler.getConfiguration().getDefaultErrorUI().getName(); + } + if (uiClass != null) { + try { + ClassDescriptor uiClazz = + ClassDescriptorHelper.getClassDescriptor(uiClass); + if (!ClassDescriptorHelper.getClassDescriptor(AbstractBeanValidatorUI.class).isAssignableFrom(uiClazz)) { + compiler.reportError( + "attribute 'ui' :'" + uiClass + + "' is not assignable from class " + + AbstractBeanValidatorUI.class + ); + withError = true; + } else { + String prefix = compiler.getImportedType(uiClazz.getName()); + String code = handler.getSetPropertyCode( + getJavaCode(), + UI_CLASS_ATTRIBUTE, + prefix + ".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 addParentValidator(Element tag, + BeanValidatorHandler handler, + JAXXCompiler compiler) { + if (parentValidator != null) { + String initializer; + if (parentValidator.startsWith("{") && + parentValidator.endsWith("}")) { + + // todo : should be able to bind + initializer = parentValidator.substring( + 1, + parentValidator.length() - 1 + ); + + } else { + // the attribute referes an existing widget + if (!compiler.checkReference( + tag, + parentValidator, + true, + PARENT_VALIDATOR_ATTRIBUTE)) { + // parentValidator is not defined + return true; + } + initializer = parentValidator; + } + String code = handler.getSetPropertyCode( + getJavaCode(), + PARENT_VALIDATOR_ATTRIBUTE, + initializer, + 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 prefix = compiler.getImportedType(SwingValidatorUtil.class); + + String code = prefix + + ".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 prefix = compiler.getImportedType(SwingValidatorUtil.class); + + String code = prefix + + ".registerErrorTableMouseListener(" + errorTable + + ");"; + appendAdditionCode(code); + + return false; + } + + protected boolean addBean(Element tag, + BeanValidatorHandler handler, + JAXXCompiler compiler) { + + if (beanClass == null || beanClass.isEmpty()) { + // try to guest beanClass from bean attribute + if (bean != null && !bean.isEmpty()) { + beanClass = compiler.getSymbolTable().getClassTagIds().get(bean); + if (beanClass == null) { + compiler.reportError( + "could not find class of the bean '" + bean + + "', and no beanClass was setted"); + return true; + } + } + } + if (beanClass == null) { + compiler.reportError( + "tag '" + tag + "' requires a 'beanClass' attribute, " + + "and could not guest it from 'bean' attribute " + + "(no bean attribute setted...)"); + return true; + } + + JAXXBeanInfo beanInfo = getBeanDescriptor(compiler); + if (beanInfo == null) { + compiler.reportError( + tag, + "could not find descriptor of class " + beanClass + ); + return true; + } + + String beanInitializer = null; + if (bean != null) { + + if (bean.startsWith("{") && bean.endsWith("}")) { + + String labelBinding = + DataBindingHelper.processDataBindings(bean); + if (labelBinding != null) { + compiler.getBindingHelper().registerDataBinding( + getId() + ".bean", + labelBinding, + getId() + ".setBean(" + labelBinding + ");" + ); + } +// // 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 (isBeanUsedByValidator(compiler, 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); + } + + String beanClassName = beanInfo.getJAXXBeanDescriptor().getClassDescriptor().getName(); + String type = compiler.getImportedType(beanClassName); + // contextName must be in constructor to able to init validator with his correct contextName + String constructorParams = type + ".class, " + + TypeManager.getJavaCode(context); +// setConstructorParams(constructorParams); + String prefix = compiler.getImportedType(SwingValidatorUtil.class); + setInitializer( + prefix + ".newValidator(" + constructorParams + ")" + ); + + // add generic type to validator + setGenericTypes(beanClassName); + + if (getAutoField()) { + registerAutoFieldBean(tag, compiler, beanInfo); + } + + if (getBeanDescriptor(compiler) != null) { + + // add fieldrepresentation invocations +// addFieldRepresentations(tag, compiler); + + // register the validator in compiler + registerValidator(compiler, this); + + } + + return false; + } + + private void registerValidator( + JAXXCompiler compiler, + CompiledBeanValidator compiledBeanValidator) { + List<CompiledBeanValidator> vals = validators.get(compiler); + if (vals == null) { + vals = new ArrayList<CompiledBeanValidator>(); + validators.put(compiler, vals); + } + vals.add(compiledBeanValidator); + List<String> ids = validatedComponents.get(compiler); + if (ids == null) { + ids = new ArrayList<String>(); + validatedComponents.put(compiler, ids); + } + ids.addAll(compiledBeanValidator.getFields().values()); + } + + /** + * Register in buffer all field representation to init (and to record in method {@link JAXXValidator#registerValidatorFields()} + * + * @param compiler the compiler used + * @param javaFile generated file + * @param buffer the buffer where to add code + * @since 2.2.1 + */ + public void addFieldRepresentations(JAXXCompiler compiler, + JavaFile javaFile, + StringBuilder buffer) { + 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; + } + String validatorId = TypeManager.getJavaCode(getId()); + String keyCode = TypeManager.getJavaCode(propertyName); + String editorCode = TypeManager.getJavaCode(component); + JavaField editor = javaFile.getField(component); + String annotation = ValidatorField.class.getSimpleName() + + "( validatorId = " + validatorId + "," + + " propertyName = " + keyCode + "," + + " editorName = " + editorCode + "" + + ")"; + editor.addAnnotation(annotation); + +// if (!compiler.checkReference(tag, component, true, null)) { +// // editor component not find on ui +// continue; +// } + +// buffer.append(getJavaCode()); +// buffer.append(".setFieldRepresentation("); +// buffer.append(keyCode); +// buffer.append(", "); +// buffer.append(component); +// buffer.append(");\n"); + } + } + + protected void registerAutoFieldBean(Element tag, + JAXXCompiler compiler, + JAXXBeanInfo beanInfo) { + for (JAXXPropertyDescriptor beanProperty : + beanInfo.getJAXXPropertyDescriptors()) { + String descriptionName = beanProperty.getName(); + if (log.isDebugEnabled()) { + log.debug("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 (log.isDebugEnabled()) { + log.debug("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 (log.isDebugEnabled()) { + log.debug("add excludeField <" + id + ":" + component + ">"); + } + excludeFields.put(id, component); + } + } + + public 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; + } + } + + /** + * Test if a given bean is attached to a validator. + * + * @param compiler current compiler to use + * @param beanId the bean to test + * @return <code>true</code> if the given bean is attached to a validator, + * <code>false</code> otherwise + */ + public static boolean isBeanUsedByValidator(JAXXCompiler compiler, + String beanId) { + List<CompiledBeanValidator> beanValidatorList = validators.get(compiler); + if (beanValidatorList != null) { + for (CompiledBeanValidator validator : beanValidatorList) { + if (beanId.equals(validator.getBean())) { + return true; + } + } + } + return false; + } + + /** + * @param compiler compiler to use + * @return <code>true</code> if some validators were detected, + * <code>false</code> otherwise + */ + public static boolean hasValidator(JAXXCompiler compiler) { + List<CompiledBeanValidator> beanValidatorList = + validators.get(compiler); + return beanValidatorList != null && !beanValidatorList.isEmpty(); + } + + /** + * Test if a given CompiledObject is attached to a validator. + * + * @param compiler compiler to use + * @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 static boolean isComponentUsedByValidator(JAXXCompiler compiler, + String componentId) { + List<String> ids = validatedComponents.get(compiler); + return ids != null && ids.contains(componentId); + } + + public static List<CompiledBeanValidator> getValidators(JAXXCompiler compiler) { + return validators.get(compiler); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java new file mode 100644 index 0000000..617b823 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/ExcludeFieldValidatorHandler.java @@ -0,0 +1,125 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.validator; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import jaxx.runtime.validator.swing.SwingValidator; +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"; + /** Logger */ + static private Log log = LogFactory.getLog(ExcludeFieldValidatorHandler.class); + + @Override + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.info(tag); + } + //todo check there is no child + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.debug(tag); + } + + ClassDescriptor descriptor = + ClassDescriptorHelper.getClassDescriptor(SwingValidator.class); + if (!descriptor.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); + } + + + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/FieldValidatorHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/FieldValidatorHandler.java new file mode 100644 index 0000000..4b3138b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tags/validator/FieldValidatorHandler.java @@ -0,0 +1,155 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags.validator; + +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tags.TagHandler; +import jaxx.compiler.tags.validator.BeanValidatorHandler.CompiledBeanValidator; +import jaxx.runtime.validator.swing.SwingValidator; +import org.apache.commons.lang3.StringUtils; +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"; + + /** Logger */ + static private Log log = LogFactory.getLog(FieldValidatorHandler.class); + + public void compileFirstPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.debug(tag); + } + //todo check there is no child + } + + @Override + public void compileSecondPass(Element tag, + JAXXCompiler compiler) throws CompilerException, IOException { + if (compiler.getConfiguration().isVerbose()) { + log.debug(tag); + } + + ClassDescriptor descriptor = + ClassDescriptorHelper.getClassDescriptor(SwingValidator.class); + if (!descriptor.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); + if (StringUtils.isEmpty(name)) { + compiler.reportError(TAG + " tag requires a " + NAME_ATTRIBUTE + + " attribute"); + return; + } + name = name.trim(); + + String component = tag.getAttribute(COMPONENT_ATTRIBUTE); + if (StringUtils.isEmpty(component)) { + // 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(); + + boolean complexType = false; + if (component.startsWith("{") && component.endsWith("}")) { + + complexType = true; + + // means a complex reference (says a java Code in facts) + component = compiler.preprocessScript( + component.substring(1, component.length() - 1)); + } + + if (log.isDebugEnabled()) { + log.debug("Check '" + component + "' reference"); + } + + // 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 (complexType) { + String binding = DataBindingHelper.processDataBindings(component); + boolean withBinding = binding != null; + + if (log.isDebugEnabled()) { + log.debug("apply data binding on [" + component + "] : " + withBinding); + } + + // this means reference is ok, can safely add field + + // add a field + info.registerField(name, component, compiler); + return; + } + + // simple reference, check it directly on compiler + + // 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); + } + + + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java new file mode 100644 index 0000000..3114bc1 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileFirstPassTask.java @@ -0,0 +1,126 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.CompilerConfiguration; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; + +/** + * First compile pass task to validate jaxx files and look after dependencies. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class CompileFirstPassTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(CompileFirstPassTask.class); + + /** Task name */ + public static final String TASK_NAME = "CompileFirstPass"; + + public CompileFirstPassTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + + JAXXCompilerFile[] undone = engine.getFilesToCompile(); + + while (undone.length > 0) { + + // start a new round of compilation + + for (JAXXCompilerFile jaxxFile : undone) { + + boolean successForFile = treateFile(engine, jaxxFile); + + if (!successForFile) { + + // something is wrong... + success = false; + } + } + + // prepare next round + undone = engine.getFilesToCompile(); + } + return success; + } + + protected boolean treateFile(JAXXEngine engine, + JAXXCompilerFile jaxxFile) throws Exception { + + boolean isVerbose = engine.isVerbose(); + + if (isVerbose) { + log.info("start " + jaxxFile.getClassName()); + } + + boolean success = true; + + CompilerConfiguration configuration = engine.getConfiguration(); + + JAXXCompiler compiler = engine.newCompiler(jaxxFile); + addStartProfileTime(engine, compiler); + + compiler.compileFirstPass(); + + if (configuration.isAutoImportCss() && !compiler.isIdentCssFound()) { + + // check if we can add ident css file + + File cssFile = jaxxFile.getCssFile(); + + if (log.isDebugEnabled()) { + log.debug("test ident css file " + cssFile + " : " + isVerbose); + } + if (cssFile.exists()) { + + compiler.setIdentCssFound(true); + + if (isVerbose) { + log.info("Auto import of css " + cssFile); + } + // ok add it + compiler.registerStyleSheetFile(cssFile); + } + } + addEndProfileTime(engine, compiler); + + if (compiler.isFailed()) { + success = false; + } + return success; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java new file mode 100644 index 0000000..fe30502 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/CompileSecondPassTask.java @@ -0,0 +1,95 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Task to execute the Second round of compile. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class CompileSecondPassTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = + LogFactory.getLog(CompileSecondPassTask.class); + + /** Task name */ + public static final String TASK_NAME = "CompileSecondPass"; + + public CompileSecondPassTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + boolean isVerbose = engine.isVerbose(); + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + + String className = jaxxFile.getClassName(); + if (isVerbose) { + log.info("start " + className); + } + + JAXXCompiler compiler = jaxxFile.getCompiler(); + + addStartProfileTime(engine, compiler); + if (log.isDebugEnabled()) { + log.debug("runInitializers for " + className); + } + if (!compiler.isFailed()) { + compiler.runInitializers(); + } + if (log.isDebugEnabled()) { + log.debug("compile second pass for " + className); + } + compiler.compileSecondPass(); + addEndProfileTime(engine, compiler); + if (log.isDebugEnabled()) { + log.debug("done with result [" + !compiler.isFailed() + + "] for " + className); + } + if (compiler.isFailed()) { + success = false; + } + } + + return success; + } + +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java new file mode 100644 index 0000000..922219c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/FinalizeTask.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Task to execute after stylesheet tasks and juste before generation task. + * <p/> + * This task will finialize all compilers. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class FinalizeTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(FinalizeTask.class); + + /** Task name */ + public static final String TASK_NAME = "Finalize"; + + public FinalizeTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + boolean isVerbose = engine.getConfiguration().isVerbose(); + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + + if (isVerbose) { + log.info("start " + jaxxFile.getClassName()); + } + JAXXCompiler compiler = jaxxFile.getCompiler(); + addStartProfileTime(engine, compiler); + compiler.finalizeCompiler(); + addEndProfileTime(engine, compiler); + if (compiler.isFailed()) { + success = false; + } + } + return success; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateConstructorsTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateConstructorsTask.java new file mode 100644 index 0000000..9a607f2 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateConstructorsTask.java @@ -0,0 +1,511 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.CompiledObject; +import jaxx.compiler.CompilerException; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import jaxx.compiler.finalizers.DefaultFinalizer; +import jaxx.compiler.java.JavaArgument; +import jaxx.compiler.java.JavaConstructor; +import jaxx.compiler.java.JavaElementFactory; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.MethodDescriptor; +import jaxx.compiler.tags.TagManager; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static java.lang.reflect.Modifier.PUBLIC; + +/** + * Task to execute just after finalize task to create all constructors for any + * compiler. + * <p/> + * In fact, we can not compute constructor in one time since some compiler may + * need of the constructors of previous compiler... + * <p/> + * This task will compute all constructors to generate. + * + * @author tchemit <chemit@codelutin.com> + * @see JavaConstructor + * @since 2.4 + */ +public class GenerateConstructorsTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(GenerateConstructorsTask.class); + + /** Task name */ + public static final String TASK_NAME = "PostFinalize"; + + private static final String PARAMETER_NAME_PARENT_CONTEXT = "parentContext"; + + public GenerateConstructorsTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + boolean isVerbose = engine.getConfiguration().isVerbose(); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + // to contains all compilers + List<JAXXCompiler> compilers = new ArrayList<JAXXCompiler>(); + for (JAXXCompilerFile jaxxFile : files) { + compilers.add(jaxxFile.getCompiler()); + } + + int round = 0; + + while (!compilers.isEmpty()) { + + if (isVerbose) { + log.info("Round " + round++ + ", still " + + compilers.size() + " compilers to treat."); + } + + // launch a round since there is still some compiler to treat + Iterator<JAXXCompiler> itr = compilers.iterator(); + while (itr.hasNext()) { + JAXXCompiler compiler = itr.next(); + JavaFile javaFile = compiler.getJavaFile(); + + boolean isJAXXObject = javaFile.isSuperclassIsJAXXObject(); + if (!isJAXXObject) { + + // can directly compute constructors + + if (log.isDebugEnabled()) { + log.debug("Compute constructor from non super " + + "jaxx object file " + javaFile.getName()); + } + + // get the constructors of the parent class + + addConstructorsForNoneSuperClassJaxx(engine, compiler); + itr.remove(); + continue; + } + + // compiler inheritate from a jaxx object + CompiledObject rootObject = compiler.getRootObject(); + ClassDescriptor parentClassDescriptor = rootObject.getObjectClass(); + + if (parentClassDescriptor.getResolverType() + != ClassDescriptorHelper.ResolverType.JAXX_FILE) { + + // the parent was not generated by this engine; we can safely + // use it + + if (log.isDebugEnabled()) { + log.debug("Compute constructor from outside super " + + "jaxx object file " + javaFile.getName()); + } + addConstructorsForSuperClassJaxx(engine, compiler, null); + itr.remove(); + continue; + + } + + JAXXCompiler parentCompiler = engine.getJAXXCompiler( + JAXXCompiler.getCanonicalName(parentClassDescriptor)); + + + if (!compilers.contains(parentCompiler)) { + + // parent was generated by this engine and was laready + // treated, can now safely deal this the given compiler + + if (log.isDebugEnabled()) { + log.debug("Compute constructor from inside super " + + "jaxx object file " + javaFile.getName()); + } + + addConstructorsForSuperClassJaxx(engine, compiler, parentCompiler); + itr.remove(); + continue; + } + + // can not treate at the moment... + if (log.isDebugEnabled()) { + log.debug("Can not compute constructors for " + + compiler.getRootObject().getId() + + " waits fro his parent to be treated..."); + } + } + } + return success; + } + + /** + * To add constructor on the given {@code compiler}, knowing that the super + * class of it is not a jaxx class. + * <p/> + * In this mode, we takes all the constructors of the parent (if parent has + * some!) and for each of them add the simple one and another one with + * first parameter a {@link JAXXContext}. + * + * @param engine the current engine which compiled compiler + * @param compiler the current compiler to treat + * @throws ClassNotFoundException if a class could not be found (when wanted to have extact type for constructor parameters) + * @throws IllegalStateException if given {@code compiler has a super JAXX class}. + */ + protected void addConstructorsForNoneSuperClassJaxx(JAXXEngine engine, + JAXXCompiler compiler) throws ClassNotFoundException, IllegalStateException { + + JavaFile javaFile = compiler.getJavaFile(); + + if (javaFile.isSuperclassIsJAXXObject()) { + throw new IllegalStateException( + "This method does not accept compiler that " + + "inheritates from a jaxx file."); + } + + String className = javaFile.getSimpleName(); + + if (engine.isVerbose()) { + log.info("start " + javaFile.getName()); + } + + addStartProfileTime(engine, compiler); + + // get already registred constructors : need to keep the list of parameters + // not to generate a constructor with same prototype twice. + List<List<String>> prototypes = getDeclaredConstructorPrototypes(compiler, javaFile); + + MethodDescriptor[] constructorDescriptors = + compiler.getRootObject().getObjectClass().getConstructorDescriptors(); + + List<String> constructorTypes; + boolean canAddConstructor; + + if (constructorDescriptors == null || constructorDescriptors.length == 0) { + + // no constructors (use only a default constructor) + + constructorTypes = getConstructorTypes(); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructor(compiler, className, constructorTypes); + } + + constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructorWithInitialContext(compiler, className, constructorTypes, false); + } + } else { + for (MethodDescriptor constructorDescriptor : constructorDescriptors) { + + constructorTypes = getConstructorTypes(constructorDescriptor.getParameterTypes()); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructor(compiler, className, constructorTypes); + } + + constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructorWithInitialContext(compiler, className, constructorTypes, false); + } + } + } + + addEndProfileTime(engine, compiler); + } + + /** + * To add constructor on the given {@code compiler}, knowing that the super + * class of it is a jaxx class. + * <p/> + * In this mode, we takes all the constructors of the parent (if parent has + * some!) and for each of them add the simple one and another one with + * first parameter a {@link JAXXContext}. + * + * @param engine the current engine which compiled compiler + * @param compiler the current compiler to treat + * @param parentCompiler the compiler of the super class (can be + * {@code null} if super class was not generated by + * the given engine). + * @throws ClassNotFoundException if a class could not be found (when wanted to have extact type for constructor parameters) + * @throws IllegalStateException if given {@code compiler has not a super JAXX class}. + */ + protected void addConstructorsForSuperClassJaxx(JAXXEngine engine, + JAXXCompiler compiler, + JAXXCompiler parentCompiler) throws ClassNotFoundException, IllegalStateException { + + JavaFile javaFile = compiler.getJavaFile(); + + if (!javaFile.isSuperclassIsJAXXObject()) { + throw new IllegalStateException( + "This method does not accept compiler that " + + "inheritates not from a jaxx file."); + } + + String className = javaFile.getSimpleName(); + + if (engine.isVerbose()) { + log.info("start " + javaFile.getName()); + } + + addStartProfileTime(engine, compiler); + + // get already registred constructors : need to keep the list of parameters + // not to generate a constructor with same prototype twice. + List<List<String>> prototypes = getDeclaredConstructorPrototypes(compiler, javaFile); + + MethodDescriptor[] constructorDescriptors; + + if (parentCompiler == null) { + + // the parent was not generated by this engine, this means that is + // class descriptor can be used to obtain constructors + constructorDescriptors = compiler.getRootObject().getObjectClass().getConstructorDescriptors(); + } else { + + // the parent was generated by this engine, can not trust the class + // descriptor at the moment, so just seek in his java file for + // already generated constructor + List<JavaConstructor> constructors = parentCompiler.getJavaFile().getConstructors(); + constructorDescriptors = new MethodDescriptor[constructors.size()]; + + int i = 0; + for (JavaConstructor constructor : constructors) { + String[] parameters = new String[constructor.getArguments().length]; + int j = 0; + for (JavaArgument argument : constructor.getArguments()) { + String type = argument.getType(); + parameters[j++] = type; + } + constructorDescriptors[i++] = new MethodDescriptor( + null, + constructor.getModifiers(), + null, + parameters, + compiler.getClassLoader() + ); + } + } + + // dealing with a jsuper class JAXX we are sure to have at least two constructors : + // a default one + one with just a JAXXContext parameter + + List<String> constructorTypes; + boolean canAddConstructor; + + for (MethodDescriptor constructorDescriptor : constructorDescriptors) { + + ClassDescriptor[] parameterTypes = constructorDescriptor.getParameterTypes(); + + if (parentCompiler == null) { + + // we already have the good type ??? this is dangerous + // because we could miss an import ? must be improved + constructorTypes = new ArrayList<String>(parameterTypes.length); + + for (ClassDescriptor parameterType : parameterTypes) { + constructorTypes.add(parameterType.getName()); + } + } else { + + + constructorTypes = getConstructorTypes(parameterTypes); + } + canAddConstructor = canAddConstructor(prototypes, constructorTypes); + if (canAddConstructor) { + addConstructor(compiler, className, constructorTypes); + } + +// constructorTypes.add(0, JAXXCompiler.getCanonicalName(JAXXContext.class)); +// canAddConstructor = canAddConstructor(prototypes, constructorTypes); +// if (canAddConstructor) { +// addConstructorWithInitialContext(compiler, className, constructorTypes, true); +// } + } + + + addEndProfileTime(engine, compiler); + } + + protected List<List<String>> getDeclaredConstructorPrototypes(JAXXCompiler compiler, + JavaFile javaFile) throws ClassNotFoundException { + List<JavaConstructor> constructors = javaFile.getConstructors(); + List<List<String>> prototypes = new ArrayList<List<String>>(constructors.size()); + for (JavaConstructor constructor : constructors) { + List<String> prototype = new ArrayList<String>(); + for (JavaArgument argument : constructor.getArguments()) { + String type = argument.getType(); + String fqn = TagManager.resolveClassName(type, compiler); + ClassDescriptor classDescriptor = ClassDescriptorHelper.getClassDescriptor(fqn); + String canonicalName = JAXXCompiler.getCanonicalName(classDescriptor); + prototype.add(canonicalName); + } + prototypes.add(prototype); + } + return prototypes; + } + + private boolean canAddConstructor(List<List<String>> prototypes, List<String> constructorTypes) { + return !prototypes.contains(constructorTypes); + } + + private List<String> getConstructorTypes(ClassDescriptor... descriptors) { + List<String> result = new ArrayList<String>(); + // add all parameters from constructor + for (ClassDescriptor descriptor : descriptors) { + String fqn = JAXXCompiler.getCanonicalName(descriptor); + result.add(fqn); + } + return result; + } + + protected void addConstructor(JAXXCompiler compiler, + String className, + List<String> constructorTypes) throws CompilerException { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + JavaArgument[] arguments = new JavaArgument[constructorTypes.size()]; + + if (!constructorTypes.isEmpty()) { + + // constructeur avec des paramètres + code.append(" super("); + int i = 0; + for (String constructorType : constructorTypes) { + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + if (i > 0) { + code.append(" ,"); + } + code.append(argument.getName()); + i++; + } + + code.append(");").append(eol); + } + code.append(DefaultFinalizer.METHOD_NAME_$INITIALIZE + "();"); + code.append(eol); + JavaConstructor constructor = JavaElementFactory.newConstructor(PUBLIC, + className, + code.toString(), + arguments + ); + compiler.getJavaFile().addConstructor(constructor); + } + + protected void addConstructorWithInitialContext(JAXXCompiler compiler, + String className, + List<String> constructorTypes, + boolean superclassIsJAXXObject) throws CompilerException { + StringBuilder code = new StringBuilder(); + String eol = JAXXCompiler.getLineSeparator(); + + JavaArgument firstArgument = JavaElementFactory.newArgument( + JAXXContext.class.getName(), + PARAMETER_NAME_PARENT_CONTEXT + ); + JavaArgument[] arguments = new JavaArgument[constructorTypes.size()]; + arguments[0] = firstArgument; + for (int i = 1, max = constructorTypes.size(); i < max; i++) { + String constructorType = constructorTypes.get(i); + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + } + if (superclassIsJAXXObject) { + + // we are sure to have at least the first parameter in the super code + code.append(" super("); + code.append(PARAMETER_NAME_PARENT_CONTEXT); + for (int i = 1, max = constructorTypes.size(); i < max; i++) { + String constructorType = constructorTypes.get(i); + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + code.append(" ,"); + code.append(argument.getName()); + } + code.append(");").append(eol); + } else { + + // only a super class only if more than the parentContext parameter + if (constructorTypes.size() > 1) { + + code.append(" super("); + + for (int i = 1, max = constructorTypes.size(); i < max; i++) { + String constructorType = constructorTypes.get(i); + JavaArgument argument = JavaElementFactory.newArgument( + constructorType, + "param" + i + ); + arguments[i] = argument; + if (i > 1) { + code.append(" ,"); + } + code.append(argument.getName()); + } + code.append(");").append(eol); + } + } + + if (!superclassIsJAXXObject) { + + // call explicitly the init code of the parentContext + String prefix = compiler.getImportedType(JAXXUtil.class); + code.append(prefix); + code.append(".initContext(this, " + PARAMETER_NAME_PARENT_CONTEXT + ");"); + code.append(eol); + } + code.append(DefaultFinalizer.METHOD_NAME_$INITIALIZE + "();"); + code.append(eol); + JavaConstructor constructor = JavaElementFactory.newConstructor(PUBLIC, + className, + code.toString(), + arguments + ); + compiler.getJavaFile().addConstructor(constructor); + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java new file mode 100644 index 0000000..a9d109c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/GenerateTask.java @@ -0,0 +1,208 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import jaxx.compiler.java.JavaArgument; +import jaxx.compiler.java.JavaConstructor; +import jaxx.compiler.java.JavaFile; +import jaxx.compiler.java.JavaFileGenerator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.eugene.java.extension.ImportsManager; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Last task to generate java files. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class GenerateTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(GenerateTask.class); + + /** Task name */ + public static final String TASK_NAME = "Generate"; + + public GenerateTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + boolean success = true; + + boolean verbose = engine.isVerbose(); + + JavaFileGenerator generator = + new JavaFileGenerator(JAXXCompiler.getLineSeparator(), verbose); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + if (verbose) { + log.info("start " + jaxxFile.getClassName()); + } + + JAXXCompiler compiler = jaxxFile.getCompiler(); + + addStartProfileTime(engine, compiler); + + try { + consumeCompiler(compiler, generator); + } finally { + compiler.getJavaFile().clear(); + } + addEndProfileTime(engine, compiler); + if (compiler.isFailed()) { + success = false; + } + } + return success; + } + + public void consumeCompiler(JAXXCompiler compiler, + JavaFileGenerator generator) throws IOException { + + JavaFile javaFile = compiler.getJavaFile(); + + String packageName = javaFile.getPackageName(); + + // optimize imports + List<String> imports = optimizeImports(javaFile, packageName); + + String packageToExclude = packageName + ".*"; + + // push back previous imports + for (String importFQN : javaFile.getImports()) { + if (!packageToExclude.equals(importFQN) && + !imports.contains(importFQN)) { + imports.add(importFQN); + } + } + + // set them to the file to generate + javaFile.setImports(imports); + + + // generate java file + compiler.generate(generator); + } + + public List<String> optimizeImports(JavaFile f, + String packageName) { + + ImportsManager importsManager = f.getImportManager(); + + List<String> result; + + for (String importFQN : f.getImports()) { + if (log.isDebugEnabled()) { + log.debug("Add import : " + importFQN); + } + importsManager.addImport(importFQN); + } + + if (f.getSuperClass() != null) { + String superClass = f.getSuperClass(); + try { + String type = importsManager.getType(superClass); + f.setSuperClass(type); + } catch (Exception e) { + log.error("file [" + f.getName() + + "] Could not determine simple name of super class " + + superClass); + } + } + + List<String> interfaces = f.getInterfaces(); + List<String> interfaces2 = new ArrayList<String>(interfaces.size()); + for (String anInterface : interfaces) { + try { + String newInterface = importsManager.getType(anInterface); + interfaces2.add(newInterface); + } catch (Exception e) { + log.error("file [" + f.getName() + + "] Could not get interface " + anInterface + " :: " + + e.getMessage()); + interfaces2.add(anInterface); + } + } + f.setInterfaces(interfaces2); + + // optimize constructors parameters + optimizeConstructorParameters(f, importsManager); +// importsManager.addImport(JAXXUtil.class); +// if (!f.isSuperclassIsJAXXObject() || needSwingUtil) { +// +// // while implementing JAXXObject contract we sure need the +// // SwingUtil class +// importsManager.addImport(SwingUtil.class); +// } + result = importsManager.getImports(packageName); + result.remove(packageName + ".*"); + if (log.isDebugEnabled()) { + log.debug("[" + f.getName() + "] Detect " + result.size() + + " imports to add."); + for (String s : result) { + log.debug(" " + s); + } + } + + return result; + } + + protected void optimizeConstructorParameters(JavaFile f, + ImportsManager importsManager) { + + List<JavaConstructor> constructors = f.getConstructors(); + for (JavaConstructor constructor : constructors) { + JavaArgument[] arguments = constructor.getArguments(); + for (JavaArgument argument : arguments) { + String type = argument.getType(); + try { + String simpleType = importsManager.getType(type); + argument.setType(simpleType); + } catch (Exception e) { + log.error("file [" + f.getName() + + "] Could not get simple type of constructor paramter " + type + " :: " + + e.getMessage()); + } + + } + } + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java new file mode 100644 index 0000000..d9169dd --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/InitTask.java @@ -0,0 +1,86 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.CompilerConfiguration; +import jaxx.compiler.JAXXEngine; +import jaxx.compiler.JAXXFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * The init task to be launched first. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class InitTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(InitTask.class); + + /** Task name */ + public static final String TASK_NAME = "Init"; + + public InitTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + + CompilerConfiguration configuration = engine.getConfiguration(); + + // check initializers + if (configuration.getInitializers() == null) { + throw new NullPointerException( + "no initializers found in configuration."); + } + + // check decorators + if (configuration.getDecorators() == null) { + + throw new NullPointerException( + "no decorators found in configuration."); + } + + // check finalizers + if (configuration.getFinalizers() == null) { + + throw new NullPointerException( + "no finalizers found in configuration."); + } + + if (configuration.isVerbose()) { + log.info("Will init " + JAXXFactory.class.getName()); + } + JAXXFactory.initFactory(); + + engine.clearReports(); + + return success; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java new file mode 100644 index 0000000..35d93d6 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/JAXXEngineTask.java @@ -0,0 +1,86 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; + +/** + * Base class to implement a task to be launched by a {@link JAXXEngine}. + * <p/> + * The {@link #perform(JAXXEngine)} method contains the logic of the task. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public abstract class JAXXEngineTask { + + /** Task name */ + private final String name; + + public JAXXEngineTask(String name) { + this.name = name; + } + + /** + * Performs the task on the given {@code engine}. + * + * @param engine the engine to use + * @return {@code false} if task failed (with no exception), {@code true} otherwise. + * @throws Exception if any error + */ + public abstract boolean perform(JAXXEngine engine) throws Exception; + + public String getName() { + return name; + } + + /** + * Checks the engine does not have any more files to discover. + * + * @param engine the engine to test + * @throws IllegalStateException if there is still some files to discover. + */ + protected void checkAllFilesCompiled(JAXXEngine engine) throws IllegalStateException { + JAXXCompilerFile[] undone = engine.getFilesToCompile(); + + if (undone.length > 0) { + + throw new IllegalStateException("Can not start '" + getName() + "', there is still files to process in '" + CompileFirstPassTask.TASK_NAME); + } + } + + protected void addStartProfileTime(JAXXEngine engine, + JAXXCompiler compiler) { + engine.addProfileTime(compiler, name + "_start"); + } + + + protected void addEndProfileTime(JAXXEngine engine, + JAXXCompiler compiler) { + engine.addProfileTime(compiler, name + "_end"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java new file mode 100644 index 0000000..6f15d70 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/ProfileTask.java @@ -0,0 +1,56 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A task to display result of profile mode + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ProfileTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(ProfileTask.class); + + /** Task name */ + public static final String TASK_NAME = "Profile"; + + public ProfileTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + boolean success = true; + StringBuilder buffer = engine.getProfiler().computeProfileReport(); + log.info(buffer.toString()); + return success; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java new file mode 100644 index 0000000..d8c67ad --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tasks/StyleSheetTask.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.tasks; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Task to apply css stylesheet on objects after second round of compilation. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class StyleSheetTask extends JAXXEngineTask { + + /** Logger */ + private static final Log log = LogFactory.getLog(StyleSheetTask.class); + + /** Task name */ + public static final String TASK_NAME = "StyleSheet"; + + public StyleSheetTask() { + super(TASK_NAME); + } + + @Override + public boolean perform(JAXXEngine engine) throws Exception { + + // check all files are attached to a compiler + checkAllFilesCompiled(engine); + + boolean success = true; + boolean isVerbose = engine.getConfiguration().isVerbose(); + + JAXXCompilerFile[] files = engine.getCompiledFiles(); + + for (JAXXCompilerFile jaxxFile : files) { + String className = jaxxFile.getClassName(); + if (isVerbose) { + log.info("start " + className); + } + + JAXXCompiler compiler = jaxxFile.getCompiler(); + addStartProfileTime(engine, compiler); + compiler.applyStylesheets(); + addEndProfileTime(engine, compiler); + + if (compiler.isFailed()) { + success = false; + } + } + return success; + } + +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/PrintTagInfo.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/PrintTagInfo.java new file mode 100644 index 0000000..673d863 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/PrintTagInfo.java @@ -0,0 +1,145 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools; + +import jaxx.compiler.DefaultCompilerConfiguration; +import jaxx.compiler.JAXXFactory; +import jaxx.compiler.tags.*; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.beans.JAXXPropertyDescriptor; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.MethodDescriptor; +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; + +/** Generates information about a tag for use on the jaxxframework.org web site. */ +public class PrintTagInfo { + /** + * Displays information about the class name in arg[0]. + * + * @param arg command-line arguments + * @throws Exception if an error occurs + */ + public static void main(String[] arg) throws Exception { + if (arg.length < 1) { + throw new IllegalArgumentException("programm needs at least two parameters : the file where to put the result, and at least one fqn class to treate"); + } + String firstarg = arg[0]; + boolean toFile = false; + BufferedWriter w; + if (firstarg.startsWith("file:")) { + w = new BufferedWriter(new FileWriter(firstarg.substring(5))); + toFile = true; + } else { + w = new BufferedWriter(new OutputStreamWriter(System.out)); + } + + try { + JAXXFactory.setConfiguration(new DefaultCompilerConfiguration()); + JAXXFactory.initFactory(); + for (int i = toFile ? 1 : 0; i < arg.length; i++) { + String className = arg[i]; + treateClass(w, className); + } + } finally { + w.flush(); + w.close(); + } + + } + + protected static void treateClass(BufferedWriter w, String className) throws ClassNotFoundException, IOException { + + ClassDescriptor beanClass = ClassDescriptorHelper.getClassDescriptor(className); + DefaultObjectHandler handler = TagManager.getTagHandler(beanClass); + + DefaultObjectHandler superHandler = TagManager.getTagHandler(beanClass.getSuperclass()); + + // dump all bean properties + w.append("Properties in ").append(String.valueOf(beanClass)); + w.newLine(); + JAXXPropertyDescriptor[] properties = handler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); + JAXXPropertyDescriptor[] superProperties = superHandler.getJAXXBeanInfo().getJAXXPropertyDescriptors(); + for (JAXXPropertyDescriptor property : properties) { + if (property.getWriteMethodDescriptor() == null) { + continue; + } + + boolean found = false; + String name = property.getName(); + for (JAXXPropertyDescriptor superProperty : superProperties) { + if (superProperty.getName().equals(name)) { + found = true; + break; + } + } + if (!found) { + if (property.getPropertyType() == null) { + System.err.println(name + " has null type"); + } else { + w.append("{{EquivalentAttribute|"); + w.append(name); + w.append("|"); + w.append(className.replace('.', '/')); + w.append("|set"); + w.append(StringUtils.capitalize(name)); + w.append("|"); + w.append(JAXXCompiler.getCanonicalName(property.getPropertyType())); + w.append("}}"); + w.append("|-"); + w.newLine(); + } + } + } + + w.newLine(); + w.newLine(); + + // dump all bound methods + dumpMethods(w, beanClass, handler); + } + + protected static void dumpMethods(BufferedWriter w, ClassDescriptor beanClass, DefaultObjectHandler handler) throws IOException { + MethodDescriptor[] methods = beanClass.getMethodDescriptors(); + w.append("Bound methods in ").append(String.valueOf(beanClass)); + w.newLine(); + for (MethodDescriptor method : methods) { + try { + if (handler.isMemberBound(method.getName())) { + w.append("* <tt>").append(method.getName()).append("()</tt>"); + w.newLine(); + } + } catch (Throwable e) { + // ignore ? + } + } + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java new file mode 100644 index 0000000..52245ab --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/AbstractContextNode.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractContextNode implements ContextNode { + private List<ContextNode> arguments = new ArrayList<ContextNode>(); + + + @Override + public void addArgument(ContextNode node) { + arguments.add(node); + } + + @Override + public ContextNode[] getArguments() { + return arguments.toArray(new ContextNode[arguments.size()]); + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/CapturedObject.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/CapturedObject.java new file mode 100644 index 0000000..59a4bc2 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/CapturedObject.java @@ -0,0 +1,171 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.tools.jaxxcapture.handlers.ObjectHandler; + +import java.awt.Component; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +public class CapturedObject extends AbstractContextNode { + private String className; + private ObjectHandler handler; + /** Maps children to their constraints. */ + private Map<CapturedObject, ContextNode> children = new LinkedHashMap<CapturedObject, ContextNode>(); + private CapturedObject parent; + private Map<String, String> properties = new LinkedHashMap<String, String>(); + private Map<String, Object> additionalData = new HashMap<String, Object>(); + private StringBuilder innerXML = new StringBuilder(); + private StringBuilder script = new StringBuilder(); + private boolean inlineable = true; + private JAXXCapture capture; + + public CapturedObject(ObjectHandler handler, String className, JAXXCapture capture) { + this.handler = handler; + this.className = className; + this.capture = capture; + } + + + public ObjectHandler getObjectHandler() { + return handler; + } + + + public void addChild(CapturedObject child, ContextNode constraints) { + children.put(child, constraints); + child.setParent(this); + } + + + public CapturedObject[] getChildren() { + return children.keySet().toArray(new CapturedObject[children.size()]); + } + + + public CapturedObject getParent() { + return parent; + } + + + public void setParent(CapturedObject parent) { + this.parent = parent; + } + + + public ContextNode getConstraints(CapturedObject child) { + return children.get(child); + } + + + public String getClassName() { + return className; + } + + + public String getProperty(String key) { + return properties.get(key); + } + + + public void setProperty(String key, String value) { + properties.put(key, value); + } + + + public Map<String, String> getProperties() { + return properties; + } + + + public Object getAdditionalData(String key) { + return additionalData.get(key); + } + + + public void setAdditionalData(String key, Object value) { + additionalData.put(key, value); + } + + + public Map<String, Object> getAdditionalData() { + return additionalData; + } + + + public void setInlineable(boolean inlineable) { + this.inlineable = inlineable; + } + + + public boolean isInlineable() { + try { + return script.length() == 0 && !Component.class.isAssignableFrom(Class.forName(className, true, capture.getClassLoader())) && inlineable; + } + catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + + public void appendInnerXML(String xml) { + if (this.innerXML.length() > 0) { + this.innerXML.append(JAXXCompiler.getLineSeparator()); + } + this.innerXML.append(xml); + } + + + public String getInnerXML() { + return innerXML.toString(); + } + + + public void appendScriptCode(String script) { + if (this.script.length() > 0) { + this.script.append(JAXXCompiler.getLineSeparator()); + } + this.script.append(script); + } + + + public String getScriptCode() { + return script.toString(); + } + + + public String getXML(JAXXCapture capture) { + return getObjectHandler().getXML(this, capture); + } + + @Override + public String toString() { + return "CapturedObject[" + getProperty("id") + ", " + className + "]"; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ContextNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ContextNode.java new file mode 100644 index 0000000..e873522 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ContextNode.java @@ -0,0 +1,33 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +public interface ContextNode { + + void addArgument(ContextNode node); + + ContextNode[] getArguments(); +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java new file mode 100644 index 0000000..5d620dc --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/JAXXCapture.java @@ -0,0 +1,404 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +import jaxx.compiler.ClassMap; +import jaxx.compiler.CompiledObject; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.tools.jaxxcapture.handlers.JTabbedPaneHandler; +import jaxx.compiler.tools.jaxxcapture.handlers.ObjectHandler; +import jaxx.compiler.tools.jaxxcapture.handlers.TableHandler; +import jaxx.compiler.types.TypeManager; +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.SAXException; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JTabbedPane; +import javax.swing.JWindow; +import javax.swing.SwingUtilities; +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.EventQueue; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.beans.XMLEncoder; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +public class JAXXCapture { + + private static ClassMap<Object> objectHandlers = new ClassMap<Object>(); + + static { + //TODO make a serviceLoader mecanism to allow inter-module loading + objectHandlers.put(ClassDescriptorHelper.getClassDescriptor(Object.class), new ObjectHandler()); + objectHandlers.put(ClassDescriptorHelper.getClassDescriptor(JTabbedPane.class), new JTabbedPaneHandler()); + try { + objectHandlers.put(ClassDescriptorHelper.getClassDescriptor("jaxx.runtime.swing.Table"), new TableHandler()); + } catch (ClassNotFoundException e) { + System.err.println(e); + } + } + private Map<String, Object> sourceObjects = new HashMap<String, Object>(); + private Map<String, CapturedObject> capturedObjects = new HashMap<String, CapturedObject>(); + private ClassLoader classLoader; + private int count; + + private static class CaptureEventQueue extends EventQueue { + + private ClassLoader classLoader; + + private CaptureEventQueue(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + public void dispatchEvent(AWTEvent event) { + if (event.getID() == MouseEvent.MOUSE_PRESSED && ((MouseEvent) event).isControlDown()) { + Component target = ((MouseEvent) event).getComponent(); + if (!(target instanceof Window)) { + target = SwingUtilities.getWindowAncestor(target); + } + if (target instanceof JFrame) { + target = ((JFrame) target).getContentPane(); + } else if (target instanceof JDialog) { + target = ((JDialog) target).getContentPane(); + } + if (target instanceof JWindow) { + target = ((JWindow) target).getContentPane(); + } + if (target != null) { + Thread.currentThread().setContextClassLoader(classLoader); + JAXXCapture capture = new JAXXCapture(classLoader); + capture.applyNames(target); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + XMLEncoder encoder = new XMLEncoder(buffer); + encoder.writeObject(target); + encoder.close(); + try { + System.err.println(new String(buffer.toByteArray())); + System.out.println(capture.convertToJAXX(new ByteArrayInputStream(buffer.toByteArray()))); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + super.dispatchEvent(event); + } + } + + private JAXXCapture(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public Map<String, CapturedObject> getCapturedObjects() { + return capturedObjects; + } + + private void applyNames(Component target) { + String name = target.getName(); + if (name == null || sourceObjects.containsKey(name) || !CompiledObject.isValidID(name)) { + do { + name = "Object" + ++count; + } while (sourceObjects.containsKey(name)); + } + target.setName(name); + assert !sourceObjects.containsKey(name) : "ID " + name + " is already registered"; + sourceObjects.put(name, target); + + if (target instanceof Container) { + Container container = (Container) target; + for (int i = 0; i < container.getComponentCount(); i++) { + applyNames(container.getComponent(i)); + } + } + } + + public static String getText(Element tag) { // NOT a safe general-purpose implementation! + return ((Text) tag.getChildNodes().item(0)).getData(); + } + + private String getArgumentsCode(ContextNode[] arguments) { + StringBuilder result = new StringBuilder(); + result.append('('); + for (int i = 0; i < arguments.length; i++) { + if (i != 0) { + result.append(", "); + } + result.append(getJavaCode(arguments[i])); + } + result.append(')'); + return result.toString(); + } + + public String getJavaCode(ContextNode node) { + StringBuilder result = new StringBuilder(); + if (node instanceof PropertyNode) { + ContextNode[] arguments = node.getArguments(); + result.append(arguments.length == 0 ? "get" : "set"); + result.append(StringUtils.capitalize(((PropertyNode) node).getProperty())); + result.append(getArgumentsCode(arguments)); + } else if (node instanceof MethodNode) { + result.append((((MethodNode) node).getMethodName())); + result.append(getArgumentsCode(node.getArguments())); + } else if (node instanceof CapturedObject) { + CapturedObject object = (CapturedObject) node; + if (object.isInlineable()) { + result.append("new "); + result.append(object.getClassName()); + result.append(getArgumentsCode(node.getArguments())); + } else { + String id = object.getProperty("id"); + assert id != null; + result.append(id); + } + } else if (node instanceof ValueNode) { + result.append(TypeManager.getJavaCode(((ValueNode) node).getValue())); + } else if (node instanceof LiteralNode) { + result.append(((LiteralNode) node).getJavaCode()); + } else { + throw new IllegalArgumentException("unrecognized node type: " + node); + } + return result.toString(); + } + + // returns the best matching method for the specified argument types + private static Method getMethod(Class<?> target, String methodName, Class<?>[] arguments) { + try { + // use the package-private class java.beans.ReflectionUtils to resolve the method. This isn't 100% safe, but it's better than + // having to rewrite the resolution myself. + Class<?> reflectionUtils = Class.forName("java.beans.ReflectionUtils"); + Method getMethod = reflectionUtils.getDeclaredMethod("getMethod", new Class<?>[]{Class.class, String.class, Class[].class}); + getMethod.setAccessible(true); + return (Method) getMethod.invoke(null, target, methodName, arguments); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // returns the best matching constructor for the specified argument types + private static Constructor<?> getConstructor(Class<?> target, Class<?>[] arguments) { + try { + // use the package-private class java.beans.ReflectionUtils to resolve the constructor. This isn't 100% safe, but it's better than + // having to rewrite the resolution myself. + Class<?> reflectionUtils = Class.forName("java.beans.ReflectionUtils"); + Method getConstructor = reflectionUtils.getDeclaredMethod("getConstructor", new Class<?>[]{Class.class, Class[].class}); + getConstructor.setAccessible(true); + return (Constructor<?>) getConstructor.invoke(null, target, arguments); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private Object createInstance(CapturedObject object) { + try { + ContextNode[] argumentNodes = object.getArguments(); + Object[] arguments = new Object[argumentNodes.length]; + Class<?>[] argumentTypes = new Class<?>[argumentNodes.length]; + for (int j = 0; j < argumentNodes.length; j++) { + if (argumentNodes[j] instanceof ValueNode) { + arguments[j] = ((ValueNode) argumentNodes[j]).getValue(); + argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; + } else if (argumentNodes[j] instanceof CapturedObject) { + arguments[j] = createInstance((CapturedObject) argumentNodes[j]); + argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; + } + } + Constructor<?> constructor = getConstructor(Class.forName(object.getClassName(), true, classLoader), argumentTypes); + return constructor.newInstance(arguments); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String getJavaCode(Stack/*<ContextNode>*/ context) { + CapturedObject contextCapturedObject = (CapturedObject) context.get(0); + StringBuilder result = new StringBuilder(); + int start = 1; + for (int i = context.size() - 1; i > 1; i--) { + if (context.get(i) instanceof CapturedObject) { + start = i; + contextCapturedObject = (CapturedObject) context.get(i); + break; + } + } + Object contextObject = sourceObjects.get(contextCapturedObject.getProperty("id")); + Class<?> contextClass = contextObject != null ? contextObject.getClass() : null; + + for (int i = start; i < context.size(); i++) { + ContextNode node = (ContextNode) context.get(i); + if (contextObject != null && (node instanceof MethodNode || node instanceof PropertyNode)) { + // need to follow the call chain so we can insert typecasts as necessary + try { + String methodName; + ContextNode[] argumentNodes = node.getArguments(); + if (node instanceof MethodNode) { + methodName = ((MethodNode) node).getMethodName(); + } else { + methodName = (argumentNodes.length == 0 ? "get" : "set") + StringUtils.capitalize(((PropertyNode) node).getProperty()); + } + Object[] arguments = new Object[argumentNodes.length]; + Class<?>[] argumentTypes = new Class<?>[argumentNodes.length]; + for (int j = 0; j < argumentNodes.length; j++) { + if (argumentNodes[j] instanceof ValueNode) { + arguments[j] = ((ValueNode) argumentNodes[j]).getValue(); + argumentTypes[j] = arguments[j] != null ? arguments[j].getClass() : null; + } else if (argumentNodes[j] instanceof CapturedObject) { + arguments[j] = createInstance((CapturedObject) argumentNodes[j]); + argumentTypes[j] = arguments[j].getClass(); + } else if (argumentNodes[j] instanceof LiteralNode) { + arguments[j] = ((LiteralNode) argumentNodes[j]).getValue(); + argumentTypes[j] = arguments[j].getClass(); + } else { + throw new IllegalArgumentException("unsupported argument type: " + argumentNodes[j]); + } + } + + Method method = getMethod(contextClass, methodName, argumentTypes); + if (method == null) { + // could not find method in contextClass, must be defined in a subclass -- insert a typecast + result.insert(0, "((" + getOutputName(contextObject.getClass()) + ") "); + result.append(')'); + method = getMethod(contextObject.getClass(), methodName, argumentTypes); + } + if (method == null) { + throw new RuntimeException("could not find method " + methodName + Arrays.asList(argumentTypes) + " in " + contextObject.getClass() + " (context: " + context + ")"); + } + contextObject = method.invoke(contextObject, arguments); + contextClass = method.getReturnType(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + if (i > start) { + result.append('.'); + } + + result.append(getJavaCode(node)); + } + return result + ";"; + } + + private String getOutputName(Class<?> c) { + return c.getName(); + } + + public CapturedObject processObject(Element objectTag, Stack<ContextNode> context) { + String className = objectTag.getAttribute("class"); + ObjectHandler handler; + if (className.length() > 0) { + try { + ClassDescriptor descriptor = ClassDescriptorHelper.getClassDescriptor(className, classLoader); + handler = (ObjectHandler) objectHandlers.get(descriptor); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } else { + handler = (ObjectHandler) objectHandlers.get(ClassDescriptorHelper.getClassDescriptor(Object.class)); + } + + return handler.processObject(objectTag, context, this); + } + + private synchronized String convertToJAXX(InputStream beansXML) throws IOException { + try { + Document document = JAXXCompiler.parseDocument(beansXML); + Element rootElement = document.getDocumentElement(); + NodeList nodes = rootElement.getChildNodes(); + Stack<ContextNode> context = new Stack<ContextNode>(); + for (int i = 0; i < nodes.getLength(); i++) { + Node child = nodes.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) child; + if (!element.getTagName().equals("object")) { + throw new Error("expected tag 'object', found '" + element.getTagName() + "'"); + } + CapturedObject root = processObject(element, context); + for (CapturedObject object : capturedObjects.values()) { // add all orphan objects to the root, so any non-inlineable ones have their XML created + if (object.getParent() == null && object != root) { + root.addChild(object, null); + } + } + return root.getXML(this); + } + } + return null; + } catch (SAXException e) { + throw new RuntimeException(e); + } finally { + reset(); + } + } + + private void reset() { + sourceObjects.clear(); + capturedObjects.clear(); + count = 0; + } + + public static void main(String[] arg) throws Exception { + File file = new File(arg[0]); + JarFile jarFile = new JarFile(file); + ClassLoader classLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}); + Thread.currentThread().setContextClassLoader(classLoader); + EventQueue systemQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); + systemQueue.push(new CaptureEventQueue(classLoader)); + Manifest mf = jarFile.getManifest(); + String mainClassName = mf.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS); + Class<?> mainClass = Class.forName(mainClassName, true, classLoader); + Method main = mainClass.getMethod("main", String[].class); + main.invoke(null, new Object[]{new String[0]}); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/LiteralNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/LiteralNode.java new file mode 100644 index 0000000..ee75297 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/LiteralNode.java @@ -0,0 +1,45 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +public class LiteralNode extends AbstractContextNode { + private String javaCode; + private Object value; + + public LiteralNode(String javaCode, Object value) { + this.javaCode = javaCode; + this.value = value; + } + + + public String getJavaCode() { + return javaCode; + } + + public Object getValue() { + return value; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/MethodNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/MethodNode.java new file mode 100644 index 0000000..7adc0b8 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/MethodNode.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +public class MethodNode extends AbstractContextNode { + private String methodName; + + public MethodNode(String methodName) { + this.methodName = methodName; + } + + + public String getMethodName() { + return methodName; + } + + @Override + public String toString() { + return "Method[" + methodName + ", " + java.util.Arrays.asList(getArguments()) + "]"; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/PropertyNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/PropertyNode.java new file mode 100644 index 0000000..6b455bd --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/PropertyNode.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +public class PropertyNode extends AbstractContextNode { + private String property; + + public PropertyNode(String property) { + this.property = property; + } + + + public String getProperty() { + return property; + } + + + public String toString() { + return "Property[" + property + ", " + java.util.Arrays.asList(getArguments()) + "]"; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ValueNode.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ValueNode.java new file mode 100644 index 0000000..638261c --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/ValueNode.java @@ -0,0 +1,39 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture; + +public class ValueNode extends AbstractContextNode { + private Object value; + + public ValueNode(Object value) { + this.value = value; + } + + + public Object getValue() { + return value; + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java new file mode 100644 index 0000000..bc55ba3 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/JTabbedPaneHandler.java @@ -0,0 +1,51 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture.handlers; + +import jaxx.compiler.tools.jaxxcapture.ContextNode; +import jaxx.compiler.tools.jaxxcapture.JAXXCapture; +import jaxx.compiler.tools.jaxxcapture.MethodNode; +import org.w3c.dom.Element; + +import java.util.Arrays; +import java.util.Stack; + +public class JTabbedPaneHandler extends ObjectHandler { + + @Override + protected void evaluateMethod(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + String methodName = tag.getAttribute("method"); + if (methodName.equals("addTab")) { + MethodNode addTab = new MethodNode(methodName); + context.push(addTab); + processChildren(tag, context, capture); + context.pop(); + System.err.println(Arrays.asList(addTab.getArguments())); + } else { + super.evaluateMethod(tag, context, capture); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java new file mode 100644 index 0000000..65fe377 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/ObjectHandler.java @@ -0,0 +1,351 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture.handlers; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.java.JavaFileGenerator; +import jaxx.compiler.tools.jaxxcapture.CapturedObject; +import jaxx.compiler.tools.jaxxcapture.ContextNode; +import jaxx.compiler.tools.jaxxcapture.JAXXCapture; +import jaxx.compiler.tools.jaxxcapture.LiteralNode; +import jaxx.compiler.tools.jaxxcapture.MethodNode; +import jaxx.compiler.tools.jaxxcapture.PropertyNode; +import jaxx.compiler.tools.jaxxcapture.ValueNode; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.awt.Container; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Stack; + +public class ObjectHandler { + private static int count; + + public static final String ATTRIBUTE_PROPERTY = "property"; + + protected CapturedObject createCapturedObject(String className, JAXXCapture capture) { + return new CapturedObject(this, className, capture); + } + + + // returns true if the tag has any "void" children + protected boolean processChildren(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + boolean result = false; + NodeList children = tag.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element innerTag = (Element) child; + if (innerTag.getTagName().equals(JAXXCompilerFinalizer.TYPE_VOID)) { + result = true; + } + evaluate(innerTag, context, capture); + } + } + return result; + } + + + protected void evaluateProperty(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + // determine containing object + CapturedObject contextObject = null; + for (int i = context.size() - 1; i >= 0; i--) { + if (context.get(i) instanceof CapturedObject) { + contextObject = (CapturedObject) context.get(i); + break; + } + } + assert contextObject != null; + + String property = tag.getAttribute(ATTRIBUTE_PROPERTY); + if (!property.equals("actionCommand")) { // filter out actionCommand due to screwiness in XMLEncoder's handling of it + Object current = context.peek(); + PropertyNode newContext = new PropertyNode(property); + context.push(newContext); + boolean voidChildren = processChildren(tag, context, capture); + + ContextNode[] arguments = newContext.getArguments(); + if (arguments.length == 1) { + if (current instanceof CapturedObject && arguments[0] instanceof ValueNode) // simple property assignment + { + ((CapturedObject) current).setProperty(property, dataBindingEncode(String.valueOf(((ValueNode) arguments[0]).getValue()))); + } else if (current instanceof CapturedObject && arguments[0] instanceof CapturedObject && ((CapturedObject) arguments[0]).isInlineable()) // simple data binding + { + ((CapturedObject) current).setProperty(property, "{" + capture.getJavaCode(arguments[0]) + "}"); + } else { + contextObject.setInlineable(false); + contextObject.appendScriptCode(capture.getJavaCode(context)); + } + } else if (!voidChildren) { + contextObject.setInlineable(false); + contextObject.appendScriptCode(capture.getJavaCode(context)); + } + + assert context.peek() == newContext; + context.pop(); + } + } + + + protected void evaluateAdd(CapturedObject contextObject, CapturedObject child, ContextNode constraints) { + contextObject.addChild(child, constraints); + } + + + protected void evaluateMethod(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + // determine containing object + CapturedObject contextObject = null; + for (int i = context.size() - 1; i >= 0; i--) { + if (context.get(i) instanceof CapturedObject) { + contextObject = (CapturedObject) context.get(i); + break; + } + } + assert contextObject != null; + + try { + String methodName = tag.getAttribute("method"); + MethodNode newContext = new MethodNode(methodName); + context.push(newContext); + boolean voidChildren = processChildren(tag, context, capture); + boolean add = false; + + ContextNode[] arguments = newContext.getArguments(); + if (methodName.equals("add") && arguments.length >= 1 && arguments[0] instanceof CapturedObject) { + Class<?> contextClass = Class.forName(contextObject.getClassName(), true, capture.getClassLoader()); + if (Container.class.isAssignableFrom(contextClass)) { + add = true; + evaluateAdd(contextObject, (CapturedObject) arguments[0], null); + } + } + + if (!voidChildren && !add) { + contextObject.appendScriptCode(capture.getJavaCode(context)); + } + + assert context.peek() == newContext; + context.pop(); + } + catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + + protected void evaluate(Element tag, Stack<ContextNode> context, JAXXCapture capture) { + String tagName = tag.getTagName(); + if (tagName.equals("object")) { + String fieldName = tag.getAttribute("field"); + ContextNode currentNode = context.peek(); + if (fieldName.length() > 0) { + try { + String className = tag.getAttribute("class"); + Field field = Class.forName(className, true, capture.getClassLoader()).getField(fieldName); + Object value = field.get(null); + currentNode.addArgument(new LiteralNode(className + "." + fieldName, value)); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } else { + currentNode.addArgument(capture.processObject(tag, context)); + } + } else if (tagName.equals(JAXXCompilerFinalizer.TYPE_VOID)) { + String property = tag.getAttribute(ATTRIBUTE_PROPERTY); + if (property.length() > 0) { + evaluateProperty(tag, context, capture); + } else { + evaluateMethod(tag, context, capture); + } + } else if (tagName.equals("string")) { + context.peek().addArgument(new ValueNode(JAXXCapture.getText(tag))); + } else if (tagName.equals("boolean")) { + context.peek().addArgument(new ValueNode(Boolean.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("char")) { + context.peek().addArgument(new ValueNode(JAXXCapture.getText(tag).charAt(0))); + } else if (tagName.equals("short")) { + context.peek().addArgument(new ValueNode(Short.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("int")) { + context.peek().addArgument(new ValueNode(Integer.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("long")) { + context.peek().addArgument(new ValueNode(Long.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("float")) { + context.peek().addArgument(new ValueNode(Float.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("double")) { + context.peek().addArgument(new ValueNode(Double.valueOf(JAXXCapture.getText(tag)))); + } else if (tagName.equals("null")) { + context.peek().addArgument(new ValueNode(null)); + } else { + System.err.println("unsupported tag: " + tag.getTagName()); + } + } + + + private static String dataBindingEncode(String value) { + return value.replaceAll("\\{", "\\\\{").replaceAll("\\}", "\\\\}"); + } + + + public CapturedObject processObject(Element objectTag, Stack<ContextNode> context, JAXXCapture capture) { + String className = objectTag.getAttribute("class"); + if (className.length() > 0) { + CapturedObject capturedObject = createCapturedObject(className, capture); + context.push(capturedObject); + NodeList children = objectTag.getChildNodes(); + String id = objectTag.getAttribute("id"); + if (id.length() == 0 || capture.getCapturedObjects().containsKey(id)) { + id = "Auto" + ++count; + } + assert !capture.getCapturedObjects().containsKey(id); + capture.getCapturedObjects().put(id, capturedObject); + capturedObject.setProperty("id", id); + // process object's name before anything else + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) child; + if (element.getTagName().equals(JAXXCompilerFinalizer.TYPE_VOID) && element.getAttribute(ATTRIBUTE_PROPERTY).equals("name")) { + evaluate(element, context, capture); + String name = capturedObject.getProperty("name"); + if (name != null && !capture.getCapturedObjects().containsKey(name)) { + capture.getCapturedObjects().put(name, capturedObject); + capturedObject.setProperty("id", name); + capturedObject.getProperties().remove("name"); + } + } + } + } + // process remaining children + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) child; + if (!JAXXCompilerFinalizer.TYPE_VOID.equals(element.getTagName()) || !element.getAttribute(ATTRIBUTE_PROPERTY).equals("name")) { + evaluate(element, context, capture); + } + } + } + assert context.peek() == capturedObject; + context.pop(); + + return capturedObject; + } else { + CapturedObject result = capture.getCapturedObjects().get(objectTag.getAttribute("idref")); + if (result == null) { + throw new RuntimeException("Internal error: could not find tag with id " + objectTag.getAttribute("idref")); + } + result.setInlineable(false); // we have at least two references to it, and so can't inline it + return result; + } + } + + + private static String xmlEncode(String src) { + return src.replaceAll("'", "&").replaceAll("<", "<"); + } + + + public String getXML(CapturedObject object, JAXXCapture capture) { + StringBuilder result = new StringBuilder(); + result.append('<'); + String className = object.getClassName(); + if (className.startsWith("javax.swing.")) { + className = className.substring("javax.swing.".length()); + } + result.append(className); + Map<String, String> properties = object.getProperties(); + for (Map.Entry<String, String> e : properties.entrySet()) { + result.append(' '); + result.append(e.getKey()); + result.append("='"); + result.append(xmlEncode(e.getValue())); + result.append('\''); + } + ContextNode[] arguments = object.getArguments(); + if (arguments != null && arguments.length > 0) { + result.append(" constructorParams='"); + for (int j = 0; j < arguments.length; j++) { + if (j != 0) { + result.append(", "); + } + result.append(capture.getJavaCode(arguments[j])); + } + result.append('\''); + } + boolean tagClosed = false; + + String children = getChildXML(object, capture); + String lineSeparator = JAXXCompiler.getLineSeparator(); + if (children != null && children.length() > 0) { + if (!tagClosed) { + tagClosed = true; + result.append('>'); + result.append(lineSeparator); + } + result.append(children); + } + + String script = object.getScriptCode(); + if (script != null && script.length() > 0) { + if (!tagClosed) { + tagClosed = true; + result.append('>'); + result.append(lineSeparator); + } + result.append(" <script>"); + result.append(lineSeparator); + result.append(JavaFileGenerator.indent(script, 4, false, lineSeparator)); + result.append(lineSeparator); + result.append(" </script>"); + result.append(lineSeparator); + } + if (tagClosed) { + result.append("</"); + result.append(className); + result.append('>'); + } else { + result.append("/>"); + } + return result.toString(); + } + + + protected String getChildXML(CapturedObject object, JAXXCapture capture) { + StringBuilder result = new StringBuilder(); + CapturedObject[] children = object.getChildren(); + String lineSeparator = JAXXCompiler.getLineSeparator(); + for (CapturedObject aChildren : children) { + if (!aChildren.isInlineable()) { + result.append(JavaFileGenerator.indent(aChildren.getXML(capture), 2, false, lineSeparator)); + result.append(lineSeparator); + } + } + return result.toString(); + } +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java new file mode 100644 index 0000000..a91e9cd --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/tools/jaxxcapture/handlers/TableHandler.java @@ -0,0 +1,39 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tools.jaxxcapture.handlers; + +import jaxx.compiler.tools.jaxxcapture.CapturedObject; +import jaxx.compiler.tools.jaxxcapture.JAXXCapture; + +public class TableHandler extends ObjectHandler { + + @Override + protected CapturedObject createCapturedObject(String className, JAXXCapture capture) { + CapturedObject result = new CapturedObject(this, "javax.swing.JPanel", capture); + result.setProperty("layout", "{new GridBagLayout()}"); + return result; + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/ColorConverter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/ColorConverter.java new file mode 100644 index 0000000..1d9b986 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/ColorConverter.java @@ -0,0 +1,63 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +import java.awt.Color; +import java.lang.reflect.Field; + +public class ColorConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[]{ + Color.class + }; + } + + @Override + public String getJavaCode(Object object) { + Color color = (Color) object; + return "new Color(" + color.getRed() + ", " + color.getGreen() + ", " + color.getBlue() + ")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (!Color.class.equals(type)) { + 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); + } + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/GridBagConstraintsConverter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/GridBagConstraintsConverter.java new file mode 100644 index 0000000..3e56aee --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/GridBagConstraintsConverter.java @@ -0,0 +1,51 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +import java.awt.GridBagConstraints; + +public class GridBagConstraintsConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[] { + GridBagConstraints.class + }; + } + + @Override + public String getJavaCode(Object object) { + GridBagConstraints g = (GridBagConstraints) object; + return "new GridBagConstraints(" + g.gridx + ", " + g.gridy + ", " + g.gridwidth + ", " + g.gridheight + ", " + + g.weightx + ", " + g.weighty + ", " + g.anchor + ", " + g.fill + ", " + + TypeManager.getJavaCode(g.insets) + ", " + g.ipadx + ", " + g.ipady + ")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + throw new UnsupportedOperationException("GridBagConstraints must be represented using Java code"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/InsetsConverter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/InsetsConverter.java new file mode 100644 index 0000000..d4aaeef --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/InsetsConverter.java @@ -0,0 +1,64 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +import java.awt.Insets; +import java.util.StringTokenizer; + +public class InsetsConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[]{Insets.class}; + } + + @Override + public String getJavaCode(Object object) { + Insets insets = (Insets) object; + return "new Insets(" + insets.top + ", " + insets.left + ", " + insets.bottom + ", " + insets.right + ")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (!Insets.class.equals(type)) { + 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"); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/KeyStrokeConverter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/KeyStrokeConverter.java new file mode 100644 index 0000000..3fbf388 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/KeyStrokeConverter.java @@ -0,0 +1,49 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +import javax.swing.KeyStroke; + +public class KeyStrokeConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + return new Class<?>[]{KeyStroke.class}; + } + + @Override + public String getJavaCode(Object object) { + return "KeyStroke.getKeyStroke(\"" + object.toString() + "\")"; + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (!KeyStroke.class.equals(type)) { + throw new IllegalArgumentException("unsupported type: " + type); + } + return KeyStroke.getKeyStroke(string); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/PrimitiveConverter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/PrimitiveConverter.java new file mode 100644 index 0000000..34d233b --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/PrimitiveConverter.java @@ -0,0 +1,125 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +import jaxx.compiler.JAXXCompiler; + +public class PrimitiveConverter implements TypeConverter { + + @Override + public Class<?>[] getSupportedTypes() { + + return new Class<?>[]{ + boolean.class, + Boolean.class, + byte.class, + Byte.class, + short.class, + Short.class, + int.class, + Integer.class, + long.class, + Long.class, + float.class, + Float.class, + double.class, + Double.class, + char.class, + Character.class, + String.class + }; + } + + @Override + public String getJavaCode(Object object) { + if (object instanceof Boolean) { + return String.valueOf(((Boolean) object).booleanValue()); + } + if (object instanceof Byte) { + return String.valueOf(((Byte) object).byteValue()); + } + if (object instanceof Short) { + return String.valueOf(((Short) object).shortValue()); + } + if (object instanceof Integer) { + return String.valueOf(((Integer) object).intValue()); + } + if (object instanceof Long) { + return String.valueOf(((Long) object).longValue()) + "L"; + } + if (object instanceof Float) { + return String.valueOf(((Float) object).floatValue()) + "F"; + } + if (object instanceof Double) { + return String.valueOf(((Double) object).doubleValue()); + } + if (object instanceof String) { + return '"' + JAXXCompiler.escapeJavaString((String) object) + '"'; + } + throw new IllegalArgumentException("unsupported object: " + object); + } + + @Override + public Object convertFromString(String string, Class<?> type) { + if (String.class.equals(type) || Object.class.equals(type) || type == null) { + return string; + } + if (int.class.equals(type) || Integer.class.equals(type)) { + return Integer.valueOf(string); + } + if (boolean.class.equals(type) || Boolean.class.equals(type)) { + if (string.toLowerCase().equals("true")) { + return Boolean.TRUE; + } + if (string.toLowerCase().equals("false")) { + return Boolean.FALSE; + } + throw new IllegalArgumentException("expected 'true' or 'false', found '" + string + "'"); + } + if (byte.class.equals(type) || Byte.class.equals(type)) { + return Byte.valueOf(string); + } + if (short.class.equals(type) || Short.class.equals(type)) { + return Short.valueOf(string); + } + if (long.class.equals(type) || Long.class.equals(type)) { + return Long.valueOf(string); + } + if (float.class.equals(type) || Float.class.equals(type)) { + return Float.valueOf(string); + } + if (double.class.equals(type) || Double.class.equals(type)) { + return Double.valueOf(string); + } + if (char.class.equals(type) || Character.class.equals(type)) { + if (string.length() == 1) { + return string.charAt(0); + } + throw new IllegalArgumentException("expected a single character, found '" + string + "'"); + } + throw new IllegalArgumentException("unsupported type: " + type); + } +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeConverter.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeConverter.java new file mode 100644 index 0000000..a6e7710 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeConverter.java @@ -0,0 +1,35 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +public interface TypeConverter { + + Class<?>[] getSupportedTypes(); + + String getJavaCode(Object object); + + Object convertFromString(String string, Class<?> type); +} diff --git a/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeManager.java b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeManager.java new file mode 100644 index 0000000..5996e25 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/java/jaxx/compiler/types/TypeManager.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +import java.util.HashMap; +import java.util.Map; +import java.util.ServiceLoader; + +public class TypeManager { + + /** + * Dictionnary of converters loaded by the {@link ServiceLoader} mecanism + */ + private static Map<Class<?>, TypeConverter> converters; + + /** + * @return dictionnary of known converters + */ + public static Map<Class<?>, TypeConverter> getConverters() { + if (converters == null) { + converters = new HashMap<Class<?>, TypeConverter>(); + // load converters + ServiceLoader<TypeConverter> loader = + ServiceLoader.load(TypeConverter.class); + for (TypeConverter c : loader) { + // for each supported type, register the converter + for (Class<?> type : c.getSupportedTypes()) { + converters.put(type, c); + } + } + } + return converters; + } + + private TypeManager() { /* not instantiable */ } + + public static TypeConverter getTypeConverter(Class<?> type) { + return getConverters().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); + } + + /** + * Convertit un nom de variable en nom de constante. + * + * @param variableName le nom de variable a convertir + * @return le nom de la constante à partir du nom de la variable + */ + public static String convertVariableNameToConstantName(String variableName) { + StringBuilder buffer = new StringBuilder(); + boolean lastCarIsUp = false; + char lastChar = '$'; + for (int i = 0, j = variableName.length(); i < j; i++) { + char c = variableName.charAt(i); + boolean carIsUp; + if (c == '!') { + buffer.append("NOT_"); + lastChar = '_'; + lastCarIsUp = true; + continue; + } + if (Character.isLetterOrDigit(c)) { + carIsUp = Character.isUpperCase(c); + } else { + carIsUp = false; + if (c != '$') { + // on remplace tous les caractères non standard par un _ + if (lastChar == '_' && c != '_') { + continue; + } + c = '_'; + } + } + + if (i > 0 && !lastCarIsUp && carIsUp) { + // ajout d'un _ + buffer.append('_'); + } + if (carIsUp) { + buffer.append(c); + } else { + buffer.append(Character.toUpperCase(c)); + } + lastCarIsUp = carIsUp || c == '$' || c == '_'; + lastChar = c; + } + return buffer.toString(); + } +} diff --git a/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.CompiledObjectDecorator b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.CompiledObjectDecorator new file mode 100644 index 0000000..55f046a --- /dev/null +++ b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.CompiledObjectDecorator @@ -0,0 +1,3 @@ +jaxx.compiler.decorators.DefaultCompiledObjectDecorator +jaxx.compiler.decorators.BoxedCompiledObjectDecorator +jaxx.compiler.decorators.HelpRootCompiledObjectDecorator diff --git a/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.JAXXCompilerFinalizer b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.JAXXCompilerFinalizer new file mode 100644 index 0000000..abb8df4 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.JAXXCompilerFinalizer @@ -0,0 +1,3 @@ +jaxx.compiler.finalizers.DefaultFinalizer +jaxx.compiler.finalizers.SwingFinalizer +jaxx.compiler.finalizers.ValidatorFinalizer diff --git a/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.spi.Initializer b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.spi.Initializer new file mode 100644 index 0000000..763ca46 --- /dev/null +++ b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.spi.Initializer @@ -0,0 +1 @@ +jaxx.compiler.spi.DefaultInitializer \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.types.TypeConverter b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.types.TypeConverter new file mode 100644 index 0000000..440367e --- /dev/null +++ b/trunk/jaxx-compiler/src/main/resources/META-INF/services/jaxx.compiler.types.TypeConverter @@ -0,0 +1,5 @@ +jaxx.compiler.types.ColorConverter +jaxx.compiler.types.GridBagConstraintsConverter +jaxx.compiler.types.InsetsConverter +jaxx.compiler.types.KeyStrokeConverter +jaxx.compiler.types.PrimitiveConverter diff --git a/trunk/jaxx-compiler/src/site/rst/index.rst b/trunk/jaxx-compiler/src/site/rst/index.rst new file mode 100644 index 0000000..14d8951 --- /dev/null +++ b/trunk/jaxx-compiler/src/site/rst/index.rst @@ -0,0 +1,40 @@ +.. - +.. * #%L +.. * JAXX :: Compiler +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============= +jaxx-compiler +============= + +.. contents:: + + +Présentation +------------ + +Le compilateur Jaxx TODO + +**Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes +librairies.** + diff --git a/trunk/jaxx-compiler/src/site/site_fr.xml b/trunk/jaxx-compiler/src/site/site_fr.xml new file mode 100644 index 0000000..48fc93d --- /dev/null +++ b/trunk/jaxx-compiler/src/site/site_fr.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Compiler + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <src>http://maven-site.chorem.org/public/images/logos/jaxx-logo.png</src> + <href>index.html</href> + </bannerLeft> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="index.html"/> + </breadcrumbs> + + <menu ref="parent"/> + + <menu name="Utilisateur"/> + + <menu ref="reports"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/beans/BeanIntoUtilTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/beans/BeanIntoUtilTest.java new file mode 100644 index 0000000..da8c096 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/beans/BeanIntoUtilTest.java @@ -0,0 +1,59 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.beans; + +import org.junit.Assert; +import org.junit.Test; + +import java.beans.Introspector; + +/** @author tchemit <chemit@codelutin.com> */ +public class BeanIntoUtilTest { + + @Test + public void testExtraBeanInfoPath() { + BeanInfoUtil.reset(); + String[] searchPath0 = Introspector.getBeanInfoSearchPath(); + + BeanInfoUtil.addJaxxBeanInfoPath("jaxx.runtime.swing"); + + String[] searchPath = Introspector.getBeanInfoSearchPath(); + Assert.assertEquals(searchPath0.length + 1, searchPath.length); + + BeanInfoUtil.reset(); + Assert.assertEquals(searchPath0.length, Introspector.getBeanInfoSearchPath().length); + + String packageName = getClass().getPackage().getName() + ".dummy"; + BeanInfoUtil.addJaxxBeanInfoPath("jaxx.beaninfos", packageName); + + searchPath = Introspector.getBeanInfoSearchPath(); + Assert.assertEquals(searchPath0.length + 2, searchPath.length); + Assert.assertEquals(packageName, searchPath[searchPath.length - 1]); + + BeanInfoUtil.reset(); + Assert.assertEquals(searchPath0.length, Introspector.getBeanInfoSearchPath().length); + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/binding/JavaParserUtilTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/binding/JavaParserUtilTest.java new file mode 100644 index 0000000..fe02c70 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/binding/JavaParserUtilTest.java @@ -0,0 +1,327 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.binding; + +import jaxx.compiler.java.parser.JavaParser; +import jaxx.compiler.java.parser.SimpleNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.io.StringReader; +import java.util.*; + +/** + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class JavaParserUtilTest { + + /** + * Logger + */ + private static final Log log = LogFactory.getLog(JavaParserUtilTest.class); + + Map<SimpleNode, List<SimpleNode>> store = new LinkedHashMap<SimpleNode, List<SimpleNode>>(); + Map<SimpleNode, List<SimpleNode>> casts = new LinkedHashMap<SimpleNode, List<SimpleNode>>(); + List<SimpleNode> literals = new ArrayList<SimpleNode>(); + Set<String> requirements; + Iterator<SimpleNode> simpleNodeIterator; + Iterator<String> requirementsIterator; + SimpleNode node; + String source; + + @Test + public void testGetExpressionsWithLiterals() throws Exception { + + parseSourceAndGetExpressions("1", 1, 1); + assertNextNode(source, 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("true", 1, 1); + assertNextNode(source, 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("\"1\"", 1, 1); + assertNextNode(source, 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("\"1\" + \"2\"", 2, 2); + assertNextNode("\"1\"", 0); + assertLiteralNode(0); + assertNextNode("\"2\"", 0); + assertLiteralNode(1); + + parseSourceAndGetExpressions("1.1 + 2", 2, 2); + assertNextNode("1.1", 0); + assertLiteralNode(0); + assertNextNode("2", 0); + assertLiteralNode(1); + } + + @Test + public void testGetExpressionsWithNoLiterals() throws Exception { + + parseSourceAndGetExpressions("a", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("a.getText()", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("a.getText().getLength()", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("getText()", 0, 1); + assertNextNode(source, 0); + + parseSourceAndGetExpressions("getText(a)", 0, 2); + assertNextNode(source, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("getText(a, b, c)", 0, 4); + assertNextNode(source, 3); + assertNextNode("a", 0); + assertNextNode("b", 0); + assertNextNode("c", 0); + + parseSourceAndGetExpressions("getText(a + b, c)", 0, 4); + assertNextNode(source, 3); + assertNextNode("a", 0); + assertNextNode("b", 0); + assertNextNode("c", 0); + + parseSourceAndGetExpressions("getText(a + b + c)", 0, 4); + assertNextNode(source, 3); + assertNextNode("a", 0); + assertNextNode("b", 0); + assertNextNode("c", 0); + + parseSourceAndGetExpressions("(Hum)a", 0, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("(Hum) a", 0, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("((Hum) a)", 0, 2); + assertNextNode(source, 1); + assertNextNode("a", 0); + + parseSourceAndGetExpressions("((Hum) a).getText()", 0, 2); + assertNextNode(source, 1); + assertNextNode("a", 0); + } + + @Test + public void testGetExpressions() throws Exception { + + parseSourceAndGetExpressions("getText(\"a\")", 1, 2); + assertNextNode(source, 1); + assertNextNode("\"a\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.getText(\"a\")", 1, 2); + assertNextNode(source, 1); + assertNextNode("\"a\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("getText2() && getText(\"a.b\")", 1, 3); + assertNextNode("getText2()", 0); + assertNextNode("getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.getText2() && getText(\"a.b\")", 1, 3); + assertNextNode("SwingUtil.getText2()", 0); + assertNextNode("getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.getText2() && SwingUtil2.getText(\"a.b\")", 1, 3); + assertNextNode("SwingUtil.getText2()", 0); + assertNextNode("SwingUtil2.getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + + parseSourceAndGetExpressions("SwingUtil.get().getText2() && SwingUtil2.getText(\"a.b\")", 1, 3); + assertNextNode("SwingUtil.get().getText2()", 0); + assertNextNode("SwingUtil2.getText(\"a.b\")", 1); + assertNextNode("\"a.b\"", 0); + assertLiteralNode(0); + } + + @Test + public void testGetMethodInvocationParameters() throws Exception { + getMethodInvocationParameters("a", null); + getMethodInvocationParameters("a(", null); + getMethodInvocationParameters("a( ", null); + getMethodInvocationParameters("a)", null); + getMethodInvocationParameters("a )", null); + getMethodInvocationParameters("a()", ""); + getMethodInvocationParameters("a( )", ""); + getMethodInvocationParameters("a( yo )", "yo"); + getMethodInvocationParameters("SwingUtil.a( yo )", "yo"); + getMethodInvocationParameters("SwingUtil.a( yo, ya )", "yo, ya"); + + } + + @Test + public void testGetRequirementsWithLiterals() throws Exception { + + parseSourceAndGetRequirements("1"); + + parseSourceAndGetRequirements("true"); + + parseSourceAndGetRequirements("\"1\""); + + parseSourceAndGetRequirements("\"1\" + \"2\""); + + parseSourceAndGetRequirements("1.1 + 2"); + } + + + @Test + public void testGetRequirementsWithNoLiterals() throws Exception { + + parseSourceAndGetRequirements("a"); + + parseSourceAndGetRequirements("a.getText()", "a"); + + parseSourceAndGetRequirements("a.getText().getLength()", "a", "a.getText()"); + + parseSourceAndGetRequirements("getText()"); + + parseSourceAndGetRequirements("getText(a)"); + + parseSourceAndGetRequirements("getText(a, b, c)"); + + parseSourceAndGetRequirements("getText(a + b, c)"); + + parseSourceAndGetRequirements("getText(a + b + c)"); + + parseSourceAndGetRequirements("(Hum)a"); + + parseSourceAndGetRequirements("((Hum)a)"); + + parseSourceAndGetRequirements("((Hum)a).getText()", "a"); + + parseSourceAndGetRequirements("((Hum)a).getB().getText()", "a", "a.getB()"); + + parseSourceAndGetRequirements("((Hum)a.getB()).getText()", "a", "a.getB()"); + } + + @Test + public void testGetRequirements() throws Exception { + + parseSourceAndGetRequirements("getText(\"a\")"); + + parseSourceAndGetRequirements("SwingUtil.getText(\"a\")", "SwingUtil"); + + parseSourceAndGetRequirements("getText2() && getText(\"a.b\")"); + + parseSourceAndGetRequirements("SwingUtil.getText2() && getText(\"a.b\")", "SwingUtil"); + + parseSourceAndGetRequirements("SwingUtil.getText2() && SwingUtil2.getText(\"a.b\")", "SwingUtil", "SwingUtil2"); + + parseSourceAndGetRequirements("SwingUtil.get().getText2() && SwingUtil2.getText(\"a.b\")", "SwingUtil2", "SwingUtil", "SwingUtil.get()"); + + } + + protected void parseSourceAndGetExpressions(String source, int expectedNbLiterals, int expectedNbExpressions) { + + // clean stores + literals.clear(); + + parseSource(source); + + Assert.assertEquals(expectedNbLiterals, literals.size()); + Assert.assertEquals(expectedNbExpressions, store.size()); + + simpleNodeIterator = store.keySet().iterator(); + } + + protected void parseSourceAndGetRequirements(String source, String... expected) { + + parseSource(source); + + requirements = JavaParserUtil.getRequired(store.keySet(), casts); + Assert.assertEquals(expected.length, requirements == null ? 0 : requirements.size()); + if (expected.length > 0) { + + requirementsIterator = requirements.iterator(); + for (String s : expected) { + Assert.assertTrue(requirementsIterator.hasNext()); + Assert.assertEquals(s, requirementsIterator.next()); + } + } + } + + protected void getMethodInvocationParameters(String code, String expected) { + String invocationParameters = JavaParserUtil.getMethodInvocationParameters(code); + Assert.assertEquals(expected, invocationParameters); + } + + protected void assertNextNode(String expectedText, int nbDep) { + + Assert.assertTrue(simpleNodeIterator.hasNext()); + node = simpleNodeIterator.next(); + Assert.assertNotNull(node); + Assert.assertEquals(expectedText, node.getText().trim()); + Assert.assertEquals(nbDep, store.get(node).size()); + } + + private void parseSource(String source) { + + this.source = source; + // clean stores + store.clear(); + literals.clear(); + casts.clear(); + + if (log.isDebugEnabled()) { + log.debug(source); + } + + JavaParser p; + SimpleNode node; + p = new JavaParser(new StringReader(source)); + while (!p.Line()) { + node = p.popNode(); + JavaParserUtil.getExpressions(node, store, literals, casts); + } + } + + protected void assertLiteralNode(int nbDep) { + Assert.assertNotNull(node); + Assert.assertTrue(nbDep <= literals.size()); + Assert.assertEquals(node, literals.get(nbDep)); + } + +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaFieldTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaFieldTest.java new file mode 100644 index 0000000..49088d3 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaFieldTest.java @@ -0,0 +1,127 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.java; + +import com.google.common.collect.Lists; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; + +/** + * Created: 3 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class JavaFieldTest { + /** Logger */ + private static final Log log = LogFactory.getLog(JavaFieldTest.class); + + @Test + public void testGetFieldOrderScope() { + + EnumSet<JavaField.FieldOrder> allConstants = EnumSet.allOf(JavaField.FieldOrder.class); + if (log.isDebugEnabled()) { + for (JavaField.FieldOrder allConstant : allConstants) { + log.debug("\n" + allConstant.getHeader()); + } + } + + EnumSet<JavaField.FieldOrder> constants; + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.STATIC); + + Assert.assertEquals(4, constants.size()); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsBean)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPublicBindings)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPrivateBindings)); + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.PUBLIC); + + Assert.assertEquals(3, constants.size()); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsBean)); +// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPublicBindings)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.publicFields)); + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.PROTECTED); + + Assert.assertEquals(2, constants.size()); +// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.protectedFields)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.internalFields)); + + + constants = JavaField.getFieldOrderScope(allConstants, Modifier.PRIVATE); + Assert.assertEquals(3, constants.size()); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsPrivateBindings)); +// Assert.assertTrue(constants.contains(JavaField.FieldOrder.staticsOthers)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.privateFields)); + Assert.assertTrue(constants.contains(JavaField.FieldOrder.internalFields)); + + } + + /** + * To test http://nuiton.org/issues/2154. + * + * @since 2.5.1 + */ + @Test + public void testCompare() { + + String[] names = new String[]{ + "cf0", + "cf1", + "cf0O1", + "cf0A1", + "ct0O1", "ct0A1", + "cgett0", + "cgett1", "cgett0O1", + "cgett0A1", "cfile", "cgetfile", "t0", "t1", + "cmt0", "cmt1", "cmt0O1", "cmt0A1", "cmgett0", + "cmgett1", "cmgett0O1", "cmgett0A1", + "cMfile", "cMgetfile", + "Mt0", "Mt1", "cit0", "cit1", "cit0O1", "cit0A1", "cigett0", + "bindings" + }; + List<JavaField> theFileds = Lists.newArrayList(); + for (String name : names) { + JavaField field = new JavaField(Modifier.PROTECTED, "String", name, false); + theFileds.add(field); + } + Collections.sort(theFileds); + + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaMethodTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaMethodTest.java new file mode 100644 index 0000000..d75716d --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/java/JavaMethodTest.java @@ -0,0 +1,91 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.java; + +import jaxx.compiler.java.JavaMethod.MethodOrder; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Modifier; +import java.util.EnumSet; + +/** + * @author tchemit <chemit@codelutin.com> + */ +public class JavaMethodTest { + /** + * Logger + */ + private static final Log log = LogFactory.getLog(JavaMethodTest.class); + + @Test + public void testGetMethodOrderScope() { + + EnumSet<MethodOrder> allConstants = EnumSet.allOf(MethodOrder.class); + if (log.isDebugEnabled()) { + for (MethodOrder allConstant : allConstants) { + log.debug("\n" + allConstant.getHeader()); + } + } + + EnumSet<MethodOrder> constants; + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.STATIC); + + Assert.assertEquals(1, constants.size()); + Assert.assertTrue(constants.contains(MethodOrder.statics)); + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PUBLIC); + + Assert.assertEquals(8, constants.size()); + Assert.assertTrue(constants.contains(MethodOrder.constructors)); + Assert.assertTrue(constants.contains(MethodOrder.JAXXObject)); + Assert.assertTrue(constants.contains(MethodOrder.JAXXContext)); + Assert.assertTrue(constants.contains(MethodOrder.JAXXValidation)); + Assert.assertTrue(constants.contains(MethodOrder.events)); + Assert.assertTrue(constants.contains(MethodOrder.publicGetters)); + Assert.assertTrue(constants.contains(MethodOrder.publicSetters)); + Assert.assertTrue(constants.contains(MethodOrder.otherPublic)); + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PROTECTED); + + Assert.assertEquals(3, constants.size()); + Assert.assertTrue(constants.contains(MethodOrder.protectedGetters)); + Assert.assertTrue(constants.contains(MethodOrder.protecteds)); + Assert.assertTrue(constants.contains(MethodOrder.createMethod)); + + + constants = JavaMethod.getMethodOrderScope(allConstants, Modifier.PRIVATE); + Assert.assertEquals(4, constants.size()); + Assert.assertTrue(constants.contains(MethodOrder.internalMethod)); + Assert.assertTrue(constants.contains(MethodOrder.createMethod)); + Assert.assertTrue(constants.contains(MethodOrder.packageLocal)); + Assert.assertTrue(constants.contains(MethodOrder.privates)); + + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/ClassDescriptorTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/ClassDescriptorTest.java new file mode 100644 index 0000000..276f554 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/ClassDescriptorTest.java @@ -0,0 +1,148 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.reflect; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class ClassDescriptorTest { + + @BeforeClass + public static void before() { + ClassDescriptorHelper.setShowLoading(true); + } + + @AfterClass + public static void after() { + ClassDescriptorHelper.setShowLoading(true); + } + + /*@Test + public void testGetClassDescriptor() throws Exception { + ClassDescriptorHelper.getClassDescriptor("jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode"); + }*/ + @Test + public void testBuiltInClassName() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor object = ClassDescriptorHelper.getClassDescriptor("java.lang.Object"); + MethodDescriptor toString = object.getMethodDescriptor("toString"); + assertEquals(toString.getName(), "toString"); + assertEquals(toString.getParameterTypes().length, 0); + + MethodDescriptor equals = object.getMethodDescriptor("equals", object); + assertEquals(equals.getName(), "equals"); + assertEquals(equals.getParameterTypes().length, 1); + assertEquals(equals.getParameterTypes()[0], object); + } + + @Test + public void testBuiltInClass() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor object1 = ClassDescriptorHelper.getClassDescriptor("java.lang.Object"); + ClassDescriptor object2 = ClassDescriptorHelper.getClassDescriptor(Object.class); + assertEquals(object1, object2); + } + + @Test + public void testUserClassName() throws ClassNotFoundException, NoSuchMethodException { + ClassDescriptor me = ClassDescriptorHelper.getClassDescriptor(ClassDescriptorTest.class.getName(), getClass().getClassLoader()); + MethodDescriptor testUserClassName = me.getMethodDescriptor("testUserClassName"); + assertEquals(testUserClassName.getName(), "testUserClassName"); + assertEquals(testUserClassName.getParameterTypes().length, 0); + } + + @Test(expected = ClassNotFoundException.class) + public void testWrongCase() throws ClassNotFoundException { + ClassDescriptorHelper.getClassDescriptor("jaxx.junit.classdescriptortest", getClass().getClassLoader()); + } + + @Test + public void testArrays() throws ClassNotFoundException { + ClassDescriptor intArray = ClassDescriptorHelper.getClassDescriptor(int[].class); + assertNotNull(intArray); + ClassDescriptor objectArray = ClassDescriptorHelper.getClassDescriptor(Object[].class); + assertNotNull(objectArray); + } + + @Test + public void testConstructorFromClass() throws ClassNotFoundException, MalformedURLException { + String className = MyClass.class.getName(); + ClassDescriptor descriptor = ClassDescriptorHelper.getClassDescriptor(className); + assertNotNull(descriptor); + assertEquals(ClassDescriptorHelper.ResolverType.JAVA_CLASS, descriptor.getResolverType()); + MethodDescriptor[] constructorDescriptors = descriptor.getConstructorDescriptors(); + assertNotNull(constructorDescriptors); + assertEquals(2, constructorDescriptors.length); + } + + @Test + public void testConstructorFromJavaFile() throws ClassNotFoundException, MalformedURLException { + String className = MyClass.class.getName(); + ClassLoader classLoader = getClass().getClassLoader(); + + + File testSourceDir = new File(getBasedir(), "src" + File.separator + "test" + File.separator + "java"); + + ClassLoader myClassLoader = new URLClassLoader(new URL[]{testSourceDir.toURI().toURL()}, classLoader); + + URL javaFileUrl = ClassDescriptorHelper.getURL(myClassLoader, className, "java"); + assertNotNull(javaFileUrl); + + ClassDescriptor descriptorFromFile = ClassDescriptorHelper.getClassDescriptor0( + ClassDescriptorHelper.ResolverType.JAVA_FILE, + className, + javaFileUrl, + myClassLoader + ); + assertNotNull(descriptorFromFile); + MethodDescriptor[] constructorDescriptorsfromFile = descriptorFromFile.getConstructorDescriptors(); + assertNotNull(constructorDescriptorsfromFile); + assertEquals(2, constructorDescriptorsfromFile.length); + } + + + static File basedir; + + public static File getBasedir() { + if (basedir == null) { + String tmp = System.getProperty("basedir"); + if (tmp == null) { + tmp = new File("").getAbsolutePath(); + } + basedir = new File(tmp); + + } + return basedir; + } + +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyAbstractClass.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyAbstractClass.java new file mode 100644 index 0000000..e6a06a9 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyAbstractClass.java @@ -0,0 +1,38 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +/** + * To test parser on abstract class file. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public abstract class MyAbstractClass implements MyInterface { + + protected void myAbstractMethod() { + + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass.java new file mode 100644 index 0000000..c9470e7 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass.java @@ -0,0 +1,48 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +/** + * A child class to test the bug http://nuiton.org/issues/show/1470 + * <p/> + * To test if a child class obtains properties from his super class. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4.2 + */ +public class MyChildClass extends MyClass implements Cloneable{ + + private static final long serialVersionUID = 2L; + + protected String childProperty; + + public String getChildProperty() { + return childProperty; + } + + public void setChildProperty(String childProperty) { + this.childProperty = childProperty; + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass2.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass2.java new file mode 100644 index 0000000..e63fb9f --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyChildClass2.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +/** + * To test the bug : http://nuiton.org/issues/show/1442 + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4.2 + */ +public class MyChildClass2 extends MyClass { + private static final long serialVersionUID = 1L; +} + +// This class will not be scanned! +class MyPackageClass { + +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyClass.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyClass.java new file mode 100644 index 0000000..701b4bb --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyClass.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +import java.io.Serializable; + +/** + * To test inheritance. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class MyClass extends MyAbstractClass implements Serializable { + + private static final long serialVersionUID = 1L; + + private final String myPrivateStringField = "final"; + + protected String myProtectedStringField; + + public String myPublicStringField; + + public MyClass() { + } + + public MyClass(String myProtectedStringField, String myPublicStringField) { + this.myProtectedStringField = myProtectedStringField; + this.myPublicStringField = myPublicStringField; + } + + @Override + public void myMethod() { + } + + public String getMyPrivateStringField() { + return myPrivateStringField; + } + + public String getMyProtectedStringField() { + return myProtectedStringField; + } + + public String getMyPublicStringField() { + return myPublicStringField; + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyEnum.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyEnum.java new file mode 100644 index 0000000..5598fcc --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyEnum.java @@ -0,0 +1,45 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +import java.io.Serializable; + +/** + * Created: 4 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public enum MyEnum implements Serializable, MyInterface { + + A, B; + + @Override + public void myMethod() { + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface.java new file mode 100644 index 0000000..2a369a1 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface.java @@ -0,0 +1,38 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +/** + * Simple interface to test. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public interface MyInterface { + + String MY_CONSTANT = "constant"; + + void myMethod(); +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface2.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface2.java new file mode 100644 index 0000000..60c45b5 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface2.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +import org.nuiton.util.ApplicationConfig; + +/** + * Simple interface to test. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public interface MyInterface2 extends ApplicationConfig.OptionDef { + + String MY_CONSTANT = "constant"; + + void myMethod(); +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface3.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface3.java new file mode 100644 index 0000000..446135d --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/MyInterface3.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect; + +import org.nuiton.util.ApplicationConfig.OptionDef; + +/** + * Simple interface to test. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public interface MyInterface3 extends OptionDef, Iterable<MyInterface3> { + + String MY_CONSTANT = "constant"; + + void myMethod(); +} \ No newline at end of file diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java new file mode 100644 index 0000000..c037d0c --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/reflect/resolvers/ClassDescriptorResolverFromJavaFileTest.java @@ -0,0 +1,397 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.reflect.resolvers; + +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +import jaxx.compiler.reflect.FieldDescriptor; +import jaxx.compiler.reflect.MyAbstractClass; +import jaxx.compiler.reflect.MyChildClass; +import jaxx.compiler.reflect.MyChildClass2; +import jaxx.compiler.reflect.MyClass; +import jaxx.compiler.reflect.MyEnum; +import jaxx.compiler.reflect.MyInterface; +import jaxx.compiler.reflect.MyInterface2; +import jaxx.compiler.reflect.MyInterface3; +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 org.nuiton.util.ApplicationConfig; +import org.nuiton.util.FileUtil; + +import java.io.File; +import java.io.Serializable; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +/** + * Tests the {@link ClassDescriptorResolverFromJavaFile} resolver. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ClassDescriptorResolverFromJavaFileTest { + + /** log */ + protected static final Log log = + LogFactory.getLog(ClassDescriptorResolverFromJavaFileTest.class); + + + /** test source root directory */ + public static File testSourceRoot; + + @BeforeClass + public static void initBaseDir() { + // get maven env basedir + String basedir = System.getenv("basedir"); + if (basedir == null) { + + // says basedir is where we start tests. + basedir = new File("").getAbsolutePath(); + } + testSourceRoot = FileUtil.getFileFromPaths(new File(basedir), + "src", + "test", + "java"); + } + + protected ClassDescriptor getDescriptor(Class<?> klass) throws Exception { + + String javaFilePath = + klass.getName().replaceAll("\\.", File.separator) + ".java"; + File src = new File(testSourceRoot, javaFilePath); + Assert.assertTrue(src.exists()); + + if (log.isDebugEnabled()) { + log.debug("file to parse " + src); + } + + ClassDescriptorResolverFromJavaFile resolver = + new ClassDescriptorResolverFromJavaFile(); + + ClassDescriptor descriptor = + resolver.resolvDescriptor(klass.getName(), src.toURI().toURL()); + + Assert.assertNotNull(descriptor); + if (log.isDebugEnabled()) { + log.debug("loaded " + descriptor); + } + Assert.assertEquals(klass.getName(), descriptor.getName()); + return descriptor; + } + + @Test + public void parseClassDescriptorResolverFromJavaFileTest() throws Exception { + + ClassDescriptor descriptor = + getDescriptor(ClassDescriptorResolverFromJavaFileTest.class); + + assertInterfaces(descriptor); + assertSuperClass(descriptor, Object.class); + } + + + @Test + public void parseMyEnum() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyEnum.class); + + assertInterfaces(descriptor, Serializable.class, MyInterface.class); + assertInterfaces(descriptor, MyEnum.class.getInterfaces()); + assertSuperClass(descriptor, Enum.class); + + assertIsAssignableFrom( + descriptor, + Serializable.class, + MyInterface.class, + Enum.class + ); + } + + @Test + public void parseMyInterface() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyInterface.class); + + assertInterfaces(descriptor); + assertSuperClass(descriptor, null); + } + + @Test + public void parseMyInterface2() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyInterface2.class); + + assertInterfaces(descriptor, MyInterface2.class.getInterfaces()); + assertInterfaces(descriptor, ApplicationConfig.OptionDef.class); + assertSuperClass(descriptor, null); + } + + + @Test + public void parseMyInterface3() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyInterface3.class); + + assertInterfaces(descriptor, MyInterface3.class.getInterfaces()); + assertInterfaces(descriptor, ApplicationConfig.OptionDef.class, + Iterable.class); + assertSuperClass(descriptor, null); + } + + @Test + public void parseMyAbstractClass() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyAbstractClass.class); + + assertInterfaces(descriptor, MyAbstractClass.class.getInterfaces()); + assertInterfaces(descriptor, MyInterface.class); + assertSuperClass(descriptor, Object.class); + assertIsAssignableFrom(descriptor, MyInterface.class, Object.class); + } + + @Test + public void parseMyClass() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyClass.class); + + assertInterfaces(descriptor, MyClass.class.getInterfaces()); + assertInterfaces(descriptor, Serializable.class); + assertSuperClass(descriptor, MyAbstractClass.class); + assertIsAssignableFrom(descriptor, + Serializable.class, + MyInterface.class, + MyAbstractClass.class + ); + + assertDeclaredField( + descriptor, + "serialVersionUID", + long.class, + Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC + ); + + assertDeclaredField( + descriptor, + "myPrivateStringField", + String.class, + Modifier.PRIVATE | Modifier.FINAL + ); + + assertDeclaredField( + descriptor, + "myProtectedStringField", + String.class, + Modifier.PROTECTED + ); + + assertField( + descriptor, + "myPublicStringField", + String.class, + Modifier.PUBLIC + ); + } + + @Test + public void parseMyChildClass() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyChildClass.class); + + assertInterfaces(descriptor, MyChildClass.class.getInterfaces()); + assertInterfaces(descriptor, Cloneable.class); + assertSuperClass(descriptor, MyClass.class); + assertIsAssignableFrom(descriptor, + Serializable.class, + MyInterface.class, + MyAbstractClass.class, + MyClass.class + ); + + assertDeclaredField( + descriptor, + "serialVersionUID", + long.class, + Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC + ); + + assertDeclaredField( + descriptor, + "myPrivateStringField", + String.class, + Modifier.PRIVATE | Modifier.FINAL + ); + + assertDeclaredField( + descriptor, + "myProtectedStringField", + String.class, + Modifier.PROTECTED + ); + + assertDeclaredField( + descriptor, + "childProperty", + String.class, + Modifier.PROTECTED + ); + + assertField( + descriptor, + "myPublicStringField", + String.class, + Modifier.PUBLIC + ); + + } + + @Test + public void parseMyChildClass2() throws Exception { + + ClassDescriptor descriptor = getDescriptor(MyChildClass2.class); + + assertInterfaces(descriptor, MyChildClass2.class.getInterfaces()); + assertSuperClass(descriptor, MyClass.class); + assertIsAssignableFrom(descriptor, + Serializable.class, + MyInterface.class, + MyAbstractClass.class, + MyClass.class + ); + + assertDeclaredField( + descriptor, + "serialVersionUID", + long.class, + Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC + ); + + assertDeclaredField( + descriptor, + "myPrivateStringField", + String.class, + Modifier.PRIVATE | Modifier.FINAL + ); + + assertDeclaredField( + descriptor, + "myProtectedStringField", + String.class, + Modifier.PROTECTED + ); + + assertField( + descriptor, + "myPublicStringField", + String.class, + Modifier.PUBLIC + ); + + } + + public static void assertField(ClassDescriptor descriptor, + String fieldName, + Class<?> fieldType, + int fieldModifiers) throws NoSuchFieldException { + FieldDescriptor fieldDescriptor = + descriptor.getFieldDescriptor(fieldName); + Assert.assertNotNull(fieldDescriptor); + ClassDescriptor type = fieldDescriptor.getType(); + Assert.assertNotNull(type); + Assert.assertEquals(fieldType.getName(), type.getName()); + int modifiers = fieldDescriptor.getModifiers(); + Assert.assertEquals(fieldModifiers, modifiers); + } + + public static void assertDeclaredField(ClassDescriptor descriptor, + String fieldName, + Class<?> fieldType, + int fieldModifiers) throws NoSuchFieldException { + FieldDescriptor fieldDescriptor = + descriptor.getDeclaredFieldDescriptor(fieldName); + Assert.assertNotNull(fieldDescriptor); + ClassDescriptor type = fieldDescriptor.getType(); + Assert.assertNotNull(type); + Assert.assertEquals(fieldType.getName(), type.getName()); + int modifiers = fieldDescriptor.getModifiers(); + Assert.assertEquals(fieldModifiers, modifiers); + } + + + public static void assertIsAssignableFrom(ClassDescriptor descriptor, + Class<?>... interfaces) { + + for (Class<?> anInterface : interfaces) { + ClassDescriptor descriptor2 = + ClassDescriptorHelper.getClassDescriptor(anInterface); + Assert.assertNotNull(descriptor2); + boolean value = descriptor2.isAssignableFrom(descriptor); + Assert.assertTrue( + anInterface + " should be assignable from " + descriptor, + value + ); + } + } + + public static void assertInterfaces(ClassDescriptor descriptor, + Class<?>... interfaces) { + ClassDescriptor[] descriptors = descriptor.getInterfaces(); + Assert.assertEquals(interfaces.length, descriptors.length); + + List<String> doFind = new ArrayList<String>(); + for (Class<?> anInterface : interfaces) { + doFind.add(anInterface.getName()); + } + + for (ClassDescriptor descriptor1 : descriptors) { + String name = descriptor1.getName(); + Assert.assertTrue(doFind.contains(name)); + doFind.remove(name); + } + Assert.assertTrue( + "The follwing interfaces were not find found : " + doFind, + doFind.isEmpty() + ); + } + + public static void assertSuperClass(ClassDescriptor descriptor, + Class<?> superClass) { + ClassDescriptor superDescriptor = descriptor.getSuperclass(); + if (superClass == null) { + Assert.assertNull( + "Should be null but was " + superDescriptor, + superDescriptor + ); + } else { + Assert.assertNotNull(superDescriptor); + Assert.assertEquals(superClass.getName(), superDescriptor.getName()); + } + + } + +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/tags/TagManagerTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/tags/TagManagerTest.java new file mode 100644 index 0000000..25c72db --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/tags/TagManagerTest.java @@ -0,0 +1,171 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.tags; + +import jaxx.compiler.CompilerConfiguration; +import jaxx.compiler.DefaultCompilerConfiguration; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXFactory; +import jaxx.compiler.reflect.ClassDescriptor; +import jaxx.compiler.reflect.ClassDescriptorHelper; +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; + +public class TagManagerTest { + + protected static CompilerConfiguration configuration; + + protected JAXXCompiler compiler; + + public static class TestHandler extends DefaultObjectHandler { + + public TestHandler(ClassDescriptor beanClass) { + super(beanClass); + } + } + + @BeforeClass + public static void init() throws Exception { + if (configuration == null) { + configuration = new DefaultCompilerConfiguration(); + } +// TagManager.reset(); + JAXXFactory.setConfiguration(configuration); + JAXXFactory.initFactory(); + + } + + @Before + public void setUp() { + JAXXFactory.newDummyEngine(); + compiler = JAXXFactory.newDummyCompiler(JAXXCompiler.class.getClassLoader()); +// compiler = new JAXXCompiler(JAXXCompiler.class.getClassLoader()); + compiler.addImport("javax.swing.*"); + + } + + @Test + public void testRegisterBean() { + TagManager.registerBean(ClassDescriptorHelper.getClassDescriptor(InputStream.class), TestHandler.class); + + Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorHelper.getClassDescriptor(InputStream.class)) instanceof TestHandler); + Assert.assertTrue(TagManager.getTagHandler(ClassDescriptorHelper.getClassDescriptor(FileInputStream.class)) instanceof TestHandler); + } + + @Test + public void testRegisterDefaultNamespace() { + + TagManager.registerBean(ClassDescriptorHelper.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.*"); + init(); + 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("ButtonGroup is not aliased to jaxx.runtime.swing.JAXXButtonGroup", "jaxx.runtime.swing.JAXXButtonGroup", TagManager.resolveClassName("ButtonGroup", compiler)); + Assert.assertEquals("javax.swing.ButtonGroup is not aliased to jaxx.runtime.swing.JAXXButtonGroup", "jaxx.runtime.swing.JAXXButtonGroup", TagManager.resolveClassName("javax.swing.ButtonGroup", compiler)); + } +} diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/ColorConverterTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/ColorConverterTest.java new file mode 100644 index 0000000..1db2289 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/ColorConverterTest.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.awt.*; + +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 diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/InsetsConverterTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/InsetsConverterTest.java new file mode 100644 index 0000000..668c617 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/InsetsConverterTest.java @@ -0,0 +1,74 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +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 diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/PrimitiveConverterTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/PrimitiveConverterTest.java new file mode 100644 index 0000000..735d4d3 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/PrimitiveConverterTest.java @@ -0,0 +1,137 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.compiler.types; + +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 diff --git a/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/TypeManagerTest.java b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/TypeManagerTest.java new file mode 100644 index 0000000..8829366 --- /dev/null +++ b/trunk/jaxx-compiler/src/test/java/jaxx/compiler/types/TypeManagerTest.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Compiler + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.compiler.types; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created: 29 nov. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class TypeManagerTest { + + @Test + public void testHexValue() { + + String actual; + String expected; + + actual = TypeManager.convertVariableNameToConstantName("azerty"); + expected = "AZERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("azertyQwerty"); + expected = "AZERTY_QWERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("1azertyQwerty"); + expected = "1AZERTY_QWERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("$1azertyQwerty"); + expected = "$1AZERTY_QWERTY"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("binding_$hum"); + expected = "BINDING_$HUM"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("BINding_$hum"); + expected = "BINDING_$HUM"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("BINding_$Hum"); + expected = "BINDING_$HUM"; + Assert.assertEquals(expected, actual); + + actual = TypeManager.convertVariableNameToConstantName("!BINding_$Hum"); + expected = "NOT_BINDING_$HUM"; + Assert.assertEquals(expected, actual); + } + +} diff --git a/trunk/jaxx-compiler/src/test/resources/log4j.properties b/trunk/jaxx-compiler/src/test/resources/log4j.properties new file mode 100644 index 0000000..524ae1d --- /dev/null +++ b/trunk/jaxx-compiler/src/test/resources/log4j.properties @@ -0,0 +1,32 @@ +### +# #%L +# JAXX :: Compiler +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +# 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=INFO diff --git a/trunk/jaxx-demo/LICENSE.txt b/trunk/jaxx-demo/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/jaxx-demo/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/jaxx-demo/README.txt b/trunk/jaxx-demo/README.txt new file mode 100644 index 0000000..d2e50d3 --- /dev/null +++ b/trunk/jaxx-demo/README.txt @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install diff --git a/trunk/jaxx-demo/changelog.txt b/trunk/jaxx-demo/changelog.txt new file mode 100644 index 0000000..3db2e3c --- /dev/null +++ b/trunk/jaxx-demo/changelog.txt @@ -0,0 +1,2 @@ +1.7.2 + * 20091003 [chemit] - initial release (insparated from obsolote jaxx-example module) diff --git a/trunk/jaxx-demo/pom.xml b/trunk/jaxx-demo/pom.xml new file mode 100644 index 0000000..426e2cf --- /dev/null +++ b/trunk/jaxx-demo/pom.xml @@ -0,0 +1,465 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jaxx</artifactId> + <version>2.5.2</version> + </parent> + + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-demo</artifactId> + + <dependencies> + + <!-- sibiling dependencies --> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-validator</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-widgets</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-core</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <!-- test dependencies --> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + <scope>test</scope> + <classifier>tests</classifier> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <dependency> + <groupId>com.fifesoft</groupId> + <artifactId>rsyntaxtextarea</artifactId> + </dependency> + + <!--dependency> + <groupId>org.nuiton.thirdparty</groupId> + <artifactId>rsyntaxtextarea</artifactId> + </dependency--> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>runtime</scope> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JAXX :: Demo</name> + <description>JAXX Demo</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <properties> + + <maven.jar.main.class>jaxx.demo.RunDemo</maven.jar.main.class> + + <jaxx.addProjectClassPath>true</jaxx.addProjectClassPath> + <jaxx.addSourcesToClassPath>true</jaxx.addSourcesToClassPath> + <jaxx.autoImportCss>true</jaxx.autoImportCss> + + <!-- generate license bundled files --> + <license.generateBundle>true</license.generateBundle> + + </properties> + + <build> + + <resources> + <resource> + <directory>src/main/filters</directory> + <filtering>true</filtering> + <includes> + <include>jaxx-demo.properties</include> + </includes> + </resource> + <resource> + <directory>src/main/resources</directory> + <includes> + <include>**/*</include> + </includes> + </resource> + <resource> + <directory>src/main/java</directory> + <includes> + <include>**/*</include> + </includes> + </resource> + </resources> + + <pluginManagement> + <plugins> + + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <useUniqueVersions>true</useUniqueVersions> + <addClasspath>true</addClasspath> + <classpathPrefix>./lib/</classpathPrefix> + </manifest> + </archive> + </configuration> + <executions> + <execution> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + + </pluginManagement> + + <plugins> + + <plugin> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <version>${project.version}</version> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <configuration> + <treateDefaultEntry>true</treateDefaultEntry> + <entries> + <entry> + <basedir>${maven.gen.dir}/java/</basedir> + </entry> + </entries> + </configuration> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + <goal>bundle</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <outputDirectory>${project.build.directory}/lib</outputDirectory> + <silent>true</silent> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>license-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-licenses</id> + <goals> + <goal>update-project-license</goal> + <goal>add-third-party</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + + <profiles> + + <profile> + <id>jnlpwar-profile</id> + <dependencies> + <dependency> + <groupId>org.codehaus.mojo</groupId> + <artifactId>webstart-jnlp-servlet</artifactId> + <version>${webstartPluginVersion}</version> + </dependency> + </dependencies> + <build> + <plugins> + <!-- key store secrets availables --> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>helper-maven-plugin</artifactId> + <executions> + <execution> + <id>get-keystore</id> + <goals> + <goal>share-server-secret</goal> + </goals> + <phase>package</phase> + <configuration> + <serverId>codelutin-keystore</serverId> + <privateKeyOut>keystorepath</privateKeyOut> + <passwordOut>keystorepass</passwordOut> + <usernameOut>keyalias</usernameOut> + <passphraseOut>keypass</passphraseOut> + </configuration> + </execution> + </executions> + </plugin> + + <!-- make webstart --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>webstart-maven-plugin</artifactId> + <executions> + <execution> + <id>generate-jnlp</id> + <phase>package</phase> + <goals> + <goal>jnlp-download-servlet</goal> + </goals> + <configuration> + <outputDirectoryName>jnlp</outputDirectoryName> + <excludeTransitive>false</excludeTransitive> + <libPath>apps</libPath> + <outputJarVersions>true</outputJarVersions> + <!--dependencies> + <includes> + <include>be.irisnet.nova:nova-common</include> + </includes> + </dependencies--> + <jnlpFiles> + <jnlpFile> + <!--templateFilename>template_com.jnlp</templateFilename> + <outputFilename>client_com.jnlp</outputFilename--> + <jarResources> + <jarResource> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-demo</artifactId> + <version>${project.version}</version> + <mainClass>${maven.jar.main.class}</mainClass> + </jarResource> + </jarResources> + </jnlpFile> + </jnlpFiles> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + <!-- by default jnlp is only perform on a release stage when using the maven-release-plugin --> + <profile> + <id>release-jnlp-profile</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + <build> + <plugins> + <!-- key store secrets availables --> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>helper-maven-plugin</artifactId> + <executions> + <execution> + <id>get-keystore</id> + <goals> + <goal>share-server-secret</goal> + </goals> + <phase>package</phase> + <configuration> + <serverId>codelutin-keystore</serverId> + <privateKeyOut>keystorepath</privateKeyOut> + <passwordOut>keystorepass</passwordOut> + <usernameOut>keyalias</usernameOut> + <passphraseOut>keypass</passphraseOut> + </configuration> + </execution> + </executions> + </plugin> + + <!-- make webstart --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>webstart-maven-plugin</artifactId> + <executions> + <execution> + <id>generate-jnlp</id> + <phase>package</phase> + <goals> + <goal>jnlp-inline</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + + <!-- by default jnlp is only perform on a release stage when using the maven-release-plugin --> + <profile> + <id>reporting</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <reporting> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>webstart-maven-plugin</artifactId> + <version>${webstartPluginVersion}</version> + </plugin> + </plugins> + </reporting> + + </profile> + + <profile> + <id>staging-site-profile</id> + <activation> + <property> + <name>stagingSite</name> + <value>true</value> + </property> + </activation> + <properties> + <jnlp.codebase>http://maven-site.liosalfar/jaxx/jaxx-demo/jnlp + </jnlp.codebase> + </properties> + </profile> + + </profiles> + +</project> diff --git a/trunk/jaxx-demo/src/license/THIRD-PARTY.properties b/trunk/jaxx-demo/src/license/THIRD-PARTY.properties new file mode 100644 index 0000000..40dc3ca --- /dev/null +++ b/trunk/jaxx-demo/src/license/THIRD-PARTY.properties @@ -0,0 +1,19 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - BSD +# - BSD style +# - Common Public License Version 1.0 +# - GNU General Public License - Version 2 with the class path exception +# - GNU Lesser General Public License +# - LGPL 2.1 +# - Lesser General Public License (LGPL) +# - Lesser General Public License (LGPL) v 3.0 +# - MPL 1.1 +# - The Apache Software License, Version 2.0 +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Fri Jun 29 01:42:10 CEST 2012 +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 diff --git a/trunk/jaxx-demo/src/main/filters/jaxx-demo.properties b/trunk/jaxx-demo/src/main/filters/jaxx-demo.properties new file mode 100644 index 0000000..2ede049 --- /dev/null +++ b/trunk/jaxx-demo/src/main/filters/jaxx-demo.properties @@ -0,0 +1,34 @@ +### +# #%L +# JAXX :: Demo +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +application.name=${project.name} +application.version=${project.version} +application.site.url=http://maven-site.nuiton.org/jaxx/jaxx-demo +application.icon.path=/icons/jaxx.png +application.license.path=META-INF/${project.artifactId}-LICENSE.txt +application.third-party.path=META-INF/${project.artifactId}-THIRD-PARTY.txt +#licence.name=${project.licenses[0].license.name} +#licence.url=${project.licenses.0.url} +application.organisation.name=${project.organization.name} +application.organisation.url=${project.organization.url} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java new file mode 100644 index 0000000..24e6870 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoConfig.java @@ -0,0 +1,368 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo; + +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; +import java.util.Properties; +import javax.swing.KeyStroke; +import jaxx.demo.feature.nav.NavDemo; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ApplicationConfig; +import org.nuiton.util.Version; +import org.nuiton.util.VersionUtil; + +import static org.nuiton.i18n.I18n._; + +/** + * La configuration de l'application. + * <p/> + * Il s'agit de l'objet partagé par toutes les démos. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.7.2 + */ +public class DemoConfig extends ApplicationConfig { + + /** Logger */ + static private Log log = LogFactory.getLog(DemoConfig.class); + + /** + * le fichier de configuration de l'application avec les informations sur + * le projet (version, license,...) et la configuration des ui (icons, ...) + */ + public static final String APPLICATION_PROPERTIES = "/jaxx-demo.properties"; + + public static final String PROPERTY_FULLSCREEN = "fullscreen"; + + public static final String PROPERTY_LOCALE = "locale"; + + public static final String PROPERTY_FONT_SIZE = "fontSize"; + + public static final String PROPERTY_LOG_LEVEL = "logLevel"; + + public static final String PROPERTY_LOG_PATTERN_LAYOUT = "logPatternLayout"; + + public static final String PROPERTY_KEY_OPEN_CONFIG = "keyOpenConfig"; + + public DemoConfig() { + + setConfigFileName(Option.CONFIG_FILE.defaultValue); + + // chargement de la configuration interne + + InputStream stream = + getClass().getResourceAsStream(APPLICATION_PROPERTIES); + + Properties p = new Properties(); + try { + p.load(stream); + for (Object k : p.keySet()) { + String key = k + ""; + Object value = p.get(k); + if (log.isDebugEnabled()) { + log.debug("install properties " + k + " : " + value); + } + setDefaultOption(key, "" + value); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + for (Option o : Option.values()) { + setDefaultOption(o.key, o.defaultValue); + } + + // on supprime le stamp de snapshot s'il existe + String sVersion = VersionUtil.removeSnapshot( + getOption("application.version")); + Version version = VersionUtil.valueOf(sVersion); + setDefaultOption("version", version.getVersion()); + + installSaveUserAction(PROPERTY_FULLSCREEN, + PROPERTY_FONT_SIZE, + PROPERTY_LOCALE); + } + + public String getCopyrightText() { + return "Version " + getVersion() + " Codelutin @ 2008-2009"; + } + + /** @return la version de l'application. */ + public Version getVersion() { + Version option = getOption(Version.class, "version"); + return option; + } + + public boolean isFullScreen() { + Boolean result = getOptionAsBoolean(Option.FULL_SCREEN.key); + return result != null && result; + } + + public Locale getLocale() { + Locale result = getOption(Locale.class, Option.LOCALE.key); + return result; + } + + public String getDemoPath() { + String result = getOption(Option.DEMO_PATH.key); + return result; + } + + public Float getFontSize() { + Float result = getOption(Float.class, Option.FONT_SIZE.key); + return result; + } + + public String getLogLevel() { + String level = getOption(Option.LOG_LEVEL.key); + return level; + } + + public String getLogPatternLayout() { + String result = getOption(Option.LOG_PATTERN_LAYOUT.key); + return result; + } + + public KeyStroke getKeyOpenConfig() { + return getOptionAsKeyStroke(Option.KEY_OPEN_CONFIG.key); + } + + public void setFullscreen(boolean fullscreen) { + Object oldValue = null; + setOption(Option.FULL_SCREEN.key, fullscreen + ""); + firePropertyChange(PROPERTY_FULLSCREEN, oldValue, fullscreen); + } + + public void setLocale(Locale newLocale) { + setOption(Option.LOCALE.key, newLocale.toString()); + firePropertyChange(PROPERTY_LOCALE, null, newLocale); + } + + public void setFontSize(Float newFontSize) { + Float oldValue = getFontSize(); + if (log.isDebugEnabled()) { + log.debug("changing font-size to " + newFontSize); + } + setOption(Option.FONT_SIZE.key, newFontSize.toString()); + firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); + } + + public void setLogLevel(String logLevel) { + String oldValue = getLogLevel(); + setOption(Option.LOG_LEVEL.key, logLevel); + firePropertyChange(PROPERTY_LOG_LEVEL, oldValue, logLevel); + } + + public void setLogPatternLayout(String logPatternLayout) { + String oldValue = getLogPatternLayout(); + setOption(Option.LOG_PATTERN_LAYOUT.key, logPatternLayout); + firePropertyChange(PROPERTY_LOG_PATTERN_LAYOUT, oldValue, logPatternLayout); + } + + public void setKeyOpenConfig(KeyStroke keyStroke) { + KeyStroke oldValue = getKeyOpenConfig(); + setOption(Option.KEY_OPEN_CONFIG.key, keyStroke.toString()); + firePropertyChange(PROPERTY_KEY_OPEN_CONFIG, oldValue, keyStroke); + } + + /** + * Save configuration, in user home directory using the + * {@link #getConfigFileName}. Default, env and commande line note saved + */ + public void saveForUser() { + // shoudl we never save any conf ? + super.saveForUser(); + } + + public static final String[] DEFAULT_JAXX_PCS = { + PROPERTY_FULLSCREEN, + PROPERTY_LOCALE, + PROPERTY_FONT_SIZE, + ADJUSTING_PROPERTY + }; + + public void removeJaxxPropertyChangeListener() { + PropertyChangeListener[] toRemove; + toRemove = JAXXUtil.findJaxxPropertyChangeListener( + DEFAULT_JAXX_PCS, + getPropertyChangeListeners()); + if (toRemove == null || toRemove.length == 0) { + return; + } + if (log.isDebugEnabled()) { + log.debug("before remove : " + getPropertyChangeListeners().length); + log.debug("toRemove : " + toRemove.length); + } + for (PropertyChangeListener listener : toRemove) { + removePropertyChangeListener(listener); + } + if (log.isDebugEnabled()) { + log.debug("after remove : " + getPropertyChangeListeners().length); + } + } + + ////////////////////////////////////////////////// + // Toutes les options disponibles + ////////////////////////////////////////////////// + + public enum Option implements OptionDef { + + CONFIG_FILE( + CONFIG_FILE_NAME, + _("jaxxdemo.config.configFileName.description"), + "jaxxdemo", + String.class, + true, + true), + FULL_SCREEN( + "ui.fullscreen", + _("jaxxdemo.config.ui.fullscreen"), + "false", + Boolean.class, + false, + false), + LOCALE( + "ui." + PROPERTY_LOCALE, + _("jaxxdemo.config.ui.locale"), + Locale.FRANCE.toString(), + Locale.class, + false, + false), + FONT_SIZE( + "ui." + PROPERTY_FONT_SIZE, + _("jaxxdemo.config.ui.fontSize"), + "10f", + Float.class, + false, + false), + LOG_LEVEL( + "ui." + PROPERTY_LOG_LEVEL, + _("jaxxdemo.config.ui.logLevel"), + "INFO", + String.class, + false, + false), + LOG_PATTERN_LAYOUT( + "ui." + PROPERTY_LOG_PATTERN_LAYOUT, + _("jaxxdemo.config.ui.logPatternLayout"), + "%5p [%t] (%F:%L) %M - %m%n", + String.class, + false, + false), + KEY_OPEN_CONFIG( + "ui." + PROPERTY_KEY_OPEN_CONFIG, + _("jaxxdemo.config.ui.keyOpenConfig"), + "ctrl alt pressed S", + KeyStroke.class, + false, + false), + DEMO_PATH( + "ui.demo.path", + _("jaxxdemo.config.ui.demo.path"), + "jaxxdemo.tree/jaxxdemo.tree.component.jaxx/jaxxdemo.tree.component.jaxx.tree/" + NavDemo.class.getSimpleName(), + String.class, + false, + true); + + public final String key; + + public final String description; + + public String defaultValue; + + public final Class<?> type; + + public boolean _transient; + + public boolean _final; + + Option(String key, + String description, + String defaultValue, + Class<?> type, + boolean _transient, + boolean _final) { + this.key = key; + this.description = description; + this.defaultValue = defaultValue; + this.type = type; + this._final = _final; + this._transient = _transient; + } + + @Override + public boolean isFinal() { + return _final; + } + + @Override + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public void setTransient(boolean _transient) { + this._transient = _transient; + } + + @Override + public void setFinal(boolean _final) { + this._final = _final; + } + + @Override + public boolean isTransient() { + return _transient; + } + + @Override + public String getDefaultValue() { + return defaultValue; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getKey() { + return key; + } + + @Override + public Class<?> getType() { + return type; + } + + + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoPanel.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoPanel.jaxx new file mode 100644 index 0000000..e71c0fe --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoPanel.jaxx @@ -0,0 +1,59 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel id='top' abstract='true'> + + <import> + org.nuiton.util.StringUtil + </import> + + <script><![CDATA[ + +protected String[] getSources() { + if (DemoPanel.class.equals(getClass())) { + return StringUtil.EMPTY_STRING_ARRAY; + } + return new String[]{ getDefaultSource() }; +} + +protected String getDefaultSource() { + return getClass().getSimpleName() + ".jaxx"; +} + +public String getLabel() { + String name = getClass().getSimpleName(); + if (name.endsWith("Demo")) { + name = name.substring(0, name.length() - "Demo".length()); + } + return name; +} + +public String getDemoTabTitle() { + return getLabel() + " Demo"; +} + ]]> + </script> + +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoSources.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoSources.jaxx new file mode 100644 index 0000000..f90dd71 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoSources.jaxx @@ -0,0 +1,108 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel layout='{new BorderLayout()}'> + + <import> + jaxx.runtime.SwingUtil + jaxx.runtime.swing.FontSizor + + java.awt.RenderingHints + javax.swing.DefaultComboBoxModel + + org.fife.ui.rsyntaxtextarea.RSyntaxTextArea + </import> + + <script><![CDATA[ + +public void init() { + //fontSizor.setDefaultFontSize(getConfig().getFontSize()); + fontSizor.init(); + fontSizor.setCallBack(new Runnable() { + + @Override + public void run() { + log.info("update font size : " + fontSizor.getFontSize()); + getConfig().setFontSize(fontSizor.getFontSize()); + } + }); + handler.init(this); +} + +public DemoConfig getConfig() { + return getContextValue(DemoConfig.class); +} + +public void updateSource(ItemEvent event) { + setCurrentSource((String) sourceTabs.getSelectedItem()); + editor.setText(handler.getSourceContent(this, getCurrentSource())); + editor.setSyntaxEditingStyle(handler.getSourceEditingStyle(this, getCurrentSource())); + editor.setCaretPosition(0); +} + ]]> + </script> + + <DemoSourcesHandler id='handler'/> + + <Class id='incomingClass' javaBean='null' genericType='?'/> + + <String id='currentSource' javaBean='null'/> + + <java.util.List id='sources' genericType='String' javaBean='null'/> + + <JToolBar id='editorPaneHeader' + floatable='false' + borderPainted='false' + opaque='false' + constraints='BorderLayout.SOUTH'> + + <JComboBox id='sourceTabs' + model='{new DefaultComboBoxModel()}' + onItemStateChanged='if(event.getStateChange() == ItemEvent.SELECTED) { updateSource(event); }'/> + <javax.swing.Box.Filler + constructorParams='SwingUtil.newMinDimension(), SwingUtil.newMinDimension(), SwingUtil.newMaxXDimension()'/> + <FontSizor id='fontSizor' opaque='false' showFontSize='true' + fontSize='{getConfig().getFontSize()}'/> + <!--defaultFontSize='{getConfig().getFontSize()}' fontSize='{getConfig().getFontSize()}'/>--> + </JToolBar> + + <JScrollPane id='editorPane' columnHeaderView='{editorPaneHeader}' + constraints='BorderLayout.CENTER'> + <RSyntaxTextArea id='editor' + font-size='{getConfig().getFontSize()}' + minimumSize="{SwingUtil.newMinDimension()}" + textAntiAliasHint='{RenderingHints.KEY_ANTIALIASING.toString()}' + editable="false" + wrapStyleWord="false" + columns="80" + lineWrap="true"/> + <!--font-size='{updateSize(getFontSizor().getFontSize())}'--> + <!-- TC-20091221 : can not use binding since we want to do something after assigment... --> + <!--text='{handler.getSourceContent(DemoSources.this, getCurrentSource())}'--> + <!--syntaxEditingStyle='{handler.getSourceEditingStyle(DemoSources.this, getCurrentSource())}'--> + </JScrollPane> + + +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoSourcesHandler.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoSourcesHandler.java new file mode 100644 index 0000000..dad898d --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoSourcesHandler.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo; + +import jaxx.runtime.SwingUtil; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * Created: 21 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class DemoSourcesHandler { + + /** Logger */ + private static final Log log = LogFactory.getLog(DemoSourcesHandler.class); + + protected static Map<String, String> sourcesCache; + + public static Map<String, String> getSourcesCache() { + if (sourcesCache == null) { + sourcesCache = new TreeMap<String, String>(); + } + return sourcesCache; + } + + public String getSourceContent(DemoSources ui, String name) { + if (name == null) { + return ""; + } + String result = getSourcesCache().get(name); + if (result == null) { + try { + if (log.isDebugEnabled()) { + log.debug(name + " from " + ui.getIncomingClass()); + } + String path = name.substring(ui.getIncomingClass().getPackage().getName().length() + 1); + result = IOUtils.toString(ui.getIncomingClass().getResourceAsStream(path)); + if (log.isDebugEnabled()) { + log.debug("source [" + name + "], loaded content =\n" + result); + } + } catch (Exception e) { + log.error("could not load file " + name, e); + result = "could not load file " + name; + } + getSourcesCache().put(name, result); + } + return result; + } + + public String getSourceEditingStyle(DemoSources ui, String source) { + + if (source == null) { + return ""; + } + ui.getEditor().setFractionalFontMetricsEnabled(true); + String s = null; + if (source.matches(".*\\.jaxx") || source.matches(".*\\.xml")) { + s = RSyntaxTextArea.SYNTAX_STYLE_XML; + } else if (source.matches(".*\\.java")) { + s = RSyntaxTextArea.SYNTAX_STYLE_JAVA; + } else if (source.matches(".*\\.css")) { + s = RSyntaxTextArea.SYNTAX_STYLE_CSS; + } + if (log.isDebugEnabled()) { + log.debug("source [" + source + "] style = " + s); + } + return s; + } + + public void init(DemoSources ui) { + List<String> sources = ui.getSources(); + if (sources == null) { + return; + } + + List<String> toFill = new ArrayList<String>(); + String prefix = ui.getIncomingClass() == null ? "" : + ui.getIncomingClass().getPackage().getName() + "."; + for (String source : sources) { + String path = prefix + source; + if (log.isDebugEnabled()) { + log.debug("adding resource " + path); + } + toFill.add(path); + } + SwingUtil.fillComboBox(ui.getSourceTabs(), toFill, null); + if (!toFill.isEmpty()) { + ui.getSourceTabs().setSelectedIndex(0); + } + toFill.clear(); + ui.getEditor().discardAllEdits(); + } + +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoTab.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoTab.jaxx new file mode 100644 index 0000000..65e3ee0 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoTab.jaxx @@ -0,0 +1,62 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JTabbedPane id='top'> + + <import> + java.util.Arrays + javax.swing.SwingUtilities + </import> + + <script><![CDATA[ + +private void $afterCompleteSetup() { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + if (demoPanel.getSources().length == 0) { + top.remove(sourceTabs); + return; + } + sourceTabs.init(); + } + }); +} + ]]> + </script> + + <tab id='tabDemoPanel' title='{demoPanel.getDemoTabTitle()}'> + <DemoPanel id='demoPanel' + initializer='getContextValue(DemoPanel.class, "content")'/> + </tab> + + <tab id='tabDemoSources' title='Sources'> + <DemoSources id='sourceTabs' + sources='{Arrays.asList(demoPanel.getSources())}' + incomingClass='{demoPanel.getClass()}' + constructorParams='demoPanel'/> + </tab> +</JTabbedPane> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUI.css b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUI.css new file mode 100644 index 0000000..0696e61 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUI.css @@ -0,0 +1,190 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +JToolBar { + borderPainted:false; + floatable:false; + opaque:false; +} + +JSplitPane { + oneTouchExpandable:true; + continuousLayout:true; + dividerSize:6; +} + +#mainFrame { + title:"JAXX Demo"; + iconImage:{SwingUtil.createIcon(getConfig().getOption("application.icon.path")).getImage()}; + undecorated:{getConfig().isFullScreen()}; +} + +#menu { + _help:{"ui.main.menu"}; +} + +#menuFile { + text:"jaxxdemo.menu.file"; + mnemonic:F; + _help:{"ui.main.menu.file"}; +} + +#menuFileConfiguration { + text:"jaxxdemo.action.configuration"; + toolTipText:"jaxxdemo.action.configuration.tip"; + actionIcon:"config"; + mnemonic:C; + _help:{"ui.main.menu.file.configuration"}; +} + +#menuFileLanguage { + text:"jaxxdemo.menu.file.locale"; + toolTipText:"jaxxdemo.menu.file.locale"; + actionIcon:"translate"; + mnemonic:C; + _help:{"ui.main.menu.file.locale"}; +} + + +#menuFileLanguageFR { + text:"jaxxdemo.action.locale.fr"; + toolTipText:"jaxxdemo.action.locale.fr.tip"; + actionIcon:"i18n-fr"; + enabled:{!acceptLocale(getConfig().getLocale(), "fr_FR")}; + mnemonic:F; + _help:{"ui.main.menu.file.locale.fr"}; +} + +#menuFileLanguageUK { + text:"jaxxdemo.action.locale.uk"; + toolTipText:"jaxxdemo.action.locale.uk.tip"; + actionIcon:"i18n-uk"; + enabled:{!acceptLocale(getConfig().getLocale(), "en_GB")}; + mnemonic:U; + _help:{"ui.main.menu.file.locale.uk"}; +} + +#menuFileFullscreen { + text:"jaxxdemo.action.fullscreen"; + toolTipText:"jaxxdemo.action.fullscreen.tip"; + actionIcon:"fullscreen"; + mnemonic:P; + visible:{!isUndecorated()}; + _help:{"ui.main.menu.file.fullscreen"}; +} + +#menuFileNormalscreen { + text:"jaxxdemo.action.normalscreen"; + toolTipText:"jaxxdemo.action.normalscreen.tip"; + actionIcon:"leave-fullscreen"; + mnemonic:N; + visible:{isUndecorated()}; +_help:{"ui.main.menu.file.leave-fullscreen"}; +} + +#menuFileExit { + text:"jaxxdemo.action.exit"; + toolTipText:"jaxxdemo.action.exit.tip"; + actionIcon:"exit"; + mnemonic:X; + _help:{"ui.main.menu.file.exit"}; +} + +#menuLogs { + text:"jaxxdemo.menu.showLogs"; + _help:{"ui.main.menu.showLogs"}; +} + +#menuHelp { + text:"jaxxdemo.menu.help"; + mnemonic:e; + _help:{"ui.main.menu.help"}; +} + +#menuHelpHelp { + text:"jaxxdemo.action.help"; + toolTipText:"jaxxdemo.action.help.tip"; + actionIcon:"help"; + mnemonic:e; + _help:{"ui.main.menu.help.help"}; +} + +#menuHelpSite { + text:"jaxxdemo.action.site"; + toolTipText:"jaxxdemo.action.site.tip"; + actionIcon:"site"; + mnemonic:s; + _help:{"ui.main.menu.help.site"}; +} + +#menuHelpAbout { + text:"jaxxdemo.action.about"; + toolTipText:"jaxxdemo.action.about.tip"; + actionIcon:"about"; + mnemonic:A; + _help:{"ui.main.menu.help.about"}; +} + +#showHelp { + toolTipText:"jaxxdemo.action.showHelp.tip"; + actionIcon:"show-help"; + borderPainted:false; + visible:true; +} + +#navigationPane { + border:{null}; + minimumSize:{new Dimension(230,0)}; + horizontalScrollBarPolicy:{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}; +} + +#navigation { + rootVisible:false; + showsRootHandles:false; + largeModel:true; + font-size:11; + model:{getTreeHelper().createModel()}; + cellRenderer:{new DemoCellRenderer(getTreeHelper().getDataProvider())}; +} + +#splitpane { + orientation:{JSplitPane.HORIZONTAL_SPLIT}; + _help:{"ui.main.body.db"}; + resizeWeight:1.0; +} + +#contentLayout { + useOnlyVisibleComponentDimension:true; +} + +#content { + layout:{contentLayout}; + _help:{"ui.main.body.db.view.content"}; +} +/* +#toolbar { + layout:{new BoxLayout(toolbar, 0)}; + _help:{"ui.main.toolbar"}; +}*/ diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx new file mode 100644 index 0000000..903ca19 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUI.jaxx @@ -0,0 +1,114 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<JFrame id='mainFrame' width='1024' height='800' + decorator='help' + onWindowClosing='getHandler().close(mainFrame)'> + + <import> + jaxx.demo.tree.DemoTreeHelper + jaxx.demo.tree.DemoCellRenderer + + jaxx.runtime.SwingUtil + jaxx.runtime.swing.CardLayout2 + jaxx.runtime.swing.StatusMessagePanel + + java.awt.Dimension + java.util.Locale + </import> + + <CardLayout2 id='contentLayout'/> + + <DemoConfig id='config' initializer='getContextValue(DemoConfig.class)'/> + + <DemoUIHandler id='handler' + initializer='getContextValue(DemoUIHandler.class)'/> + + <DemoTreeHelper id='treeHelper' + initializer='getContextValue(DemoTreeHelper.class)'/> + + + <script><![CDATA[ + +public boolean acceptLocale(Locale l, String expected) { + return l !=null && l.toString().equals(expected); +} + +private void $afterCompleteSetup() { + getHandler().initUI(this); +} +]]> + </script> + + <JMenuBar id='menu'> + + <JMenu id='menuFile'> + <JMenuItem id='menuFileConfiguration' + onActionPerformed="getHandler().showConfig(this)"/> + <JMenu id='menuFileLanguage'> + <JMenuItem id='menuFileLanguageFR' + onActionPerformed="getHandler().changeLanguage(this, Locale.FRANCE)"/> + <JMenuItem id='menuFileLanguageUK' + onActionPerformed="getHandler().changeLanguage(this, Locale.UK)"/> + </JMenu> + <JSeparator/> + <JMenuItem id='menuFileFullscreen' + onActionPerformed="getHandler().changeScreen(this, true)"/> + <JMenuItem id='menuFileNormalscreen' + onActionPerformed="getHandler().changeScreen(this, false)"/> + <JSeparator/> + <JMenuItem id='menuFileExit' + onActionPerformed="getHandler().close(this)"/> + </JMenu> + + <JMenu id='menuHelp'> + <JMenuItem id='menuLogs' + onActionPerformed="getHandler().showLogs(this)"/> + <JMenuItem id='menuHelpHelp' + onActionPerformed="getHandler().showHelp(this, null)"/> + <JMenuItem id='menuHelpSite' + onActionPerformed="getHandler().gotoSite(this)"/> + <JMenuItem id='menuHelpAbout' + onActionPerformed="getHandler().showAbout(this)"/> + </JMenu> + + </JMenuBar> + + <JPanel id='mainPane' layout='{new BorderLayout()}'> + + <JSplitPane id='splitPane' constraints='BorderLayout.CENTER'> + <JScrollPane id='navigationPane'> + <JTree id='navigation'/> + </JScrollPane> + + <JPanel id='content'/> + + </JSplitPane> + + <StatusMessagePanel id='p' constraints='BorderLayout.SOUTH'/> + + </JPanel> +</JFrame> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUIHandler.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUIHandler.java new file mode 100644 index 0000000..bffd8b4 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/DemoUIHandler.java @@ -0,0 +1,578 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/** + * *##% + * JAXX Demo + * Copyright (C) 2008 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* + */ +package jaxx.demo; + +import java.awt.Component; +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Constructor; +import java.net.URL; +import java.util.Arrays; +import java.util.Locale; +import javax.swing.AbstractAction; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import jaxx.demo.tree.DemoNode; +import jaxx.demo.tree.DemoTreeHelper; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.context.DefaultApplicationContext; +import jaxx.runtime.context.JAXXContextEntryDef; +import jaxx.runtime.context.JAXXInitialContext; +import jaxx.runtime.swing.AboutPanel; +import jaxx.runtime.swing.ErrorDialogUI; +import jaxx.runtime.swing.editor.config.ConfigUIHelper; +import jaxx.runtime.swing.log.JAXXLog4jUI; +import jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; +import org.nuiton.util.decorator.DecoratorProvider; + +import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; + +/** + * Le handler de l'ui principale. + * + * @author tchemit <chemit@codelutin.com> + * @see DemoUI + */ +public class DemoUIHandler { //implements JAXXHelp { + + /** Logger */ + static private Log log = LogFactory.getLog(DemoUIHandler.class); + + static final JAXXContextEntryDef<DemoUI> MAIN_UI_ENTRY_DEF = + JAXXUtil.newContextEntryDef("mainui", DemoUI.class); + + public static final String OPEN_CONFIG_ACTION = "openConfig"; + + /** + * Methode pour initialiser l'ui principale sans l'afficher. + * + * @param rootContext le context applicatif + * @param config la configuration a utiliser + * @return l'ui instancie et initialisee mais non visible encore + */ + public DemoUI initUI(DefaultApplicationContext rootContext, DemoConfig config) { + + if (log.isDebugEnabled()) { + log.debug("fullscreen ? " + config.isFullScreen()); + } + DecoratorProvider decoratorProvider = + rootContext.getContextValue(DecoratorProvider.class); + + if (!config.getLocale().equals(I18n.getDefaultLocale())) { + if (log.isInfoEnabled()) { + log.info("re-init I18n with locale " + config.getLocale()); + } + // change i18n language + I18n.setDefaultLocale(config.getLocale()); + // reload decorators + decoratorProvider.reload(); + } + + // create restrict context for ui + JAXXInitialContext context = new JAXXInitialContext(); + + // share handler + context.add(this); + + // share tree helper + context.add(rootContext.getContextValue(DemoTreeHelper.class)); + + // share config + context.add(rootContext.getContextValue(DemoConfig.class)); + + // share a unique DecoratorProvider + context.add(decoratorProvider); + + // share a unique DecoratorProviderListCellRenderer + context.add(new DecoratorProviderListCellRenderer(decoratorProvider)); + + // instanciate ui + DemoUI ui = new DemoUI(context); + + // add key strokes + addKeyStrokes(ui, config); + + // keep it in root context + MAIN_UI_ENTRY_DEF.setContextValue(rootContext, ui); + + // synch to error dialog + ErrorDialogUI.init(ui); + + // set fullscreen propery on main ui + ui.getGraphicsConfiguration().getDevice().setFullScreenWindow(config.isFullScreen() ? ui : null); + + return ui; + } + + protected void addKeyStrokes(final DemoUI ui, DemoConfig config) { + + // Use WHEN_IN_FOCUSED_WINDOW to don't have focus check for binding keys + JPanel mainPane = ui.getMainPane(); + mainPane.getActionMap().put(OPEN_CONFIG_ACTION, new AbstractAction() { + + @Override + public void actionPerformed(ActionEvent e) { + showConfig(ui); + } + }); + final InputMap inputMap = mainPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + config.addPropertyChangeListener(DemoConfig.PROPERTY_KEY_OPEN_CONFIG, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + KeyStroke oldValue = (KeyStroke) evt.getOldValue(); + inputMap.remove(oldValue); + setShowConfigInputMap(inputMap, (KeyStroke) evt.getNewValue()); + } + }); + setShowConfigInputMap(inputMap, config.getKeyOpenConfig()); + } + + protected void setShowConfigInputMap(InputMap inputMap, KeyStroke keyStroke) { + inputMap.put(keyStroke, OPEN_CONFIG_ACTION); + } + + public void initUI(final DemoUI ui) { + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener listener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + DemoNode node = (DemoNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select node " + node); + } + + if (node == null || node.isStringNode()) { + + // noeud de présentation, rien a faire + return; + } + showUI(ui, node.getInternalClass()); + } + }; + + JTree tree = ui.getNavigation(); + + ui.getTreeHelper().setUI(tree, true, listener); + + // auto-expand node when selected + SwingUtil.addExpandOnClickListener(tree); + + } + + protected void showUI(DemoUI ui, Class<?> type) { + + JPanel content = ui.getContent(); + + String constraints = type.getName(); + + log.info("Show for " + constraints); + + // Verify if instance is existing + DemoTab demoContent = getContentIfExist(ui, constraints); + + if (demoContent == null) { + + log.info("Will instanciate a new " + constraints); + try { + // Get constructor + Constructor<?> constructor = + type.getConstructor(JAXXContext.class); + + JAXXInitialContext tx = + new JAXXInitialContext().add(ui.getDelegateContext()); + + DemoPanel panel = (DemoPanel) constructor.newInstance(tx); + + log.info("Demo panel to use : " + panel); + + demoContent = new DemoTab(tx.add("content", panel)); + + } catch (Exception eee) { + log.error(eee, eee); + ErrorDialogUI.showError(eee); + } + + // Add to content panel + content.add(demoContent, constraints); + } + + // show ui + ui.getContentLayout().show(content, constraints); + } + +// Get content if exist in content, else return null + + protected <E extends Component> E getContentIfExist(DemoUI ui, String constraints) { + if (log.isDebugEnabled()) { + log.debug("Get content if exist " + constraints); + } + if (!ui.getContentLayout().contains(constraints)) { + return null; + } + return (E) ui.getContentLayout().getComponent(ui.getContent(), constraints); + } + + public void displayUI(final DemoUI ui, final String[] nodePath) { + + // expend all nodes of the demo tree + SwingUtil.expandTree(ui.getNavigation()); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + String[] path; + if (nodePath == null) { + // take first node + path = new String[]{"jaxxdemo.tree"}; + } else { + // take selected node + path = nodePath; + + } + log.info("node to re select " + Arrays.toString(path)); + // select node + ui.getTreeHelper().selectNode(path); + + // use best dimensions + ui.getSplitPane().resetToPreferredSizes(); + } + }); + + // show ui after all (in another invocation, tu avoid layout adjustement + // to be seen). + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + // show ui + ui.setVisible(true); + } + }); + } + + /** + * Permet de recharger l'ui principale et de changer de le mode d'affichage. + * + * @param rootContext le contexte applicatif + * @param config la configuration a utiliser + */ + public void reloadUI(DefaultApplicationContext rootContext, DemoConfig config) { + + // scan main ui + DemoUI ui = getUI(rootContext); + + String[] node = null; + if (ui != null) { + + ui.getConfig().removeJaxxPropertyChangeListener(); + + node = ui.getTreeHelper().getSelectedIds(); + + if (node != null) { + if (log.isDebugEnabled()) { + log.debug("selected node " + Arrays.toString(node)); + } + } + + ErrorDialogUI.init(null); + + ui.dispose(); + + ui.setVisible(false); + + MAIN_UI_ENTRY_DEF.removeContextValue(rootContext); + } + + ui = initUI(rootContext, config); + + displayUI(ui, node); + } + + /** + * Méthode pour changer de mode d'affichage. + * <p/> + * Si <code>fullscreen</code> est à <code>true</code> alors on passe en + * mode console (c'est à dire en mode plein écran exclusif), sinon on + * passe en mode fenetré normal. + * + * @param context l'ui principale de l'application + * @param fullscreen le nouvel état requis. + */ + public void changeScreen(JAXXContext context, boolean fullscreen) { + + DemoUI ui = getUI(context); + + // sauvegarde de l'état dans la configuration + DemoConfig config = ui.getConfig(); + config.setFullscreen(fullscreen); + + // rechargement de l'ui + reloadUI(RunDemo.get(), config); + } + + public void changeLanguage(JAXXContext context, Locale newLocale) { + + DemoUI ui = getUI(context); + + DemoConfig config = ui.getConfig(); + + // sauvegarde de la nouvelle locale + config.setLocale(newLocale); + + // rechargement de l'ui + reloadUI(RunDemo.get(), config); + } + + /** + * Ferme l'application. + * + * @param context l'ui principale de l'application + */ + public void close(JAXXContext context) { + log.info("JAXX Demo quitting..."); + try { + + DemoUI ui = getUI(context); + ui.dispose(); + } finally { + System.exit(0); + } + } + + final Runnable reloadUICallback = new Runnable() { + + @Override + public void run() { + if (log.isInfoEnabled()) { + log.info("will reload ui"); + } + DefaultApplicationContext context = RunDemo.get(); + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + reloadUI(context, config); + } + }; + + final Runnable reloadApplicationCallback = new Runnable() { + + @Override + public void run() { + if (log.isInfoEnabled()) { + log.info("will reload appplication"); + } + close(RunDemo.get()); + } + }; + + final Runnable reloadLogAppenderCallback = new Runnable() { + + @Override + public void run() { + if (log.isInfoEnabled()) { + log.info("will reload log appender"); + } + DefaultApplicationContext context = RunDemo.get(); + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + + // init jaxx logger + JAXXLog4jUI.init(config.getLogLevel(), config.getLogPatternLayout()); + } + }; + + public void showConfig(JAXXContext context) { + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + + ConfigUIHelper helper = new ConfigUIHelper(config); + + helper.registerCallBack("ui", + n_("demo.action.reload.ui"), + SwingUtil.createActionIcon("reload-ui"), + reloadUICallback); + + helper.registerCallBack("application", + n_("demo.action.reload.application"), + SwingUtil.createActionIcon("reload-application"), + reloadApplicationCallback); + + helper.registerCallBack("log", + n_("demo.action.reload.logAppender"), + SwingUtil.createActionIcon("reload-log"), + reloadLogAppenderCallback); + + // categorie repertoires + + helper.addCategory(n_("jaxxdemo.config.category.directories"), + n_("jaxxdemo.config.category.directories.description")); + + helper.addOption(DemoConfig.Option.CONFIG_FILE); + + // others + helper.addCategory(n_("jaxxdemo.config.category.other"), + n_("jaxxdemo.config.category.other.description")); + + helper.addOption(DemoConfig.Option.FULL_SCREEN); + helper.setOptionPropertyName(DemoConfig.PROPERTY_FULLSCREEN); + helper.setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.FONT_SIZE); + helper.setOptionPropertyName(DemoConfig.PROPERTY_FONT_SIZE); + helper.setOptionCallBack("application"); + + helper.addOption(DemoConfig.Option.LOCALE); + helper.setOptionPropertyName(DemoConfig.PROPERTY_LOCALE); + helper.setOptionCallBack("ui"); + + helper.addOption(DemoConfig.Option.KEY_OPEN_CONFIG); + helper.setOptionPropertyName(DemoConfig.PROPERTY_KEY_OPEN_CONFIG); +// helper.setOptionCallBack("keymap"); + + helper.addOption(DemoConfig.Option.LOG_LEVEL); + helper.setOptionPropertyName(DemoConfig.PROPERTY_LOG_LEVEL); + helper.setOptionCallBack("log"); + + helper.addOption(DemoConfig.Option.LOG_PATTERN_LAYOUT); + helper.setOptionPropertyName(DemoConfig.PROPERTY_LOG_PATTERN_LAYOUT); + helper.setOptionCallBack("log"); + + helper.buildUI(context, "jaxxdemo.config.category.other"); + + helper.displayUI(ui, false); + } + + public void showHelp(JAXXContext context, String helpId) { + log.info(context + " :: " + helpId); +// DemoUI mainUI = getUI(context); +// ObserveHelpBroker helpBroker = context.getContextValue(ObserveHelpBroker.class); +// +// if (helpId == null) { +// helpId = helpBroker.getDefaultID(); +// } +// log.debug("show help " + helpId); +// mainUI.getHelp().setCurrentID(helpId); + } + + public void showLogs(DemoUI ui) { + + JAXXLog4jUI log4jUI = new JAXXLog4jUI(); + String title = _("jaxxdemo.title.showLog"); + log4jUI.setTitle(title); + log4jUI.showInDialog(ui, false); + } + + public void gotoSite(JAXXContext context) { + + DemoUI ui = getUI(context); + DemoConfig config = ui.getConfig(); + + URL siteURL = config.getOptionAsURL("application.site.url"); + + log.info(_("jaxxdemo.message.goto.site", siteURL)); + + if (log.isDebugEnabled()) { + log.debug("goto " + siteURL); + } + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(siteURL.toURI()); + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + ErrorDialogUI.showError(ex); + } + } + } + + public void showAbout(DemoUI ui) { + + DemoConfig config = ui.getConfig(); + + String iconPath = config.getOption("application.icon.path"); + String licensePath = config.getOption("application.license.path"); + String thirdPartyPath = config.getOption("application.third-party.path"); + + AboutPanel about = new AboutPanel(); + about.setTitle(_("jaxxdemo.title.about")); + about.setAboutText(_("jaxxdemo.about.message")); + about.setBottomText(ui.getConfig().getCopyrightText()); + about.setIconPath(iconPath); + about.setLicenseFile(licensePath); + about.setThirdpartyFile(thirdPartyPath); + about.buildTopPanel(); + about.init(); + about.showInDialog(ui, true); + } + + DemoUI getUI(JAXXContext context) { + if (context instanceof DemoUI) { + return (DemoUI) context; + } + DemoUI ui = MAIN_UI_ENTRY_DEF.getContextValue(context); + return ui; + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/RunDemo.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/RunDemo.java new file mode 100644 index 0000000..296e37f --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/RunDemo.java @@ -0,0 +1,202 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo; + +import java.util.Arrays; +import java.util.Date; +import jaxx.demo.entities.DemoDecoratorProvider; +import jaxx.demo.tree.DemoDataProvider; +import jaxx.demo.tree.DemoTreeHelper; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.context.DefaultApplicationContext; +import jaxx.runtime.swing.ErrorDialogUI; +import jaxx.runtime.swing.log.JAXXLog4jUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; +import org.nuiton.i18n.init.DefaultI18nInitializer; +import org.nuiton.util.StringUtil; +import org.nuiton.util.decorator.DecoratorProvider; + +import static org.nuiton.i18n.I18n._; + +/** @author tchemit <chemit@codelutin.com> */ +public class RunDemo { + + /** Logger */ + private static Log log = LogFactory.getLog(RunDemo.class); + + /** The singleton instance of the main context */ + protected static volatile DefaultApplicationContext context; + + public static void main(String[] args) { + + long startingTime = System.nanoTime(); + log.info("JAXX Demo start at " + new Date() + " args: " + Arrays.toString(args)); + + try { + + // init root context + // to enable javassist on webstart, must remove any securityManager, + // see if this can be dangerous (should not be since jnlp is signed ?) + // moreover it speeds up the loading :) + System.setSecurityManager(null); + + long t0 = System.nanoTime(); + + I18n.init(new DefaultI18nInitializer("jaxx-demo-i18n"), null); + + Runtime.getRuntime().addShutdownHook(new ShutdownHook()); + + // init root context + DefaultApplicationContext rootContext = init(); + + // share a tree helper + rootContext.setContextValue(new DemoTreeHelper(new DemoDataProvider())); + + // init config + DemoConfig config = new DemoConfig(); + config.parse(args); + + // share the config + rootContext.setContextValue(config); + + // init decorator provider + DecoratorProvider p = new DemoDecoratorProvider(); + + // share the decorator provider + rootContext.setContextValue(p); + + long t00 = System.nanoTime(); + + // init i18n + I18n.setDefaultLocale(config.getLocale()); + + log.info("language : " + config.getLocale()); + + if (log.isDebugEnabled()) { + log.debug("i18n loading time : " + StringUtil.convertTime(t00, System.nanoTime())); + } + + log.info(_("jaxxdemo.message.config.loaded", config.getVersion())); + + // init jaxx logger + JAXXLog4jUI.init(config.getLogLevel(), config.getLogPatternLayout()); + + // prepare ui look&feel and load ui properties + try { + SwingUtil.initNimbusLoookAndFeel(); + } catch (Exception e) { + // could not find nimbus look-and-feel + log.warn(_("jaxxdemo.warning.nimbus.landf")); + } catch (Throwable e) { + log.warn(_("jaxxdemo.warning.no.ui")); + + } + + if (log.isDebugEnabled()) { + log.debug("init done in " + StringUtil.convertTime(t0, System.nanoTime())); + } + + log.info(_("jaxxdemo.init.context.done", StringUtil.convertTime(startingTime, System.nanoTime()))); + + // on affiche l'ui principale + DemoUIHandler handler = new DemoUIHandler(); + + DemoUI ui = handler.initUI(rootContext, config); + + log.info(_("jaxxdemo.init.ui.done")); + + handler.displayUI(ui, config.getDemoPath().split("/")); + + } catch (Exception e) { + log.error(e.getMessage(), e); + ErrorDialogUI.showError(e); + System.exit(1); + } + } + + /** + * @return <code>true</code> si le context a été initialisé via la méthode + * {@link #init()}, <ocde>false</code> autrement. + */ + protected static boolean isInit() { + return context != null; + } + + /** + * Permet l'initialisation du contexte applicatif et positionne + * l'context partagée. + * <p/> + * Note : Cette méthode ne peut être appelée qu'une seule fois. + * + * @return l'context partagée + * @throws IllegalStateException si un contexte applicatif a déja été positionné. + */ + protected static DefaultApplicationContext init() throws IllegalStateException { + if (isInit()) { + throw new IllegalStateException("there is an already application context registred."); + } + context = new DefaultApplicationContext(); + return context; + } + + /** + * Récupération du contexte applicatif. + * + * @return l'context partagé du contexte. + * @throws IllegalStateException si le contexte n'a pas été initialisé via + * la méthode {@link #init()} + */ + public static DefaultApplicationContext get() throws IllegalStateException { + if (!isInit()) { + throw new IllegalStateException("no application context registred."); + } + return context; + } + + protected static class ShutdownHook extends Thread { + + public ShutdownHook() { + super("shutdown JAXXDemo"); + } + + @Override + public void run() { + try { + super.run(); + + // force to kill main thread + + log.info(_("jaxxdemo.init.closed", new Date())); + Runtime.getRuntime().halt(0); + } catch (Exception ex) { + log.error("error while closing " + ex.getMessage(), ex); + Runtime.getRuntime().halt(1); + } + } + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.css b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.css new file mode 100644 index 0000000..1dedfbd --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.css @@ -0,0 +1,63 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +#layerUI { + blockIcon:{SwingUtil.createImageIcon("action-block.png")}; + acceptIcon:{SwingUtil.createImageIcon("action-accept.png")}; + useIcon:true; + blockingColor:{new Color(50,50,50)}; +} + +#layerUI2 { + blockIcon:{SwingUtil.createImageIcon("action-block.png")}; + acceptIcon:{SwingUtil.createImageIcon("action-accept.png")}; +} + +#buttonPane { + layout:{new GridLayout(0,2)}; +} + +#buttonA { + text:"button A"; + _clickedText:{"button A was clicked"}; +} + +#buttonB { + text:"button B"; + _clickedText:{"button B was clicked"}; +} + +#buttonC { + text:"button C (full block)"; + _clickedText:{"button C was clicked"}; +} + +#buttonD { + text:"button D (full block 2)"; + _clickedText:{"button D was clicked"}; +} + +#messages { + model:{new DefaultListModel()}; +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx new file mode 100644 index 0000000..81f93d4 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/BoxedDecoratorDemo.jaxx @@ -0,0 +1,131 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + jaxx.runtime.SwingUtil + jaxx.runtime.swing.BlockingLayerUI + jaxx.runtime.swing.BlockingLayerUI2 + + java.awt.Color + java.awt.event.ActionEvent + + javax.swing.AbstractAction + javax.swing.DefaultListModel + javax.swing.JComponent + </import> + <BlockingLayerUI id='layerUI' + acceptAction='{new AbstractAction() { + private static final long serialVersionUID = 1L; + @Override + public void actionPerformed(ActionEvent e) { + accept(e, "from icon of layer"); + } + }}'/> + <BlockingLayerUI2 id='layerUI2' + acceptAction='{new AbstractAction() { + private static final long serialVersionUID = 1L; + @Override + public void actionPerformed(ActionEvent e) { + accept(e, "from icon of layer"); + } + }}'/> + <script><![CDATA[ + + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "BoxedDecoratorDemo.css" }; +} + +void $afterCompleteSetup() { + for (JComponent boxed : SwingUtil.getLayeredComponents(this)) { + if (boxed == buttonD) { + SwingUtil.setLayerUI(boxed, layerUI2); + continue; + } + + BlockingLayerUI ui = layerUI.clone(); + if (boxed == buttonC) { + ui.setBlock(true); + } + SwingUtil.setLayerUI(boxed, ui); + } +} + +public void setLayer(boolean active) { + for (JComponent boxed : SwingUtil.getLayeredComponents(this)) { + if (boxed == buttonD) { + continue; + } + BlockingLayerUI ui = (BlockingLayerUI) SwingUtil.getLayer(boxed).getUI(); + if (boxed == buttonC) { + ui.setBlock(active); + } + ui.setUseIcon(active); + } +} + +protected void accept(ActionEvent e, String suffix) { + JButton source = (JButton) e.getSource(); + String clickedMessage = (String) source.getClientProperty("clickedText"); + String msg = "'" + source.getText() + "' clicked - " + suffix + " : " + clickedMessage; + ((DefaultListModel)messages.getModel()).addElement(msg); +}]]> + </script> + <Table fill='both' weightx='1' constraints='BorderLayout.CENTER'> + <row> + <cell> + <JCheckBox id='toggle' selected='true' + text='{toggle.isSelected() ? "Active layer" : "No layer"}' + onActionPerformed='setLayer(toggle.isSelected());'/> + </cell> + </row> + <row> + <cell weighty='0.5'> + <JPanel id='buttonPane'> + <JButton id='buttonA' decorator='boxed' + _clickedText='"button A was clicked"' + onActionPerformed='accept(event, "from button (no layer)")'/> + <JButton id='buttonB' decorator='boxed' + onActionPerformed='accept(event, "from button (no layer)")'/> + <JButton id='buttonC' decorator='boxed' + onActionPerformed='accept(event, "from button (no layer)");'/> + <JButton id='buttonD' decorator='boxed' + onActionPerformed='accept(event, "from button (no layer)");'/> + </JPanel> + </cell> + </row> + <row> + <cell weighty='0.5'> + <JScrollPane> + <JList id='messages'/> + </JScrollPane> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx new file mode 100644 index 0000000..33ffae4 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/StatusMessagePanelDemo.jaxx @@ -0,0 +1,35 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <JPanel layout='{new GridLayout(0,1)}' constraints='BorderLayout.CENTER'> + <JButton text='Fool me once' + onActionPerformed='p.setStatus(((JButton)event.getSource()).getText() + " ? shame on you!")'/> + <JButton text='Fool me twice' + onActionPerformed='p.setStatus(((JButton)event.getSource()).getText() + " ? shame on ...")'/> + </JPanel> + <jaxx.runtime.swing.StatusMessagePanel id='p' + constraints='BorderLayout.SOUTH'/> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx new file mode 100644 index 0000000..6b9ff37 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ComboEditorDemo.jaxx @@ -0,0 +1,69 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + org.nuiton.i18n.LanguageEnum + org.nuiton.i18n.CountryEnum + </import> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell> + <JLabel text='Locale editor:' labelFor='{localeEditor}'/> + </cell> + + <cell> + <LocaleEditor id='localeEditor'/> + </cell> + </row> + <row> + <cell> + <JLabel text='EnumEditor (language) :' labelFor='{languageEditor}'/> + </cell> + <cell> + <EnumEditor id='languageEditor' genericType='LanguageEnum' + constructorParams='LanguageEnum.class'/> + </cell> + </row> + <row> + <cell> + <JLabel text='EnumEditor (country) :' labelFor='{countryEditor}'/> + </cell> + <cell> + <EnumEditor id='countryEditor' genericType='CountryEnum' + constructorParams='CountryEnum.class'/> + </cell> + </row> + <row> + <cell columns="2"> + <JTextArea + text='{"locale : "+ localeEditor.getSelectedItem() + "\nlanguage : "+ languageEditor.getSelectedItem() + "\ncountry : " + countryEditor.getSelectedItem()}'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx new file mode 100644 index 0000000..0bc2f10 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/DatePickerDemo.jaxx @@ -0,0 +1,98 @@ +<!-- + #%L + JAXX :: Demo + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + java.text.SimpleDateFormat + java.util.Date + </import> + + <String id='patternLayout' javaBean='"dd/MM/yyyy HH:mm:ss"'/> + + <SimpleDateFormat id='dateFormat' constructorParams='patternLayout'/> + + <Date id='date' javaBean='new Date()'/> + + <script><![CDATA[ + protected void $afterCompleteSetup() { + + addPropertyChangeListener(PROPERTY_PATTERN_LAYOUT, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + dateFormat = new SimpleDateFormat(patternLayout); + datePicker.setPatternLayout(patternLayout); + resultView.setText(dateFormat.format(date)); + } + }); + + addPropertyChangeListener(PROPERTY_DATE, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + resultView.setText(dateFormat.format(date)); + } + }); + } + ]]></script> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell columns='2' fill='horizontal' weightx='1'> + <JCheckBox id='showPopupButton' + text='jaxxdemo.datePickerEditor.showPopupButton' + selected='false'/> + </cell> + </row> + <row> + <cell> + <JLabel text='jaxxdemo.datePickerEditor.patternLayout'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='patternLayoutField' + text='{patternLayout}' + onFocusLost='setPatternLayout(patternLayoutField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1' columns='2'> + <JAXXDatePicker id='datePicker' + date='{date}' + patternLayout='{patternLayout}' + showPopupButton='{showPopupButton.isSelected()}' + onActionPerformed='setDate(datePicker.getDate())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='jaxxdemo.datePickerEditor.dateResult'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JLabel id='resultView' text='{dateFormat.format(date)}'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx new file mode 100644 index 0000000..c01c7c9 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/FileEditorDemo.jaxx @@ -0,0 +1,111 @@ +<!-- + #%L + JAXX :: Demo + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + jaxx.runtime.swing.editor.FileEditor + </import> + + <String id='title' javaBean='"Open file"'/> + <String id='exts' javaBean='"txt, png"'/> + <String id='extsDescription' javaBean='"Text (*.txt), Image (*.png)"'/> + <Boolean id='acceptAllFileFilterUsed' javaBean='Boolean.TRUE'/> + <Boolean id='directoryEnabled' javaBean='Boolean.TRUE'/> + <Boolean id='fileEnabled' javaBean='Boolean.FALSE'/> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.titleLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='titleField' + text='{getTitle()}' + onKeyReleased='setTitle(titleField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.directoryEnabled'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JCheckBox id='directoryEnabledField' + selected='{isDirectoryEnabled()}' + onActionPerformed='setDirectoryEnabled(directoryEnabledField.isSelected())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.fileEnabled'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JCheckBox id='fileEnabledField' + selected='{isFileEnabled()}' + onActionPerformed='setFileEnabled(fileEnabledField.isSelected())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.extsLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='extsField' + enabled='{isFileEnabled()}' + text='{getExts()}' + onKeyReleased='setExts(extsField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.extsDescLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='extsDescriptionField' + enabled='{isFileEnabled()}' + text='{getExtsDescription()}' + onKeyReleased='setExtsDescription(extsDescriptionField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.fileEditor.acceptAllFileFilterUsed'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JCheckBox id='acceptAllFileFilterUsedField' + selected='{isAcceptAllFileFilterUsed()}' + onActionPerformed='setAcceptAllFileFilterUsed(acceptAllFileFilterUsedField.isSelected())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1' columns='2'> + <FileEditor id='fileChooser' + title='{getTitle()}' + exts='{getExts()}' + directoryEnabled='{isDirectoryEnabled()}' + fileEnabled='{isFileEnabled()}' + acceptAllFileFilterUsed='{isAcceptAllFileFilterUsed()}' + extsDescription='{getExtsDescription()}'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx new file mode 100644 index 0000000..40cbd7e --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/I18nEditorDemo.jaxx @@ -0,0 +1,95 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + javax.swing.border.Border + jaxx.runtime.swing.editor.I18nEditor + org.nuiton.i18n.I18n + java.util.Arrays + </import> + <script><![CDATA[ +protected Border getPopupBorder(String text) { + if (text==null || text.trim().isEmpty()) { + return null; + } + return new TitledBorder(_(text)); +} +]]> + </script> + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell> + <JPanel + border='{new TitledBorder(_("jaxxdemo.i18neditor.configuration"))}' + layout='{new GridLayout(0,1)}'> + + <JCheckBox id='showText' + text='jaxxdemo.i18neditor.showText' + selected='true'/> + + <JCheckBox id='showIcon' + text='jaxxdemo.i18neditor.showIcon' + selected='true'/> + + <JCheckBox id='showPopupText' + text='jaxxdemo.i18neditor.showPopupText' + selected='true'/> + + <JCheckBox id='showPopupIcon' + text='jaxxdemo.i18neditor.showPopupIcon' + selected='true'/> + + <JPanel> + <JLabel text='jaxxdemo.i18neditor.popupBorderText' + labelFor='{popupBorderText}'/> + <JTextField id='popupBorderText' + text='{_("jaxxdemo.i18neditor.popup.title")}'/> + </JPanel> + + </JPanel> + </cell> + </row> + <row> + <cell> + <I18nEditor id='editor' + showText='{showText.isSelected()}' + showIcon='{showIcon.isSelected()}' + showPopupText='{showPopupText.isSelected()}' + showPopupIcon='{showPopupIcon.isSelected()}' + popupBorder='{getPopupBorder(popupBorderText.getText())}' + locales='{Arrays.asList(I18n.getStore().getLocales())}'/> + </cell> + </row> + <row> + <cell> + <JLabel + border='{new TitledBorder(_("jaxxdemo.i18neditor.selected.locale"))}' + text='{editor.getSelectedLocale().toString()}'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx new file mode 100644 index 0000000..2b0c696 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/ListSelectorDemo.jaxx @@ -0,0 +1,103 @@ +<!-- + #%L + JAXX :: Demo + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + jaxx.runtime.swing.ListSelector + com.google.common.collect.Lists + java.util.List + jaxx.demo.entities.People + jaxx.demo.entities.Movie + jaxx.demo.entities.DemoDataProvider + jaxx.demo.entities.DemoDecoratorProvider + jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer + java.util.Collection + jaxx.runtime.swing.model.GenericListModel + </import> + + <ListCellRenderer id='listCellRenderer' initializer='new DecoratorProviderListCellRenderer(new DemoDecoratorProvider())'/> + <DemoDataProvider id='dataProvider'/> + + <String id='addToolTip' javaBean='"Add"'/> + <String id='removeToolTip' javaBean='"Remove"'/> + + <script><![CDATA[ +public List<People> getActors(Collection<Movie> movies) { + List<People> actors = Lists.newArrayList(); + for (Movie m : movies) { + List<People> actorsToAdd = m.getActors(); + actors.removeAll(actorsToAdd); + actors.addAll(actorsToAdd); + } + return actors; +} +]]></script> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.listSelector.addToolTipLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='addToolTipField' + text='{getAddToolTip()}' + onKeyReleased='setAddToolTip(addToolTipField.getText())'/> + </cell> + </row> + <row> + <cell fill='horizontal' weightx='1'> + <JLabel text='jaxxdemo.listSelector.removeToolTipLbl'/> + </cell> + <cell fill='horizontal' weightx='1'> + <JTextField id='removeToolTipField' + text='{getRemoveToolTip()}' + onKeyReleased='setRemoveToolTip(removeToolTipField.getText())'/> + </cell> + </row> + <row> + <cell fill='both' weightx='1' weighty='0.5' columns='2'> + <JScrollPane> + <ComboToListSelector id='comboToListSelector' + genericType='Movie' + addToolTip='{getAddToolTip()}' + removeToolTip='{getRemoveToolTip()}' + values='{dataProvider.getMovies()}' + renderer='{listCellRenderer}' + onValuesAdded='listToListSelector.setValues(getActors(comboToListSelector.getSelectedValues()))' + onValuesRemoved='listToListSelector.setValues(getActors(comboToListSelector.getSelectedValues()))'/> + </JScrollPane> + </cell> + </row> + <row> + <cell fill='both' weightx='1' weighty='0.5' columns='2'> + <JScrollPane> + <ListToListSelector id='listToListSelector' + genericType='People' + addToolTip='{getAddToolTip()}' + removeToolTip='{getRemoveToolTip()}' + renderer='{listCellRenderer}'/> + </JScrollPane> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx new file mode 100644 index 0000000..a5671b8 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemo.jaxx @@ -0,0 +1,120 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + jaxx.runtime.swing.editor.NumberEditor + </import> + + <!-- model --> + <NumberEditorDemoModel id='demoModel'/> + + <script><![CDATA[ + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "NumberEditorDemoModel.java" }; +} + +public void changeNumberPattern() { + editor.setNumberPattern(numberPattern.getText()); +} + +void $afterCompleteSetup() { + editor.init(); + changeNumberPattern(); +} + +]]> + </script> + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel + border='{new TitledBorder(_("jaxxdemo.numbereditor.configuration"))}' + layout='{new GridLayout(0,1)}'> + + <JCheckBox id='useFloat' + text='jaxxdemo.numbereditor.useFloat' + selected='true'/> + + <JCheckBox id='useSign' + text='jaxxdemo.numbereditor.useSign' + selected='true'/> + + <JCheckBox id='showPopupButton' + text='jaxxdemo.numbereditor.showPopupButton' + selected='true'/> + + <JCheckBox id='showResetButton' + text='jaxxdemo.numbereditor.showReset' + selected='true'/> + + <JCheckBox id='autoPopup' + text='jaxxdemo.numbereditor.autoPopup' + selected='false'/> + <JPanel + border='{new TitledBorder(_("jaxxdemo.numbereditor.numberPattern.configuration"))}' + layout='{new GridLayout(1,0)}'> + <JTextField id='numberPattern' text='{"\\d{0,3}"}'/> + <JButton id='applyNumberPattern' + text='jaxxdemo.numbereditor.applyNumberPattern' + onActionPerformed='changeNumberPattern();'/> + </JPanel> + </JPanel> + </cell> + </row> + <row> + <cell> + <NumberEditor id='editor' + constructorParams='this' + bean='{demoModel}' + property='{useFloat.isSelected() ? "floatProperty" : "integerProperty"}' + useFloat='{useFloat.isSelected()}' + useSign='{useSign.isSelected()}' + autoPopup='{autoPopup.isSelected()}' + showPopupButton='{showPopupButton.isSelected()}' + showReset='{showResetButton.isSelected()}'/> + </cell> + </row> + <row> + <cell> + <JPanel border='{new TitledBorder(_("jaxxdemo.numbereditor.model"))}' + layout='{new GridLayout(0,1)}'> + <JLabel + text='{_("jaxxdemo.numbereditor.model.numberPattern", editor.getNumberPattern())}'/> + <JLabel + text='{_("jaxxdemo.numbereditor.model.int", demoModel.getIntegerProperty())}'/> + <JLabel + text='{_("jaxxdemo.numbereditor.model.float", demoModel.getFloatProperty())}'/> + + </JPanel> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> + diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java new file mode 100644 index 0000000..de772d1 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/NumberEditorDemoModel.java @@ -0,0 +1,86 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.component.jaxx.editor; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class NumberEditorDemoModel { + + public static final String INTEGER_PROPERTY = "integerProperty"; + + public static final String FLOAT_PROPERTY = "floatProperty"; + + protected PropertyChangeSupport p; + + protected int integerProperty; + + protected float floatProperty; + + public NumberEditorDemoModel() { + p = new PropertyChangeSupport(this); + } + + public float getFloatProperty() { + return floatProperty; + } + + public int getIntegerProperty() { + return integerProperty; + } + + public void setFloatProperty(float floatProperty) { + float old = this.floatProperty; + this.floatProperty = floatProperty; + p.firePropertyChange(FLOAT_PROPERTY, old, floatProperty); + } + + public void setIntegerProperty(int integerProperty) { + int old = this.integerProperty; + this.integerProperty = integerProperty; + p.firePropertyChange(INTEGER_PROPERTY, old, integerProperty); + } + + 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); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.css b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.css new file mode 100644 index 0000000..f6c9a94 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.css @@ -0,0 +1,50 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +#configPanel { + border:{new TitledBorder(_("jaxxdemo.numbereditor.configuration"))}; + layout:{new GridLayout(0,1)}; +} + +#labelConfigLabel { + text:"jaxxdemo.timeeditor.label"; +} + +#labelConfig { + text:{_("jaxxdemo.timeeditor.editor")}; +} + +/*FIXME tchemit 2010-09-02 make this works +#editor { + property:"time"; + border:{new TitledBorder(_("jaxxdemo.timeeditor.editor"))}; + bean:{demoModel}; + date:{demoModel.getTime()}; + label:{labelConfig.getText()}; +}*/ + +#resultPane { + border:{new TitledBorder(_("jaxxdemo.timeeditor.model"))}; + layout:{new BorderLayout()}; +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx new file mode 100644 index 0000000..e01e4d9 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemo.jaxx @@ -0,0 +1,114 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + jaxx.runtime.swing.editor.TimeEditor + </import> + + <!-- model --> + <TimeEditorDemoModel id='demoModel'/> + + <script><![CDATA[ + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), + "TimeEditorDemoModel.java", + "TimeEditorDemo.css" + }; +} + +void $afterCompleteSetup() { + + // init time editor + editor.init(); + + // set current time in model + demoModel.setTime(new java.util.Date()); +} +]]> + </script> + + + <Table insets='0' fill='both' weightx='1' constraints='BorderLayout.NORTH'> + <row> + <cell> + <JPanel id="configPanel"> + + <!--JCheckBox id='useFloat' + text='jaxxdemo.numbereditor.useFloat' + selected='true'/> + + <JCheckBox id='useSign' + text='jaxxdemo.numbereditor.useSign' + selected='true'/> + + <JCheckBox id='showPopupButton' + text='jaxxdemo.numbereditor.showPopupButton' + selected='true'/> + + <JCheckBox id='showResetButton' + text='jaxxdemo.numbereditor.showReset' + selected='true'/> + + <JCheckBox id='autoPopup' + text='jaxxdemo.numbereditor.autoPopup' + selected='false'/--> + + <JPanel layout='{new BorderLayout()}'> + + <JLabel id='labelConfigLabel' constraints='BorderLayout.WEST'/> + + <JTextField id='labelConfig' constraints='BorderLayout.CENTER'/> + </JPanel> + + </JPanel> + </cell> + </row> + <row> + <cell> + <TimeEditor id='editor' constructorParams='this' property='time' + border='{new TitledBorder(_("jaxxdemo.timeeditor.editor"))}' + bean='{demoModel}' + date="{demoModel.getTime()}" + label="{labelConfig.getText()}"/> + </cell> + </row> + <row> + <cell> + + <JPanel id='resultPane'> + + <JLabel constraints='BorderLayout.CENTER' + text='{_("jaxxdemo.timeeditor.value", demoModel.getTime())}'/> + </JPanel> + + </cell> + </row> + </Table> + + +</jaxx.demo.DemoPanel> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java new file mode 100644 index 0000000..586549b --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/jaxx/editor/TimeEditorDemoModel.java @@ -0,0 +1,79 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.component.jaxx.editor; + +import jaxx.runtime.swing.editor.TimeEditor; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Date; + +/** + * Model of a bean using the {@link TimeEditor}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.2 + */ +public class TimeEditorDemoModel { + + public static final String TIME_PROPERTY = "time"; + + protected final PropertyChangeSupport p; + + protected Date time; + + public TimeEditorDemoModel() { + p = new PropertyChangeSupport(this); + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + Date old = this.time; + this.time = time; + p.firePropertyChange(TIME_PROPERTY, old, time); + } + + 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); + } + +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/HidorButtonDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/HidorButtonDemo.jaxx new file mode 100644 index 0000000..800d084 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/HidorButtonDemo.jaxx @@ -0,0 +1,45 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new GridLayout(0,1)}'> + + <HBox horizontalAlignment='center' verticalAlignment='middle'> + + <jaxx.runtime.swing.HidorButton target='{hidor1}' showText="show label1" + hideText='hide label1' + targetVisible='{true}'/> + + <JLabel id='hidor1' text='Label 1'/> + </HBox> + <HBox horizontalAlignment='center' verticalAlignment='middle'> + + <jaxx.runtime.swing.HidorButton target='{hidor2}' showText="show label2" + hideText='hide label2' + targetVisible='{false}'/> + + <JLabel id='hidor2' text='Label 2'/> + </HBox> + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jaxx new file mode 100644 index 0000000..c58e1a3 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JButtonDemo.jaxx @@ -0,0 +1,62 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <style> + JButton.fancy { + foreground: blue; + font-face: Arial; + font-size: 18; + } + + JButton.fancy:mouseover { + foreground: red; + font-style: italic; + } + </style> + + <script> + public void buttonClicked(JButton button) { + JOptionPane.showMessageDialog(this, button.getText() + " clicked!", + "onActionPerformed", + JOptionPane.INFORMATION_MESSAGE); + } + </script> + + <import> + javax.swing.JOptionPane + java.awt.Color + </import> + + <javax.swing.ImageIcon id='pencil' + constructorParams='getClass().getResource("/jaxx/demo/images/pencil_black.gif")'/> + + <VBox horizontalAlignment='center' verticalAlignment='middle'> + <JButton text='Simple Button' + onActionPerformed='buttonClicked((JButton) event.getSource())'/> + <JButton text='Fancy Button' styleClass='fancy' icon='{pencil}' + onActionPerformed='buttonClicked((JButton) event.getSource())'/> + </VBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxDemo.jaxx new file mode 100644 index 0000000..4b429e2 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxDemo.jaxx @@ -0,0 +1,65 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <import> + java.awt.Font + </import> + <script><![CDATA[ + public String getText(boolean bold, boolean italic, boolean underline) { + String text ="Sample Text"; + if (bold) + text = "<b>" + text + "</b>"; + if (italic) + text = "<i>" + text + "</i>"; + if (underline) + text = "<u>" + text + "</u>"; + return "<html>" + text; + } + ]]></script> + <VBox horizontalAlignment='center' verticalAlignment='middle'> + <Table anchor='west'> + <row> + <cell> + <JCheckBox id='bold' text='Bold' mnemonic='B'/> + </cell> + <cell rows='3'> + <JLabel font='{new Font("Arial", 0, 18)}' + text='{getText(bold.isSelected(), italic.isSelected(), underline.isSelected())}'/> + </cell> + </row> + <row> + <cell> + <JCheckBox id='italic' text='Italic' mnemonic='I'/> + </cell> + </row> + <row> + <cell> + <JCheckBox id='underline' text='Underline' mnemonic='U'/> + </cell> + </row> + </Table> + </VBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxMenuItemDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxMenuItemDemo.jaxx new file mode 100644 index 0000000..5ddd864 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JCheckBoxMenuItemDemo.jaxx @@ -0,0 +1,85 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JMenuItemDemo> + <style> + .form { + enabled: { enabledCheckBox.isSelected() }; + editable: { editableCheckBox.isSelected() }; + } + </style> + + <JMenuBar id='menuBar'> + <JMenu text='View'> + <JCheckBoxMenuItem id='enabledCheckBox' text='Enabled' selected='true'/> + <JCheckBoxMenuItem id='editableCheckBox' text='Editable' selected='true'/> + </JMenu> + </JMenuBar> + + <Table id='framePanel' anchor='northwest'> + <row> + <cell> + <JLabel text='First Name:' displayedMnemonic='F' + labelFor='{firstName}'/> + </cell> + + <cell weightx='1' fill='horizontal'> + <JTextField id='firstName' styleClass="form"/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Last Name:' displayedMnemonic='L' labelFor='{lastName}'/> + </cell> + + <cell fill='horizontal'> + <JTextField id='lastName' styleClass="form"/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Email Address:' displayedMnemonic='E' labelFor='{email}'/> + </cell> + + <cell fill='horizontal'> + <JTextField id='email' styleClass="form"/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Comments:' displayedMnemonic='C' labelFor='{comments}'/> + </cell> + + <cell weightx='1' weighty='1' fill='both'> + <JScrollPane width='150' height='75'> + <JTextArea id='comments' styleClass="form"/> + </JScrollPane> + </cell> + </row> + </Table> +</JMenuItemDemo> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JComboBoxDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JComboBoxDemo.jaxx new file mode 100644 index 0000000..a59d8b8 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JComboBoxDemo.jaxx @@ -0,0 +1,73 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<jaxx.demo.DemoPanel> + <import> + javax.swing.DefaultComboBoxModel + static org.nuiton.i18n.I18n.n_ + </import> + + <script><![CDATA[ +private void $afterCompleteSetup() { + jaxxComboBox.setSelectedIndex(0); +} +]]> + </script> + <Table> + <row> + <cell> + <JLabel text='Button label:'/> + </cell> + + <cell> + <JAXXComboBox id='jaxxComboBox' editable='true'> + <item value='{_("OK")}' selected='true'/> + <item value='{_("Cancel")}'/> + <item value='{_("Help")}'/> + </JAXXComboBox> + </cell> + + <cell> + <JButton text='{String.valueOf(jaxxComboBox.getSelectedItem())}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Button label:'/> + </cell> + + <cell> + <JComboBox id='comboBox' + editable='true' + model='{new DefaultComboBoxModel(new Object[]{n_("OK"),n_("Cancel"),n_("Help")})}'/> + </cell> + + <cell> + <JButton text='{comboBox.getSelectedItem()+""}'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JDialogDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JDialogDemo.jaxx new file mode 100644 index 0000000..d215693 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JDialogDemo.jaxx @@ -0,0 +1,113 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <import> + javax.swing.JRootPane + javax.swing.JComponent + javax.swing.KeyStroke + </import> + <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> + + <VBox 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> + + <JDialog title='Sign on' id='dialog' modal='true' onWindowOpened='dialog.setLocationRelativeTo(JDialogDemo.this); + 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> + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JListDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JListDemo.jaxx new file mode 100644 index 0000000..9d1da62 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JListDemo.jaxx @@ -0,0 +1,84 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <Table> + <row> + <cell> + <JLabel text='Supported Swing components:'/> + </cell> + </row> + + <row> + <cell> + <JScrollPane> + <JAXXList> + <item value='JApplet'/> + <item value='JButton'/> + <item value='JCheckBox'/> + <item value='JCheckBoxMenuItem'/> + <item value='JColorChooser'/> + <item value='JComboBox'/> + <item value='JDesktopPane'/> + <item value='JDialog'/> + <item value='JEditorPane'/> + <item value='JFileChooser'/> + <item value='JFormattedTextField'/> + <item value='JFrame'/> + <item value='JInternalFrame'/> + <item value='JLabel'/> + <item value='JLayeredPane'/> + <item value='JList'/> + <item value='JMenu'/> + <item value='JMenuBar'/> + <item value='JMenuItem'/> + <item value='JOptionPane'/> + <item value='JPanel'/> + <item value='JPasswordField'/> + <item value='JPopupMenu'/> + <item value='JProgressBar'/> + <item value='JRadioButton'/> + <item value='JRadioButtonMenuItem'/> + <item value='JScrollBar'/> + <item value='JScrollPane'/> + <item value='JSeparator'/> + <item value='JSlider'/> + <item value='JSpinner'/> + <item value='JSplitPane'/> + <item value='JTabbedPane'/> + <item value='JTable'/> + <item value='JTextArea'/> + <item value='JTextField'/> + <item value='JTextPane'/> + <item value='JToggleButton'/> + <item value='JToolBar'/> + <item value='JTree'/> + <item value='JWindow'/> + </JAXXList> + </JScrollPane> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JMenuItemDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JMenuItemDemo.jaxx new file mode 100644 index 0000000..9709253 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JMenuItemDemo.jaxx @@ -0,0 +1,52 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <import> + javax.swing.JOptionPane + </import> + + <script> + void $afterCompleteSetup(){} + </script> + + <JDesktopPane width='350' height='400' background='{null}'> + <JInternalFrame title='JMenu demo' width='300' height='250' + resizable='true'> + <JMenuBar id='menuBar'> + <JMenu text='Demo'> + <JMenuItem text='Message Box' + onActionPerformed='JOptionPane.showMessageDialog(this, "Menu item clicked")'/> + </JMenu> + </JMenuBar> + + <JPanel id='framePanel'> + <JLabel text='JMenu demo' id='demoMessage' + horizontalAlignment='center'/> + </JPanel> + </JInternalFrame> + </JDesktopPane> + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx new file mode 100644 index 0000000..425dad7 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JPasswordFieldDemo.jaxx @@ -0,0 +1,35 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <VBox horizontalAlignment='center' verticalAlignment='middle'> + <HBox> + <JLabel text='Password:' displayedMnemonic='P' labelFor='{password}'/> + <JPasswordField id='password'/> + </HBox> + + <JLabel text='You entered: {new String(password.getPassword())}'/> + </VBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JProgressBarDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JProgressBarDemo.jaxx new file mode 100644 index 0000000..b4d6ae8 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JProgressBarDemo.jaxx @@ -0,0 +1,123 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <import> + java.awt.Color + javax.swing.Timer + javax.swing.UIManager + </import> + + <Integer id='red' javaBean='0'/> + <Integer id='green' javaBean='0'/> + <Integer id='blue' javaBean='0'/> + <Integer id='speed' initializer='2'/> + <Integer id='redDirection' initializer='1'/> + <Integer id='greenDirection' initializer='1'/> + <Integer id='blueDirection' initializer='1'/> + <Timer id='redTimer' constructorParams='5, null' + onActionPerformed='changeRedValue()'/> + <Timer id='greenTimer' constructorParams='50, null' + onActionPerformed='changeGreenValue()'/> + <Timer id='blueTimer' constructorParams='500, null' + onActionPerformed='changeBlueValue()'/> + + + <script><![CDATA[ +void startTimers() { + redTimer.start(); + greenTimer.start(); + blueTimer.start(); +} + +void stopTimers() { + redTimer.stop(); + greenTimer.stop(); + blueTimer.stop(); +} + +void $afterCompleteSetup() { + startTimers(); +} + +protected void changeRedValue() { + setRed(Math.max(0, Math.min(255, red + speed * redDirection))); + if (red == 0 || red == 255) { + redDirection = -redDirection; + } +} +protected void changeGreenValue() { + setGreen(Math.max(0, Math.min(255, green + speed * greenDirection))); + if (green == 0 || green == 255) { + greenDirection = -greenDirection; + } +} +protected void changeBlueValue() { + setBlue(Math.max(0, Math.min(255, blue + speed * blueDirection))); + if (blue == 0 || blue == 255) { + blueDirection = -blueDirection; + } +} + ]]></script> + + <Table insets='6' constraints='BorderLayout.CENTER'> + <row> + <cell columns='3'> + <JLabel text='Welcome to the JAXX framework!' + font='{UIManager.getFont("Label.font").deriveFont(18f)}' + foreground='{new Color(getRed(), getGreen(), getBlue())}'/> + </cell> + </row> + <row> + <cell columns='3' fill='horizontal'> + <JProgressBar id='redProgressBar' + foreground='{new Color(getRed(), 0, 0)}' + value='{getRed()}' maximum='255'/> + </cell> + </row> + <row> + <cell columns='3' fill='horizontal'> + <JProgressBar id='greenProgressBar' + foreground='{new Color(0, getGreen(), 0)}' + value='{getGreen()}' maximum='255'/> + </cell> + </row> + <row> + <cell columns='3' fill='horizontal'> + <JProgressBar id='blueProgressBar' + foreground='{new Color(0, 0, getBlue())}' + value='{getBlue()}' maximum='255'/> + </cell> + </row> + <row> + <cell weightx='1' anchor='east'> + <JButton text='Start' onActionPerformed='startTimers()'/> + </cell> + <cell> + <JButton text='Stop' onActionPerformed='stopTimers()'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonDemo.jaxx new file mode 100644 index 0000000..408aba2 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonDemo.jaxx @@ -0,0 +1,44 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <import> + javax.swing.ImageIcon + </import> + + <HBox horizontalAlignment='center' verticalAlignment='middle'> + <VBox> + <JRadioButton text='Animal' value='Lynx.jpg' buttonGroup='radioButtons' + selected='true'/> + <JRadioButton text='Vegetable' buttonGroup='radioButtons' + value='Tomato.jpg'/> + <JRadioButton text='Mineral' buttonGroup='radioButtons' + value='Amethyst.jpg'/> + </VBox> + + <JLabel + icon='{new ImageIcon(getClass().getResource("/jaxx/demo/images/" + radioButtons.getSelectedValue()))}'/> + </HBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonMenuItemDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonMenuItemDemo.jaxx new file mode 100644 index 0000000..8df0fdb --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JRadioButtonMenuItemDemo.jaxx @@ -0,0 +1,57 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JMenuItemDemo> + <import> + java.awt.Font + javax.swing.UIManager + </import> + + <script><![CDATA[ + +protected Font updateFont(Object selectedValue) { + return UIManager.getFont("Label.font").deriveFont(selectedValue != null ? (float) ((Integer) selectedValue).intValue() : 12); +} +]]> + </script> + <JMenuBar id='menuBar'> + <JMenu text='Font size'> + <JRadioButtonMenuItem text='10' value='{10}' + buttonGroup='fontSize'/> + <JRadioButtonMenuItem text='12' value='{12}' + buttonGroup='fontSize' selected='true'/> + <JRadioButtonMenuItem text='14' value='{14}' + buttonGroup='fontSize'/> + <JRadioButtonMenuItem text='18' value='{18}' + buttonGroup='fontSize'/> + <JRadioButtonMenuItem text='24' value='{24}' + buttonGroup='fontSize'/> + </JMenu> + </JMenuBar> + + <JLabel id='demoMessage' text='Font size: {fontSize.getSelectedValue()}' + horizontalAlignment='center' + font='{updateFont(fontSize.getSelectedValue())}'/> +</JMenuItemDemo> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSliderDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSliderDemo.jaxx new file mode 100644 index 0000000..9d2e6e3 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSliderDemo.jaxx @@ -0,0 +1,42 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <import> + java.awt.Color + </import> + + <HBox horizontalAlignment='center' verticalAlignment='middle'> + <VBox> + <JSlider id='red' maximum='255' value='200'/> + <JSlider id='green' maximum='255' value='180'/> + <JSlider id='blue' maximum='255' value='240'/> + </VBox> + + <JPanel border='{BorderFactory.createEtchedBorder()}' width='64' + height='64' + background='{new Color(red.getValue(), green.getValue(), blue.getValue())}'/> + </HBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSpinnerDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSpinnerDemo.jaxx new file mode 100644 index 0000000..4282929 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSpinnerDemo.jaxx @@ -0,0 +1,37 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + + <JLabel text='Spacing:' displayedMnemonic='S' labelFor='{spinner}'/> + + <JSpinner minimum='0' maximum='50' id='spinner'/> + + <VBox spacing='{(Integer) spinner.getValue()}'> + <JLabel text='Use the spinner to'/> + <JLabel text='adjust the spacing'/> + <JLabel text='between these lines'/> + </VBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSplitPaneDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSplitPaneDemo.jaxx new file mode 100644 index 0000000..bb88982 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JSplitPaneDemo.jaxx @@ -0,0 +1,41 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <import> + javax.swing.ImageIcon + </import> + <JSplitPane> + <JScrollPane> + <JLabel + icon='{new ImageIcon(getClass().getResource("/jaxx/demo/images/Amethyst.jpg"))}'/> + </JScrollPane> + + <JScrollPane> + <JLabel + icon='{new ImageIcon(getClass().getResource("/jaxx/demo/images/Lynx.jpg"))}'/> + </JScrollPane> + </JSplitPane> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextAreaDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextAreaDemo.jaxx new file mode 100644 index 0000000..dd3578a --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextAreaDemo.jaxx @@ -0,0 +1,54 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <Table constraints='BorderLayout.CENTER'> + <row> + <cell> + <JLabel text='Normal text:' displayedMnemonic='N' + labelFor='{textArea}'/> + </cell> + + <cell weightx='1' fill='both' anchor='east'> + <JScrollPane> + <JTextArea id='textArea' text='Try typing some text here.'/> + </JScrollPane> + </cell> + </row> + + <row> + <cell> + <JLabel text='Upper case text:' labelFor='{upperTextArea}'/> + </cell> + + <cell weightx='1' fill='both'> + <JScrollPane> + <JTextArea id='upperTextArea' editable='false' background='{null}' + text='{textArea.getText().toUpperCase()}'/> + </JScrollPane> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextFieldDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextFieldDemo.jaxx new file mode 100644 index 0000000..44fd424 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JTextFieldDemo.jaxx @@ -0,0 +1,48 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <import> + javax.swing.JOptionPane + </import> + <Table> + <row> + <cell> + <JLabel text='Your name:' displayedMnemonic='n' labelFor='{textField}'/> + </cell> + + <cell> + <JTextField id='textField'/> + </cell> + </row> + + <row> + <cell columns='2'> + <JButton text='Greet' + onActionPerformed='JOptionPane.showMessageDialog(this, "Hello, " + textField.getText() + "!")'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JToggleButtonDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JToggleButtonDemo.jaxx new file mode 100644 index 0000000..a4737e9 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/component/swing/JToggleButtonDemo.jaxx @@ -0,0 +1,35 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <HBox horizontalAlignment='center' verticalAlignment='middle'> + <JToggleButton text='1' id='one'/> + <JToggleButton text='2' id='two'/> + <JToggleButton text='3' id='three'/> + + <JLabel + text='Total: {(one.isSelected() ? 1 : 0) + (two.isSelected() ? 2 : 0) + (three.isSelected() ? 3 : 0)}'/> + </HBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/AbstractDemoBean.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/AbstractDemoBean.java new file mode 100644 index 0000000..293e070 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/AbstractDemoBean.java @@ -0,0 +1,108 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.entities; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.Serializable; + +import static org.nuiton.i18n.I18n.n_; + +/** + * Abstract demo bean. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.2 + */ +public abstract class AbstractDemoBean implements Serializable { + + static { + n_("jaxxdemo.common.id"); + n_("jaxxdemo.common.image"); + } + + public static final String PROPERTY_ID = "id"; + + public static final String PROPERTY_IMAGE = "image"; + + private static final long serialVersionUID = 1L; + + protected String id; + + protected String image; + + protected final PropertyChangeSupport p; + + public AbstractDemoBean() { + p = new PropertyChangeSupport(this); + } + + protected AbstractDemoBean(String id, String image) { + this(); + this.id = id; + this.image = image; + } + + public String getId() { + return id; + } + + public String getImage() { + return image; + } + + public void setId(String id) { + String old = this.id; + this.id = id; + firePropertyChange(PROPERTY_ID, old, id); + } + + + public void setImage(String image) { + Object oldValue = this.image; + this.image = image; + firePropertyChange(PROPERTY_IMAGE, oldValue, image); + } + + 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); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + p.firePropertyChange(propertyName, oldValue, newValue); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDataProvider.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDataProvider.java new file mode 100644 index 0000000..1677fa3 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDataProvider.java @@ -0,0 +1,112 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.entities; + +import jaxx.runtime.swing.nav.NavDataProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class DemoDataProvider implements NavDataProvider { + + /** Logger */ + static private final Log log = LogFactory.getLog(DemoDataProvider.class); + + protected Map<String, Movie> movies; + + protected Map<String, People> peoples; + + public DemoDataProvider() { + + movies = new HashMap<String, Movie>(); + peoples = new HashMap<String, People>(); + + if (log.isDebugEnabled()) { + log.debug("for " + this); + } + People a = new People("0", "Jack", "Black", 35, "/jaxx/demo/images/jack.jpg"); + People a2 = new People("1", "Héctor", "Jiménez", 28, "/jaxx/demo/images/hector.jpg"); + People a3 = new People("2", "Ana", "de la Reguera", 34, "/jaxx/demo/images/ana.jpg"); + + Movie m = new Movie("0", "Nacho libre", 1996, "/jaxx/demo/images/nacho.jpg"); + m.addActor(a); + m.addActor(a2); + m.addActor(a3); + + Movie m2 = new Movie("1", "Nacho 2", 2009, "/jaxx/demo/images/nacho2.png"); + m2.addActor(a); + m2.addActor(a2); + + movies.put(m.getId(), m); + movies.put(m2.getId(), m2); + + peoples.put(a.getId(), a); + peoples.put(a2.getId(), a2); + peoples.put(a3.getId(), a3); + } + + @Override + public boolean isEnabled() { + return true; + } + + public Movie getMovie(String id) { + return movies.get(id); + } + + public People getPeople(String id) { + return peoples.get(id); + } + + public List<Movie> getMovies() { + return new ArrayList<Movie>(movies.values()); + } + + public List<People> getPeoples() { + return new ArrayList<People>(peoples.values()); + } + + public List<People> getPeoples(Movie m) { + return m.getActors(); + } + + public List<People> getPeoples(String moviesId) { + + if (log.isDebugEnabled()) { + log.debug("Get people for movie " + moviesId); + } + + return movies.get(moviesId).getActors(); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDecoratorProvider.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDecoratorProvider.java new file mode 100644 index 0000000..d1da12f --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/DemoDecoratorProvider.java @@ -0,0 +1,51 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.entities; + +import org.nuiton.util.decorator.DecoratorProvider; + +/** + * Demo decorator provider. + * + * @author tchemit <chemit@codelutin.com> + * @see DecoratorProvider + * @since 2.2 + */ +public class DemoDecoratorProvider extends DecoratorProvider { + @Override + protected void loadDecorators() { + + // load movie decorator + registerMultiJXPathDecorator(Movie.class, + "${title}$s#${year}$s", "#", " - "); + + // load people decorator + registerMultiJXPathDecorator(People.class, + "${firstName}$s#${lastName}$s#${age}$s", + "#", + " - " + ); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Identity.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Identity.java new file mode 100644 index 0000000..5a6537a --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Identity.java @@ -0,0 +1,128 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.entities; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; + +public class Identity { + + protected String firstName = ""; + + protected String lastName = ""; + + protected String email = "dummy@codelutin.com"; + + protected int age = 51; + + protected File config = new File("/tmp"); + + protected File dir = new File("/tmp"); + + protected final PropertyChangeSupport p; + + public Identity() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getEmail() { + return email; + } + + public int getAge() { + return age; + } + + public File getConfig() { + return config; + } + + public File getDir() { + return dir; + } + + public void setFirstName(String firstName) { + String oldFirstName = this.firstName; + this.firstName = firstName; + p.firePropertyChange("firstName", oldFirstName, firstName); + } + + public void setLastName(String lastName) { + String oldLastName = this.lastName; + this.lastName = lastName; + p.firePropertyChange("lastName", oldLastName, lastName); + } + + public void setEmail(String email) { + String oldEmail = this.email; + this.email = email; + p.firePropertyChange("email", oldEmail, email); + } + + public void setAge(int age) { + int oldAge = this.age; + this.age = age; + p.firePropertyChange("age", oldAge, age); + } + + public void setConfig(File config) { + File oldConfig = this.config; + this.config = config; + p.firePropertyChange("config", oldConfig, config); + } + + public void setDir(File dir) { + File oldDir = this.dir; + this.dir = dir; + p.firePropertyChange("dir", oldDir, dir); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Model.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Model.java new file mode 100644 index 0000000..47cc1a2 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Model.java @@ -0,0 +1,92 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.entities; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class Model { + + protected String text = "text"; + + protected String text2 = "text2"; + + protected int ratio = 51; + + + PropertyChangeSupport p; + + public Model() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + + public String getText() { + return text; + } + + public String getText2() { + return text2; + } + + public int getRatio() { + return ratio; + } + + public void setText(String text) { + String oldText = this.text; + this.text = text; + p.firePropertyChange("text", oldText, text); + } + + public void setText2(String text2) { + String oldText2 = this.text2; + this.text2 = text2; + p.firePropertyChange("text2", oldText2, text2); + } + + public void setRatio(int ratio) { + int oldRatio = this.ratio; + this.ratio = ratio; + p.firePropertyChange("ratio", oldRatio, ratio); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Movie.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Movie.java new file mode 100644 index 0000000..a41e4a5 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/Movie.java @@ -0,0 +1,141 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.entities; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.ArrayList; +import java.util.List; + +import static org.nuiton.i18n.I18n.n_; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.7.2 + */ +public class Movie extends AbstractDemoBean { + + static { + n_("jaxxdemo.common.movie"); + n_("jaxxdemo.common.title"); + n_("jaxxdemo.common.year"); + n_("jaxxdemo.common.actors"); + } + + protected String title; + + protected int year; + + protected List<People> actors; + + private static final long serialVersionUID = 1L; + + private static final String PROPERTY_ACTORS = "actors"; + + private static final String PROPERTY_TITLE = "title"; + + private static final String PROPERTY_YEAR = "year"; + + private static final String PROPERTY_IMAGE = "image"; + + public Movie(String id, String title, int year, String image) { + super(id, image); + this.title = title; + this.year = year; + actors = new ArrayList<People>(); + } + + public Movie() { + actors = new ArrayList<People>(); + } + + public List<People> getActors() { + return actors; + } + + public String getTitle() { + return title; + } + + public int getYear() { + return year; + } + + public void setActors(List<People> actors) { + Object oldValue = this.actors; + this.actors = actors; + firePropertyChange(PROPERTY_ACTORS, null, actors); + } + + public void setTitle(String title) { + Object oldValue = this.title; + this.title = title; + firePropertyChange(PROPERTY_TITLE, oldValue, title); + } + + public void setYear(int year) { + Object oldValue = this.year; + this.year = year; + firePropertyChange(PROPERTY_YEAR, oldValue, year); + } + + + public void addActor(People actor) { + actors.add(actor); + firePropertyChange(PROPERTY_ACTORS, null, actors); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Movie other = (Movie) obj; + return !(id == null ? other.id != null : !id.equals(other.id)); + } + + @Override + public int hashCode() { + int hash = 5; + hash = 41 * hash + (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append(PROPERTY_ID, id); + b.append(PROPERTY_TITLE, title); + b.append(PROPERTY_IMAGE, image); + b.append(PROPERTY_YEAR, year); + b.append(PROPERTY_ACTORS, actors); + return b.toString(); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/People.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/People.java new file mode 100644 index 0000000..90eb1b4 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/entities/People.java @@ -0,0 +1,137 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.entities; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import static org.nuiton.i18n.I18n.n_; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.7.2 + */ +public class People extends AbstractDemoBean { + + static { + n_("jaxxdemo.common.people"); + n_("jaxxdemo.common.firstName"); + n_("jaxxdemo.common.lastName"); + n_("jaxxdemo.common.age"); + } + + public static final String PROPERTY_FIRST_NAME = "firstName"; + + public static final String PROPERTY_LAST_NAME = "lastName"; + + public static final String PROPERTY_AGE = "age"; + + protected String firstName; + + protected String lastName; + + protected int age; + + private static final long serialVersionUID = 1L; + + public People() { + } + + public People(String id, + String firstName, + String lastName, + int age, + String image) { + super(id, image); + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + } + + public int getAge() { + return age; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getImage() { + return image; + } + + public void setAge(int age) { + int old = this.age; + this.age = age; + firePropertyChange(PROPERTY_AGE, old, age); + } + + public void setFirstName(String firstName) { + String old = this.firstName; + this.firstName = firstName; + firePropertyChange(PROPERTY_FIRST_NAME, old, firstName); + } + + public void setLastName(String lastName) { + String old = this.lastName; + this.lastName = lastName; + firePropertyChange(PROPERTY_LAST_NAME, old, lastName); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + People other = (People) obj; + return !(id == null ? other.id != null : !id.equals(other.id)); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 97 * hash + (id != null ? id.hashCode() : 0); + return hash; + } + + @Override + public String toString() { + ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE); + b.append(PROPERTY_ID, id); + b.append(PROPERTY_FIRST_NAME, firstName); + b.append(PROPERTY_LAST_NAME, lastName); + b.append(PROPERTY_IMAGE, image); + b.append(PROPERTY_AGE, age); + return b.toString(); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx new file mode 100644 index 0000000..465b45c --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BaseBeanDataBinding.jaxx @@ -0,0 +1,51 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + + <!-- 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> + void $afterCompleteSetup(){ + } + + public Boolean isEditing2() { + return editing2; + } + + public void setEditing2(Boolean editing2) { + Boolean oldValue = this.editing2; + this.editing2 = editing2; + firePropertyChange("editing2", oldValue, editing2); + } + </script> + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BeanDataBindingDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BeanDataBindingDemo.jaxx new file mode 100644 index 0000000..39e801c --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BeanDataBindingDemo.jaxx @@ -0,0 +1,85 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<BaseBeanDataBinding layout='{new BorderLayout()}'> + + <Boolean id='editing3' javaBean='true'/> + <script><![CDATA[ +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "BaseBeanDataBinding.jaxx" }; +} +]]> + </script> + <Table> + <row> + <cell columns='2'> + <JLabel text='{getContentMessage()}'/> + </cell> + </row> + <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> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx new file mode 100644 index 0000000..b1e4408 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/BindingExtremeDemo.jaxx @@ -0,0 +1,292 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<jaxx.demo.DemoPanel id='mainFrame' implements='DemoUIModel' + layout='{new BorderLayout()}'> + + <import> + jaxx.runtime.JAXXBinding + java.awt.Color + javax.swing.border.TitledBorder + javax.swing.DefaultListModel + javax.swing.SwingUtilities + </import> + <style> + JTextArea { editable:false; } + + JCheckBox { enabled:false; } + + .nobinding { background:{Color.GRAY}; } + </style> + + <script><![CDATA[ +public JToggleButton getT3() { return t0; } + +private void $afterCompleteSetup() { + for (Object o : $objectMap.values()) { + if (o instanceof JCheckBox) { + JCheckBox c = (JCheckBox) o; + c.setBackground($bindings.containsKey(c.getName() + ".selected") ? Color.WHITE : Color.RED); + } + } + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + DefaultListModel m = (DefaultListModel) bindings.getModel(); + for (JAXXBinding b : getDataBindings()) { + m.addElement(b.getId()); + } + } + }); +} +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "DemoUIModel.java", "DefaultDemoUIModel.java" }; +} + ]]> + </script> + + <Boolean id='f0' javaBean='Boolean.FALSE'/> + <Boolean id='f1' javaBean='Boolean.FALSE'/> + <java.io.File id='file' javaBean='new java.io.File(".")'/> + + <DefaultDemoUIModel id='model0' initializer='new DefaultDemoUIModel()'/> + + <DemoUIModel id='model1' javaBean='new DefaultDemoUIModel()'/> + + + <Table fill="both" constraints='BorderLayout.CENTER'> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cf0' selected='{isF0()}' text='isF0()'/> + <JCheckBox id='cf1' selected='{isF1()}' text='isF1()'/> + <JCheckBox id='cf0O1' selected='{isF0() || isF1()}' + text='isF0() || isF1()'/> + <JCheckBox id='cf0A1' selected='{isF0() && isF1()}' + text='isF0() && isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='ct0' selected='{t0.isSelected()}' + text='t0.isSelected()'/> + <JCheckBox id='ct1' selected='{t1.isSelected()}' + text='t1.isSelected()'/> + <JCheckBox id='ct0O1' selected='{t0.isSelected() || t1.isSelected()}' + text='t0.isSelected() || t1.isSelected()'/> + <JCheckBox id='ct0A1' + selected='{t0.isSelected() && t1.isSelected()}' + text='t0.isSelected() && t1.isSelected()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cgett0' selected='{getT0().isSelected()}' + text='getT0().isSelected()'/> + <JCheckBox id='cgett1' selected='{getT1().isSelected()}' + text='getT1().isSelected()'/> + <JCheckBox id='cgett0O1' + selected='{getT0().isSelected() || getT1().isSelected()}' + text='getT0().isSelected() || getT1().isSelected()'/> + <JCheckBox id='cgett0A1' + selected='{getT0().isSelected() && getT1().isSelected()}' + text='getT0().isSelected() && getT1().isSelected()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JTextArea id='cfile' + border='{new TitledBorder("file.getAbsolutePath()")}' + text='{file.getAbsolutePath()}' + visible='{!$bindings.containsKey("cfile.text")}' + styleClass="nobinding"/> + <JTextArea id='cgetfile' + border='{new TitledBorder("getFile().getAbsolutePath()")}' + text='{getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cgetfile.text")}'/> + </JPanel> + </cell> + </row> + <row weightx='1'> + <cell> + <JToggleButton id='t0' text='f0' onActionPerformed='setF0(!f0)'/> + </cell> + <cell> + <JToggleButton id='t1' text='f1' onActionPerformed='setF1(!f1)' + javaBean='new JToggleButton()'/> + </cell> + <cell> + <JButton text="file..." + onActionPerformed='setFile(org.nuiton.util.FileUtil.getFile(this, new String[0]))'/> + </cell> + </row> + + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cmt0' selected='{model0.isF0()}' text='model0.isF0()'/> + <JCheckBox id='cmt1' selected='{model0.isF1()}' text='model0.isF1()'/> + <JCheckBox id='cmt0O1' selected='{model0.isF0() || model0.isF1()}' + text='model0.isF0() || model0.isF1()'/> + <JCheckBox id='cmt0A1' + selected='{model0.isF0() && model0.isF1()}' + text='model0.isF0() && model0.isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cmgett0' selected='{getModel0().isF0()}' + text='getModel0().isF0()'/> + <JCheckBox id='cmgett1' selected='{getModel0().isF1()}' + text='getModel0().isF1()'/> + <JCheckBox id='cmgett0O1' + selected='{getModel0().isF0() || getModel0().isF1()}' + text='getModel0().isF0() || getModel0().isF1()'/> + <JCheckBox id='cmgett0A1' + selected='{getModel0().isF0() && getModel0().isF1()}' + text='getModel0().isF0() && getModel0().isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JTextArea id='cMfile' + border='{new TitledBorder("model0.getFile().getAbsolutePath()")}' + text='{model0.getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cMfile.text")}'/> + <JTextArea id='cMgetfile' + border='{new TitledBorder("getModel0().getFile().getAbsolutePath()")}' + text='{getModel0().getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cMgetfile.text")}'/> + </JPanel> + </cell> + </row> + <row> + <cell> + <JToggleButton id='Mt0' text='model0.f0' + onActionPerformed='model0.setF0(!model0.isF0())'/> + </cell> + <cell> + <JToggleButton id='Mt1' text='model0.f1' + onActionPerformed='model0.setF1(!model0.isF1())' + javaBean='new JToggleButton()'/> + </cell> + <cell> + <JButton text="model0.file..." + onActionPerformed='model0.setFile(org.nuiton.util.FileUtil.getFile(this,new String[0]))'/> + </cell> + </row> + + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cit0' selected='{((DemoUIModel)model1).isF0()}' + text='model1.isF0()'/> + <JCheckBox id='cit1' selected='{((DemoUIModel)model1).isF1()}' + text='model1.isF1()'/> + <JCheckBox id='cit0O1' + selected='{((DemoUIModel)model1).isF0() || ((DemoUIModel)model1).isF1()}' + text='model1.isF0() || model1.isF1()'/> + <JCheckBox id='cit0A1' + selected='{((DemoUIModel)model1).isF0() && ((DemoUIModel)model1).isF1()}' + text='model1.isF0() && model1.isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JCheckBox id='cigett0' selected='{getModel1().isF0()}' + text='getModel1().isF0()'/> + <JCheckBox id='cigett1' selected='{getModel1().isF1()}' + text='getModel1().isF1()'/> + <JCheckBox id='cigett0O1' + selected='{getModel1().isF0() || getModel1().isF1()}' + text='getModel1().isF0() || getModel1().isF1()'/> + <JCheckBox id='cigett0A1' + selected='{getModel1().isF0() && getModel1().isF1()}' + text='getModel1().isF0() && getModel1().isF1()'/> + </JPanel> + </cell> + </row> + <row> + <cell columns="3"> + <JPanel layout="{new GridLayout(1,0)}"> + <JTextArea id='cIfile' + border='{new TitledBorder("model1.getFile().getAbsolutePath()")}' + text='{model1.getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cIfile.text")}'/> + <JTextArea id='cIgetfile' + border='{new TitledBorder("getModel1().getFile().getAbsolutePath()")}' + text='{getModel1().getFile().getAbsolutePath()}' + visible='{$bindings.containsKey("cIgetfile.text")}'/> + </JPanel> + </cell> + </row> + <row> + <cell> + <JToggleButton id='It0' text='model1.f0' + onActionPerformed='model1.setF0(!model1.isF0())'/> + </cell> + <cell> + <JToggleButton id='It1' text='model1.f1' + onActionPerformed='model1.setF1(!model1.isF1())' + javaBean='new JToggleButton()'/> + </cell> + <cell> + <JButton text="model1.file..." + onActionPerformed='model1.setFile(org.nuiton.util.FileUtil.getFile(this,new String[0]))'/> + </cell> + </row> + + <row weighty="1"> + <cell columns="3"> + <JPanel layout="{new BorderLayout()}"> + <JTextArea id="bindingsLabel" editable='false' + text='{$bindings.size() + " bindings."}'/> + <JScrollPane constraints='BorderLayout.CENTER' + columnHeaderView='{bindingsLabel}'> + <JList id="bindings" model='{new DefaultListModel()}' + font-size='10'/> + </JScrollPane> + </JPanel> + </cell> + </row> + </Table> + + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DefaultDemoUIModel.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DefaultDemoUIModel.java new file mode 100644 index 0000000..e068d70 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DefaultDemoUIModel.java @@ -0,0 +1,170 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.feature.databinding; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JToggleButton; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; + +/** + * Created: 3 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class DefaultDemoUIModel implements DemoUIModel { + + + protected File file; + + protected File file1; + + protected Boolean f1 = false; + + protected Boolean f0 = false; + + protected JToggleButton t1; + + protected JToggleButton t0; + + public static final String PROPERTY_T1 = "t1"; + + public static final String PROPERTY_F1 = "f1"; + + public static final String PROPERTY_F0 = "f0"; + + public static final String PROPERTY_FILE = "file"; + + protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + protected static final Log log = LogFactory.getLog(DefaultDemoUIModel.class); + + /*---------------------------------------------------------------------------------*/ + /*-- public acessor methods -------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + public Boolean getF0() { + return f0; + } + + public Boolean getF1() { + return f1; + } + + @Override + public File getFile() { + return file; + } + + public File getFile1() { + return file1; + } + + @Override + public JToggleButton getT0() { + return t0; + } + + @Override + public JToggleButton getT1() { + return t1; + } + + @Override + public Boolean isF0() { + return f0 != null && f0; + } + + @Override + public Boolean isF1() { + return f1 != null && f1; + } + + /*---------------------------------------------------------------------------------*/ + /*-- public mutator methods -------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ + + @Override + public void setF0(Boolean newValue) { + Boolean oldValue = f0; + f0 = newValue; + firePropertyChange(PROPERTY_F0, oldValue, newValue); + } + + @Override + public void setF1(Boolean newValue) { + Boolean oldValue = f1; + f1 = newValue; + firePropertyChange(PROPERTY_F1, oldValue, newValue); + } + + @Override + public void setFile(File newValue) { + File oldValue = file; + file = newValue; + firePropertyChange(PROPERTY_FILE, oldValue, newValue); + } + + + public void setT1(JToggleButton newValue) { + JToggleButton oldValue = t1; + t1 = newValue; + firePropertyChange(PROPERTY_T1, oldValue, newValue); + } + + @Override + public void firePropertyChange(String name, Object oldValue, Object newValue) { + pcs.firePropertyChange(name, oldValue, newValue); + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + @Override + public void addPropertyChangeListener(String property, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(property, listener); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + @Override + public void removePropertyChangeListener(String property, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(property, listener); + } + + +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DemoUIModel.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DemoUIModel.java new file mode 100644 index 0000000..2e463ac --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/databinding/DemoUIModel.java @@ -0,0 +1,99 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.feature.databinding; + +import javax.swing.JToggleButton; +import java.beans.PropertyChangeListener; +import java.io.File; + +/** + * Created: 2 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public interface DemoUIModel { + + Boolean isF0(); + + Boolean isF1(); + + void setF0(Boolean b); + + void setF1(Boolean b); + + JToggleButton getT0(); + + JToggleButton getT1(); + + File getFile(); + + void setFile(File newValue); + + /** + * 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 + */ + void firePropertyChange(String name, Object oldValue, Object newValue); + + /** + * Register a general {@link PropertyChangeListener}. + * + * @param listener the listener to register + */ + void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Register a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to register + */ + void addPropertyChangeListener(String property, PropertyChangeListener listener); + + /** + * Unregister a general {@link PropertyChangeListener}. + * + * @param listener the listener to unregister + */ + void removePropertyChangeListener(PropertyChangeListener listener); + + /** + * Unregister a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to unregister + */ + void removePropertyChangeListener(String property, PropertyChangeListener listener); + +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemo.jaxx new file mode 100644 index 0000000..bc21ea1 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemo.jaxx @@ -0,0 +1,107 @@ +<!-- + #%L + JAXX :: Demo + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + jaxx.demo.feature.nav.tree.NavDemoTreeHelper + jaxx.demo.feature.nav.treetable.NavDemoTreeTableHelper + org.jdesktop.swingx.JXTreeTable + jaxx.demo.entities.DemoDataProvider + </import> + + <CardLayout2 id='contentLayout'/> + + <DemoDataProvider id='dataProvider'/> + + <NavDemoTreeHelper id='treeHelper' constructorParams='getDataProvider()'/> + + <NavDemoTreeTableHelper id='treeTableHelper' + constructorParams='getDataProvider()'/> + + <NavDemoHandler id='handler' constructorParams='this'/> + + <script><![CDATA[ + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), + "NavDemoHandler.java", + "tree/NavDemoTreeNode.java", + "tree/NavDemoTreeHelper.java", + "tree/NavDemoTreeCellRenderer.java", + "tree/ActorsTreeNodeLoador.java", + "tree/MoviesTreeNodeLoador.java", + "treetable/NavDemoTreeTableNode.java", + "treetable/NavDemoTreeTableHelper.java", + "treetable/ActorsTreeTableNodeLoador.java", + "treetable/MoviesTreeTableNodeLoador.java" + }; +} + +private void $afterCompleteSetup() { + getHandler().$afterCompleteSetup(); +} + ]]> + </script> + + <JSplitPane id='splitPane' + constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <JTabbedPane> + <tab title='jaxxdemo.tree.tabtitle'> + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> + + <JTree id="navigationTree" + font-size='11' + rootVisible='false' + showsRootHandles='false' + model='{treeHelper.createModel()}'/> + + </JScrollPane> + </tab> + <tab title='jaxxdemo.treeTable.tabtitle'> + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_NEVER}'> + + <JXTreeTable id="navigationTreeTable" + font-size='11' + rootVisible='false' + showsRootHandles='false' + columnControlVisible='true' + treeTableModel='{treeTableHelper.createModel()}'/> + + </JScrollPane> + </tab> + </JTabbedPane> + + <JPanel id="content" layout="{contentLayout}"/> + + </JSplitPane> + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemoHandler.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemoHandler.java new file mode 100644 index 0000000..39819ce --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/NavDemoHandler.java @@ -0,0 +1,300 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.feature.nav; + +import jaxx.demo.entities.AbstractDemoBean; +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.entities.People; +import jaxx.demo.feature.nav.content.AbstractContentUI; +import jaxx.demo.feature.nav.content.ActorContentUI; +import jaxx.demo.feature.nav.content.ActorsContentUI; +import jaxx.demo.feature.nav.content.MovieContentUI; +import jaxx.demo.feature.nav.content.MoviesContentUI; +import jaxx.demo.feature.nav.tree.NavDemoTreeCellRenderer; +import jaxx.demo.feature.nav.tree.NavDemoTreeNode; +import jaxx.demo.feature.nav.treetable.NavDemoTreeTableNode; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.swing.CardLayout2; +import jaxx.runtime.swing.ErrorDialogUI; +import jaxx.runtime.swing.nav.NavNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; +import org.nuiton.util.decorator.DecoratorProvider; +import org.nuiton.util.decorator.JXPathDecorator; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreePath; +import java.awt.Component; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; + +import static org.nuiton.i18n.I18n.n_; + +/** + * Handler of all uis in the Nave demo. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.2 + */ +public class NavDemoHandler { + + private static final Log log = LogFactory.getLog(NavDemoHandler.class); + + protected final NavDemo ui; + + public static String MOVIES_CATEGORY_NODE = n_("jaxxdemo.common.movies"); + + public static String ACTORS_CATEGORY_NODE = n_("jaxxdemo.common.actors"); + + public NavDemoHandler(NavDemo ui) { + this.ui = ui; + } + + public void initUI(MoviesContentUI contentUI) { + DecoratorProvider provider = + contentUI.getContextValue(DecoratorProvider.class); + JXPathDecorator<Movie> decorator = + (JXPathDecorator<Movie>) provider.getDecoratorByType(Movie.class); + contentUI.getListHeader().init(decorator, new ArrayList<Movie>()); + } + + public void initUI(ActorsContentUI contentUI) { + DecoratorProvider provider = + contentUI.getContextValue(DecoratorProvider.class); + JXPathDecorator<People> decorator = + (JXPathDecorator<People>) provider.getDecoratorByType(People.class); + contentUI.getListHeader().init(decorator, new ArrayList<People>()); + } + + public void selectChild(AbstractContentUI<?> contentUI, + AbstractDemoBean selected) { + contentUI.getTreeHelper().selectNode(selected.getId()); + contentUI.getTreeTableHelper().selectNode(selected.getId()); + } + + public String getContent(AbstractDemoBean data) { + if (data == null) { + return "no content"; + } + StringBuilder buffer = new StringBuilder(); + buffer.append(data); + return buffer.toString(); + } + + public ImageIcon getImage(AbstractDemoBean data) { + return data == null ? null : SwingUtil.createIcon(data.getImage()); + } + + /** To init the {@link NavDemo} ui. */ + public void $afterCompleteSetup() { + + // share in context + + ui.setContextValue(this); + ui.setContextValue(ui.getTreeHelper(), "treeHelper"); + ui.setContextValue(ui.getTreeTableHelper(), "treeTableHelper"); + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener treeSelectionListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + NavDemoTreeNode demoNode = + (NavDemoTreeNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select demoNode " + demoNode); + } + + // Do nothing for root + if (demoNode.isRoot()) { + return; + } + openUI(demoNode); + } + }; + + // Creation of selection listener to open ui when tree selection change + TreeSelectionListener treeTableSelectionListener = new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent event) { + TreePath path = event.getPath(); + NavDemoTreeTableNode demoNode = + (NavDemoTreeTableNode) path.getLastPathComponent(); + + if (log.isDebugEnabled()) { + log.debug("Select demoNode " + demoNode); + } + + // Do nothing for root + if (demoNode.isRoot()) { + return; + } + openUI(demoNode); + } + }; + + final JTree tree = ui.getNavigationTree(); + JXTreeTable table = ui.getNavigationTreeTable(); + + // Attach renderer + NavDemoTreeCellRenderer renderer = new NavDemoTreeCellRenderer( + ui.getContextValue(DecoratorProvider.class), + ui.getDataProvider() + ); + tree.setCellRenderer(renderer); + + // Register tree + ui.getTreeHelper().setUI(tree, true, treeSelectionListener); + + // Register tree table + ui.getTreeTableHelper().setUI(table, true, treeTableSelectionListener); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + tree.setSelectionInterval(0, 0); + ui.getSplitPane().resetToPreferredSizes(); + } + }); + + // expand the tree + SwingUtil.expandTree(tree); + SwingUtil.expandTreeTable(table); + + // auto-expand demoNode when selected + SwingUtil.addExpandOnClickListener(tree); + SwingUtil.addExpandOnClickListener(table); + } + + protected void openUI(NavNode<?, ?> demoNode) { + + // Get demoNode type + Class<?> editType = demoNode.getInternalClass(); + String id = demoNode.getId(); + + // If it's category demoNode + DemoDataProvider provider = ui.getDataProvider(); + if (editType.equals(String.class)) { + + // Actors categorie demoNode + if (ACTORS_CATEGORY_NODE.equals(id)) { + + List<People> peoples = provider.getPeoples(); + showUI(peoples, ActorsContentUI.class); + + // Movies categorie demoNode + } else if (MOVIES_CATEGORY_NODE.equals(id)) { + + List<Movie> movies = provider.getMovies(); + showUI(movies, MoviesContentUI.class); + } + + // People demoNode + } else if (editType.equals(People.class)) { + People people = provider.getPeople(id); + showUI(people, ActorContentUI.class); + + // Movie demoNode + } else if (editType.equals(Movie.class)) { + Movie movie = provider.getMovie(id); + showUI(movie, MovieContentUI.class); + } + } + + // Create by introspection content ui + + protected <B> void showUI(B bean, + Class<? extends AbstractContentUI<B>> uiClass) { + + // Verify if instance is existing + AbstractContentUI<B> ui = getContentIfExist(uiClass); + + // Get layout identifier + String contentName = uiClass.getName(); + + JPanel content = this.ui.getContent(); + if (ui == null) { + try { + // Get constructor + Constructor<? extends AbstractContentUI<B>> constructor = + uiClass.getConstructor(JAXXContext.class); + + // Invoke instance creation + ui = constructor.newInstance(this.ui); + } catch (Exception eee) { + log.error("Could not create ui of type " + uiClass, eee); + ErrorDialogUI.showError(eee); + return; + } + + // Add to content panel + content.add(ui, contentName); + } + + // Attach bean + ui.setData(bean); + + // show ui + this.ui.getContentLayout().show(content, contentName); + + // revalidate container + SwingUtilities.invokeLater(revalidateContent); + + } + + // Get content if exist in content, else return null + + protected <E extends Component> E getContentIfExist(Class<E> uiClass) { + String contentName = uiClass.getName(); + if (log.isDebugEnabled()) { + log.debug("Get content if exist " + contentName); + } + CardLayout2 layout2 = ui.getContentLayout(); + if (!layout2.contains(contentName)) { + return null; + } + return (E) layout2.getComponent(ui.getContent(), contentName); + } + + private final Runnable revalidateContent = new Runnable() { + + @Override + public void run() { + ui.revalidate(); + } + }; + +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx new file mode 100644 index 0000000..5593de6 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/AbstractContentUI.jaxx @@ -0,0 +1,50 @@ +<!-- + #%L + JAXX :: Demo + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel abstract='true' + layout='{new BorderLayout()}' + genericType='B'> + + <import> + jaxx.demo.feature.nav.NavDemoHandler + jaxx.demo.feature.nav.tree.NavDemoTreeHelper + jaxx.demo.feature.nav.treetable.NavDemoTreeTableHelper + </import> + + <NavDemoTreeHelper id='treeHelper' + initializer='getContextValue(NavDemoTreeHelper.class,"treeHelper")'/> + + <NavDemoTreeTableHelper id='treeTableHelper' + initializer='getContextValue(NavDemoTreeTableHelper.class,"treeTableHelper")'/> + + <NavDemoHandler id='handler' + initializer='getContextValue(NavDemoHandler.class)'/> + <script><![CDATA[ + +public abstract B getData(); + +public abstract void setData(B data); + ]]> + </script> +</JPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorContentUI.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorContentUI.jaxx new file mode 100644 index 0000000..c8b7f61 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorContentUI.jaxx @@ -0,0 +1,62 @@ +<!-- + #%L + JAXX :: Demo + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='People'> + + <import> + jaxx.demo.entities.People + static org.nuiton.i18n.I18n._ + </import> + + <People id='data' javaBean='null'/> + + <JSplitPane id='splitPane' + orientation='{JSplitPane.VERTICAL_SPLIT}' + resizeWeight='0.5' + constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <JTextPane + border='{new TitledBorder(_("jaxxdemo.navigation.actor.title"))}' + editable='false' + font-size='11' + text='{getHandler().getContent(getData())}'/> + </JScrollPane> + + <JScrollPane border='{new TitledBorder("Picture")}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' + minimumSize='{SwingUtil.newMinDimension()}'> + + <JLabel horizontalAlignment='center' + icon='{getHandler().getImage(getData())}'/> + + </JScrollPane> + + </JSplitPane> +</AbstractContentUI> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx new file mode 100644 index 0000000..2cd05e5 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/ActorsContentUI.jaxx @@ -0,0 +1,83 @@ +<!-- + #%L + JAXX :: Demo + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='List<People>'> + + <import> + java.util.List + jaxx.demo.entities.People + jaxx.runtime.swing.editor.bean.BeanListHeader + jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer + </import> + + <java.util.List id='data' genericType='People' javaBean='null'/> + + <script><![CDATA[ +private void $afterCompleteSetup() { + getHandler().initUI(this); +} + ]]></script> + + <JPanel layout='{new BorderLayout()}'> + + <JScrollPane + border='{new TitledBorder(_("jaxxdemo.navigation.actors.title"))}' + constraints='BorderLayout.CENTER' + columnHeaderView='{toolbar}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <!-- list of actors --> + <JList id='list' + cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> + + <!-- list header --> + <JToolBar id='toolbar' floatable='false' layout='{new BorderLayout()}'> + <JPanel layout='{new GridLayout(1,0)}' + constraints='BorderLayout.CENTER'> + + <!-- to show the selected actor --> + <JButton text='jaxxdemo.action.show' + enabled='{list.getSelectedIndex()!=-1}' + onActionPerformed='getHandler().selectChild(this, (People) list.getSelectedValue())'/> + + <!-- to show a new actor --> + <JButton text='jaxxdemo.action.add'/> + + <!-- to delete the selected actor --> + <JButton text='jaxxdemo.action.remove' + enabled='{list.getSelectedIndex()!=-1}'/> + </JPanel> + + <BeanListHeader id='listHeader' constraints='BorderLayout.EAST' + i18nPrefix='jaxxdemo.common.' + data='{getData()}' genericType='People' + list='{list}' showReset='true' + beanType='{People.class}'/> + </JToolBar> + + </JScrollPane> + + </JPanel> +</AbstractContentUI> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MovieContentUI.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MovieContentUI.jaxx new file mode 100644 index 0000000..0e2148a --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MovieContentUI.jaxx @@ -0,0 +1,62 @@ +<!-- + #%L + JAXX :: Demo + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='Movie'> + + <import> + jaxx.demo.entities.Movie + static org.nuiton.i18n.I18n._ + </import> + + <Movie id='data' javaBean='null'/> + + <JSplitPane id='splitPane' + orientation='{JSplitPane.VERTICAL_SPLIT}' + resizeWeight='0.5' + constraints='BorderLayout.CENTER' + oneTouchExpandable='true'> + + <JScrollPane border='{null}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <JTextPane + border='{new TitledBorder(_("jaxxdemo.navigation.movie.title"))}' + editable='false' + font-size='11' + text='{getHandler().getContent(getData())}'/> + </JScrollPane> + + <JScrollPane border='{new TitledBorder("Picture")}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}' + minimumSize='{SwingUtil.newMinDimension()}'> + + <JLabel horizontalAlignment='center' + icon='{getHandler().getImage(getData())}'/> + + </JScrollPane> + + </JSplitPane> +</AbstractContentUI> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx new file mode 100644 index 0000000..edd416d --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/content/MoviesContentUI.jaxx @@ -0,0 +1,82 @@ +<!-- + #%L + JAXX :: Demo + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<AbstractContentUI superGenericType='List<Movie>'> + + <import> + java.util.List + jaxx.demo.entities.Movie + jaxx.runtime.swing.editor.bean.BeanListHeader + jaxx.runtime.swing.renderer.DecoratorProviderListCellRenderer + </import> + <script><![CDATA[ + +private void $afterCompleteSetup() { + getHandler().initUI(this); +} + ]]></script> + + <java.util.List id='data' genericType='Movie' javaBean='null'/> + + <JPanel layout='{new BorderLayout()}'> + + <JScrollPane + border='{new TitledBorder(_("jaxxdemo.navigation.movies.title"))}' + constraints='BorderLayout.CENTER' + columnHeaderView='{toolbar}' + horizontalScrollBarPolicy='{JScrollPane.HORIZONTAL_SCROLLBAR_NEVER}' + verticalScrollBarPolicy='{JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED}'> + + <!-- list of movies --> + <JList id='list' + cellRenderer='{getContextValue(DecoratorProviderListCellRenderer.class)}'/> + + <!-- list header --> + <JToolBar id='toolbar' floatable='false' layout='{new BorderLayout()}'> + <JPanel layout='{new GridLayout(1,0)}' + constraints='BorderLayout.CENTER'> + + <!-- to show the selected actor --> + <JButton text='jaxxdemo.action.show' + enabled='{list.getSelectedIndex()!=-1}' + onActionPerformed='getHandler().selectChild(this, (Movie) list.getSelectedValue())'/> + + <!-- to show a new actor --> + <JButton text='jaxxdemo.action.add'/> + + <!-- to delete the selected actor --> + <JButton text='jaxxdemo.action.remove' + enabled='{list.getSelectedIndex()!=-1}'/> + </JPanel> + + <BeanListHeader id='listHeader' constraints='BorderLayout.EAST' + i18nPrefix='jaxxdemo.common.' + data='{getData()}' genericType='Movie' + list='{list}' showReset='true' + beanType='{Movie.class}'/> + </JToolBar> + </JScrollPane> + + </JPanel> +</AbstractContentUI> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java new file mode 100644 index 0000000..0b37a19 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/ActorsTreeNodeLoador.java @@ -0,0 +1,81 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.tree; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.People; +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; + +import java.util.List; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class ActorsTreeNodeLoador extends NavTreeNodeChildLoador<People, People, NavDemoTreeNode> { + + private static final long serialVersionUID = 1L; + + public ActorsTreeNodeLoador() { + super(People.class); + } + + @Override + public List<People> getData(Class<?> parentClass, + String moviesId, + NavDataProvider dataProvider) throws Exception { + + // Get people for parentId + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // If its not root + if (moviesId != null) { + + // Return peoples for movies id + return provider.getPeoples(moviesId); + } + + // Return all peoples + return provider.getPeoples(); + } + + @Override + public NavDemoTreeNode createNode(People data, NavDataProvider dataProvider) { + + NavDemoTreeNode actorNode; + + // Create actor static nodes + actorNode = new NavDemoTreeNode( + getBeanType(), + data.getId(), + null, + null + ); + + return actorNode; + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java new file mode 100644 index 0000000..54ffee8 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/MoviesTreeNodeLoador.java @@ -0,0 +1,96 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.tree; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.feature.nav.NavDemoHandler; +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.NavHelper; +import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; + +import java.util.List; + +import static org.nuiton.i18n.I18n.n_; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class MoviesTreeNodeLoador extends NavTreeNodeChildLoador<Movie, Movie, NavDemoTreeNode> { + + private static final long serialVersionUID = 1L; + + protected boolean isTreeTable; + + public MoviesTreeNodeLoador() { + this(false); + } + + public MoviesTreeNodeLoador(boolean isTreeTable) { + super(Movie.class); + this.isTreeTable = isTreeTable; + } + + @Override + public List<Movie> getData(Class<?> parentClass, + String parentId, + NavDataProvider dataProvider) throws Exception { + + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // Return all movies + return provider.getMovies(); + } + + @Override + public NavDemoTreeNode createNode(Movie data, NavDataProvider dataProvider) { + + NavDemoTreeNode moviesNode; + NavDemoTreeNode actorsCategoryNode; + + // Create movies static nodes + moviesNode = new NavDemoTreeNode( + getBeanType(), + data.getId(), + null, + null + ); + + // Create clients category node + actorsCategoryNode = new NavDemoTreeNode( + String.class, + n_(NavDemoHandler.ACTORS_CATEGORY_NODE), + null, + NavHelper.getChildLoador(ActorsTreeNodeLoador.class) + ); + + // Add actors nodes to movies node + moviesNode.add(actorsCategoryNode); + + return moviesNode; + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java new file mode 100644 index 0000000..16e0072 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeCellRenderer.java @@ -0,0 +1,116 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.tree; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.entities.People; +import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.decorator.Decorator; +import org.nuiton.util.decorator.DecoratorProvider; + +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeModel; +import java.awt.Component; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavDemoTreeCellRenderer extends AbstractNavTreeCellRenderer<DefaultTreeModel, NavDemoTreeNode> { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(NavDemoTreeCellRenderer.class); + + protected DecoratorProvider decoratorProvider; + + public NavDemoTreeCellRenderer(DecoratorProvider decoratorProvider, + DemoDataProvider provider) { + setDataProvider(provider); + this.decoratorProvider = decoratorProvider; + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + @Override + protected String computeNodeText(NavDemoTreeNode node) { + + // Get node type + Class<?> editType = node.getInternalClass(); + String id = node.getId(); + + // get decorator + Decorator<?> decorator = decoratorProvider.getDecoratorByType(editType); + + Object toDecorate = null; + + // People node + if (editType.equals(People.class)) { + toDecorate = getDataProvider().getPeople(id); + + // Movie node + } else if (editType.equals(Movie.class)) { + toDecorate = getDataProvider().getMovie(id); + } + + // Get decorated value + String decorated = decorator.toString(toDecorate); + + if (log.isDebugEnabled()) { + log.debug("Compute text for node " + + node + " return " + + decorated); + } + + return decorated; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + + // get node + NavDemoTreeNode node = (NavDemoTreeNode) value; + + // get text for node + String text = getNodeText(node); + + // Render node + return super.getTreeCellRendererComponent(tree, text, sel, + expanded, leaf, + row, hasFocus); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java new file mode 100644 index 0000000..598ef03 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeHelper.java @@ -0,0 +1,88 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.tree; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.feature.nav.NavDemoHandler; +import jaxx.runtime.swing.nav.tree.NavTreeHelper; + +import javax.swing.tree.DefaultTreeModel; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavDemoTreeHelper extends NavTreeHelper<NavDemoTreeNode> { + + public NavDemoTreeHelper(DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + public DefaultTreeModel createModel() { + + // Create root static node + NavDemoTreeNode root = new NavDemoTreeNode( + String.class, + "Root node", + null, + null + ); + + // Create movies category node + NavDemoTreeNode moviesCategoryNode = new NavDemoTreeNode( + String.class, + NavDemoHandler.MOVIES_CATEGORY_NODE, + null, + getChildLoador(MoviesTreeNodeLoador.class) + ); + + // Create peoples category node + NavDemoTreeNode peoplesCategoryNode = new NavDemoTreeNode( + String.class, + NavDemoHandler.ACTORS_CATEGORY_NODE, + null, + getChildLoador(ActorsTreeNodeLoador.class) + ); + + // Add to root + root.add(moviesCategoryNode); + root.add(peoplesCategoryNode); + + // Create model + DefaultTreeModel model = createModel(root); + + // Populate childs nodes + root.populateChilds(getBridge(), getDataProvider()); + + return model; + } + +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java new file mode 100644 index 0000000..52dfa33 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/tree/NavDemoTreeNode.java @@ -0,0 +1,49 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.tree; + +import jaxx.runtime.swing.nav.tree.NavTreeNode; +import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavDemoTreeNode extends NavTreeNode<NavDemoTreeNode> { + + private static final long serialVersionUID = 1L; + + public NavDemoTreeNode(String id) { + super(id); + } + + public NavDemoTreeNode(Class<?> internalClass, + String id, + String context, + NavTreeNodeChildLoador<?, ?, NavDemoTreeNode> loador) { + super(internalClass, id, context, loador); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java new file mode 100644 index 0000000..03f8b78 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/ActorsTreeTableNodeLoador.java @@ -0,0 +1,82 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.treetable; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.People; +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; + +import java.util.List; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class ActorsTreeTableNodeLoador extends NavTreeTableNodeChildLoador<People, People, NavDemoTreeTableNode> { + + private static final long serialVersionUID = 1L; + + public ActorsTreeTableNodeLoador() { + super(People.class); + } + + @Override + public List<People> getData(Class<?> parentClass, + String moviesId, + NavDataProvider dataProvider) throws Exception { + + // Get people for parentId + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // If its not root + if (moviesId != null) { + + // Return peoples for movies id + return provider.getPeoples(moviesId); + } + + // Return all peoples + return provider.getPeoples(); + } + + @Override + public NavDemoTreeTableNode createNode(People data, NavDataProvider dataProvider) { + + NavDemoTreeTableNode actorNode; + + // Create actor static nodes + + actorNode = new NavDemoTreeTableNode( + getBeanType(), + data.getId(), + null, + null + ); + + return actorNode; + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java new file mode 100644 index 0000000..7d22b85 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/MoviesTreeTableNodeLoador.java @@ -0,0 +1,97 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.treetable; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.feature.nav.NavDemoHandler; +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.NavHelper; +import jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; + +import java.util.List; + +import static org.nuiton.i18n.I18n.n_; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class MoviesTreeTableNodeLoador extends NavTreeTableNodeChildLoador<Movie, Movie, NavDemoTreeTableNode> { + + private static final long serialVersionUID = 1L; + + protected boolean isTreeTable; + + public MoviesTreeTableNodeLoador() { + this(false); + } + + public MoviesTreeTableNodeLoador(boolean isTreeTable) { + super(Movie.class); + this.isTreeTable = isTreeTable; + } + + @Override + public List<Movie> getData(Class<?> parentClass, + String parentId, + NavDataProvider dataProvider) throws Exception { + + DemoDataProvider provider = (DemoDataProvider) dataProvider; + + // Return all movies + return provider.getMovies(); + } + + @Override + public NavDemoTreeTableNode createNode(Movie data, + NavDataProvider dataProvider) { + + NavDemoTreeTableNode moviesNode; + NavDemoTreeTableNode actorsCategoryNode; + + // Create movies static nodes + moviesNode = new NavDemoTreeTableNode( + getBeanType(), + data.getId(), + null, + null + ); + + // Create clients category node + actorsCategoryNode = new NavDemoTreeTableNode( + String.class, + n_(NavDemoHandler.ACTORS_CATEGORY_NODE), + null, + NavHelper.getChildLoador(ActorsTreeTableNodeLoador.class) + ); + + // Add actors nodes to movies node + moviesNode.add(actorsCategoryNode); + + return moviesNode; + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java new file mode 100644 index 0000000..10e8799 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableHelper.java @@ -0,0 +1,88 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.feature.nav.treetable; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.feature.nav.NavDemoHandler; +import jaxx.runtime.swing.nav.treetable.NavTreeTableHelper; +import jaxx.runtime.swing.nav.treetable.NavTreeTableModel; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavDemoTreeTableHelper extends NavTreeTableHelper<NavDemoTreeTableNode> { + + public NavDemoTreeTableHelper(DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + + public NavTreeTableModel createModel() { + + // Create root static node + NavDemoTreeTableNode root = new NavDemoTreeTableNode( + String.class, + "Root node", + null, + null + ); + + // Create movies category node + NavDemoTreeTableNode moviesCategoryNode = new NavDemoTreeTableNode( + String.class, + NavDemoHandler.MOVIES_CATEGORY_NODE, + null, + getChildLoador(MoviesTreeTableNodeLoador.class) + ); + + // Create peoples category node + NavDemoTreeTableNode peoplesCategoryNode = new NavDemoTreeTableNode( + String.class, + NavDemoHandler.ACTORS_CATEGORY_NODE, + null, + getChildLoador(ActorsTreeTableNodeLoador.class) + ); + + // Add to root + root.add(moviesCategoryNode); + root.add(peoplesCategoryNode); + + // Create model + NavDemoTreeTableModel delegate = new NavDemoTreeTableModel(getDataProvider()); + NavTreeTableModel model = createModel(root, delegate); + + // Populate childs nodes + root.populateChilds(getBridge(), getDataProvider()); + + return model; + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java new file mode 100644 index 0000000..2f54450 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableModel.java @@ -0,0 +1,119 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.feature.nav.treetable; + +import jaxx.demo.entities.DemoDataProvider; +import jaxx.demo.entities.Movie; +import jaxx.demo.entities.People; +import jaxx.runtime.swing.nav.NavNode; +import jaxx.runtime.swing.nav.treetable.NavTreeTableModel; + +import static org.nuiton.i18n.I18n._; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavDemoTreeTableModel extends NavTreeTableModel.MyDefaultTreeTableModel { + + protected DemoDataProvider dataProvider; + + public NavDemoTreeTableModel(DemoDataProvider dataProvider) { + this.dataProvider = dataProvider; + } + + @Override + public Object getValueAt(Object o, int i) { + NavNode node = (NavNode) o; + + // Get node type + Class<?> editType = node.getInternalClass(); + String id = node.getId(); + + // If it's category node + if (node.isStringNode()) { + if (i == 0) { + return _(id); + } + return ""; + + // People node + } else if (editType.equals(People.class)) { + People people = dataProvider.getPeople(id); + return getPeopleColumn(people, i); + + // Movie node + } else if (editType.equals(Movie.class)) { + Movie movie = dataProvider.getMovie(id); + return getMovieColumn(movie, i); + } + + // This never append + return "not found"; + } + + private String getMovieColumn(Movie movie, int i) { + String result = ""; + + switch (i) { + case 0: + result = movie.getTitle(); + break; + case 2: + result = String.valueOf(movie.getYear()); + break; + } + return result; + } + + protected String getPeopleColumn(People people, int i) { + String result = ""; + + switch (i) { + case 0: + result = people.getFirstName(); + break; + case 1: + result = people.getLastName(); + break; + case 2: + result = String.valueOf(people.getAge()); + break; + } + return result; + } + + @Override + public String[] getColumnsNames() { + return new String[]{_("jaxxdemo.common.firstName"), + _("jaxxdemo.common.lastName"), + _("jaxxdemo.common.age")}; + } + + @Override + public boolean isCellEditable(Object node, int column) { + return false; + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java new file mode 100644 index 0000000..79a1a0b --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/nav/treetable/NavDemoTreeTableNode.java @@ -0,0 +1,47 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.demo.feature.nav.treetable; + +import jaxx.runtime.swing.nav.treetable.NavTreeTableNode; +import jaxx.runtime.swing.nav.treetable.NavTreeTableNodeChildLoador; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavDemoTreeTableNode extends NavTreeTableNode<NavDemoTreeTableNode> { + private static final long serialVersionUID = 1L; + + protected NavDemoTreeTableNode(String id) { + super(id); + } + + public NavDemoTreeTableNode(Class<?> internalClass, + String id, + String context, + NavTreeTableNodeChildLoador<?, ?, NavDemoTreeTableNode> childLoador) { + super(internalClass, id, context, childLoador); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/Validation.css b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/Validation.css new file mode 100644 index 0000000..e0c4281 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/Validation.css @@ -0,0 +1,29 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +JSlider { + paintTicks: true; + minorTickSpacing: 5; + majorTickSpacing: 10; +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/ValidationListDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/ValidationListDemo.jaxx new file mode 100644 index 0000000..85a1185 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/ValidationListDemo.jaxx @@ -0,0 +1,372 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <style source="Validation.css"/> + + <import> + javax.swing.JOptionPane + static org.nuiton.i18n.I18n.n_ + jaxx.demo.entities.Identity + jaxx.demo.entities.Model + jaxx.runtime.validator.swing.SwingValidatorMessageListRenderer + jaxx.runtime.validator.swing.SwingValidatorMessageListModel + + java.io.File + </import> + + <script><![CDATA[ + +void $afterCompleteSetup() { +} + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "Validation.css", + "Identity.java", "Identity-error-validation.xml", "Identity-info-validation.xml", "Identity-warning-validation.xml", + "Model.java", "Model-error-validation.xml", "Model-info-validation.xml", "Model-warning-validation.xml" + }; +} +]]> + </script> + <!-- models --> + <Model id='model1'/> + <Model id='model2'/> + <Identity id='identity'/> + + <!-- errors model --> + <SwingValidatorMessageListModel id='errorListModel' + onContentsChanged='ok.setEnabled(errorListModel.isEmpty())'/> + + <!-- validators --> + <BeanValidator id='validator' bean='model1' + uiClass="jaxx.runtime.validator.swing.ui.ImageValidationUI"> + <field name="text"/> + <field name="text2"/> + <field name="ratio"/> + </BeanValidator> + <BeanValidator id='validator2' bean='model2' + uiClass="jaxx.runtime.validator.swing.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' + uiClass="jaxx.runtime.validator.swing.ui.TranslucentValidationUI"> + <field name="email" component="email2"/> + </BeanValidator> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <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='{model1.getText()}' + _validatorLabel='{n_("form.text")}' + onKeyReleased='model1.setText(text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='text2' text='{model1.getText2()}' + _validatorLabel='{n_("form.text2")}' + onKeyReleased='model1.setText2(text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='ratio' minimum='0' maximum='100' + value='{model1.getRatio()}' + _validatorLabel='{n_("form.ratio")}' + onStateChanged='model1.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='{model1.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model1.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model1.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()}' + _validatorLabel='{n_("form2.text")}' + onKeyReleased='model2.setText(_text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text2' text='{model2.getText2()}' + _validatorLabel='{n_("form2.text2")}' + onKeyReleased='model2.setText2(_text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='_ratio' minimum='0' maximum='100' + value='{model2.getRatio()}' + _validatorLabel='{n_("form2.ratio")}' + onStateChanged='model2.setRatio(_ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model2.getRatio()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' + layout='{new GridLayout()}' width='250' height='180'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JTextField id='firstName' text='{identity.getFirstName()}' + onKeyReleased='identity.setFirstName(firstName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JTextField id='lastName' text='{identity.getLastName()}' + onKeyReleased='identity.setLastName(lastName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JTextField id='email2' text='{identity.getEmail()}' + onKeyReleased='identity.setEmail(email2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JSlider id='age' minimum='0' maximum='100' + value='{identity.getAge()}' + onStateChanged='identity.setAge(age.getValue())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file :'/> + </cell> + <cell> + <JTextField id='config' text='{identity.getConfig()+""}' + onKeyReleased='identity.setConfig(new File(config.getText()))'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Working directory:'/> + </cell> + <cell> + <JTextField id='dir' text='{identity.getDir()+""}' + onKeyReleased='identity.setDir(new File(dir.getText()))'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getFirstName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getLastName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getEmail()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JLabel text='{identity.getAge()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file:'/> + </cell> + <cell> + <JLabel text='{identity.getConfig()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Directory file:'/> + </cell> + <cell> + <JLabel text='{identity.getDir()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel border='{BorderFactory.createTitledBorder("Messages")}' + layout='{new GridLayout()}' height='200' + width='500'> + <JScrollPane> + <JList id='errorList' model='{errorListModel}' + cellRenderer='{new SwingValidatorMessageListRenderer()}'/> + </JScrollPane> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel layout='{new GridLayout(1,2,0,0)}'> + <JButton id='cancel' text='cancel' + onActionPerformed='JOptionPane.showMessageDialog(this, cancel.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + <JButton id='ok' text='valid' + onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + </JPanel> + </cell> + </row> + </Table> + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/ValidationTableDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/ValidationTableDemo.jaxx new file mode 100644 index 0000000..60b024f --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/feature/validation/ValidationTableDemo.jaxx @@ -0,0 +1,377 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + <style source="Validation.css"/> + + <import> + javax.swing.JOptionPane + static org.nuiton.i18n.I18n.n_ + jaxx.demo.entities.Identity + jaxx.demo.entities.Model + jaxx.runtime.validator.swing.SwingValidatorUtil + jaxx.runtime.validator.swing.SwingValidatorMessageTableRenderer + jaxx.runtime.validator.swing.SwingValidatorMessageTableModel + + java.io.File + </import> + + <script><![CDATA[ +void $afterCompleteSetup() { + SwingValidatorUtil.installUI(errorTable, new SwingValidatorMessageTableRenderer()); +} + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "Validation.css", + "Identity.java", "Identity-error-validation.xml", "Identity-info-validation.xml", "Identity-warning-validation.xml", + "Model.java", "Model-error-validation.xml", "Model-info-validation.xml", "Model-warning-validation.xml" + }; +} +]]></script> + + <!-- models --> + <Model id='model1'/> + <Model id='model2'/> + <Identity id='identity'/> + + <!-- errors model --> + <SwingValidatorMessageTableModel id='errorTableModel' + onTableChanged='ok.setEnabled(errorTableModel.getRowCount()==0)'/> + + <!-- validators --> + <BeanValidator id='validator' bean='model1' + uiClass="jaxx.runtime.validator.swing.ui.ImageValidationUI"> + <field name="text"/> + <field name="text2"/> + <field name="ratio"/> + </BeanValidator> + <BeanValidator id='validator2' bean='model2' + uiClass="jaxx.runtime.validator.swing.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' + uiClass="jaxx.runtime.validator.swing.ui.TranslucentValidationUI"> + <field name="email" component="email2"/> + </BeanValidator> + + <Table fill='both' constraints='BorderLayout.CENTER'> + <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='{model1.getText()}' + onKeyReleased='model1.setText(text.getText())' + _validatorLabel='{n_("form.text")}' + /> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='text2' text='{model1.getText2()}' + onKeyReleased='model1.setText2(text2.getText())' + _validatorLabel='{n_("form.text2")}' + /> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='ratio' minimum='0' maximum='100' + value='{model1.getRatio()}' + _validatorLabel='{n_("form.ratio")}' + onStateChanged='model1.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='{model1.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model1.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model1.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()}' + _validatorLabel='{n_("form2.text")}' + onKeyReleased='model2.setText(_text.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JTextField id='_text2' text='{model2.getText2()}' + _validatorLabel='{n_("form2.text2")}' + onKeyReleased='model2.setText2(_text2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JSlider id='_ratio' minimum='0' maximum='100' + value='{model2.getRatio()}' + _validatorLabel='{n_("form2.ratio")}' + onStateChanged='model2.setRatio(_ratio.getValue())'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Model2")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Text2:'/> + </cell> + <cell weightx='1'> + <JLabel text='{model2.getText2()}'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Ratio:'/> + </cell> + <cell> + <JLabel text='{model2.getRatio()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identify Form")}' + layout='{new GridLayout()}' width='250' height='180'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JTextField id='firstName' text='{identity.getFirstName()}' + onKeyReleased='identity.setFirstName(firstName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JTextField id='lastName' text='{identity.getLastName()}' + onKeyReleased='identity.setLastName(lastName.getText())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JTextField id='email2' text='{identity.getEmail()}' + onKeyReleased='identity.setEmail(email2.getText())'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JSlider id='age' minimum='0' maximum='100' + value='{identity.getAge()}' + onStateChanged='identity.setAge(age.getValue())'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file :'/> + </cell> + <cell> + <JTextField id='config' text='{identity.getConfig()+""}' + onKeyReleased='identity.setConfig(new File(config.getText()))'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Working directory:'/> + </cell> + <cell> + <JTextField id='dir' text='{identity.getDir()+""}' + onKeyReleased='identity.setDir(new File(dir.getText()))'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <JPanel border='{BorderFactory.createTitledBorder("Identity Model")}' + layout='{new GridLayout()}' width='250' height='120'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='FirstName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getFirstName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='LastName:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getLastName()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Email:'/> + </cell> + <cell weightx='1'> + <JLabel text='{identity.getEmail()}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Age:'/> + </cell> + <cell> + <JLabel text='{identity.getAge()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Config file:'/> + </cell> + <cell> + <JLabel text='{identity.getConfig()+""}'/> + </cell> + </row> + <row> + <cell> + <JLabel text='Directory file:'/> + </cell> + <cell> + <JLabel text='{identity.getDir()+""}'/> + </cell> + </row> + </Table> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel border='{BorderFactory.createTitledBorder("Messages")}' + layout='{new GridLayout()}' height='200' + width='500'> + <JScrollPane columnHeaderView='{errorTable.getTableHeader()}'> + <JTable id='errorTable' model='{errorTableModel}' rowSelectionAllowed='true' + autoCreateRowSorter='true' + autoResizeMode='2' cellSelectionEnabled='false' + selectionMode='0'/> + </JScrollPane> + </JPanel> + </cell> + </row> + <row> + <cell columns='2' fill="both"> + <JPanel layout='{new GridLayout(1,2,0,0)}'> + <JButton id='cancel' text='cancel' + onActionPerformed='JOptionPane.showMessageDialog(this, cancel.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + <JButton id='ok' text='valid' + onActionPerformed='JOptionPane.showMessageDialog(this, ok.getText() + " clicked!", "onActionPerformed", JOptionPane.INFORMATION_MESSAGE);'/> + </JPanel> + </cell> + </row> + </Table> + +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.css b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.css new file mode 100644 index 0000000..7c91e0d --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.css @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +#table { + border: {BorderFactory.createEmptyBorder(4, 4, 4, 4)}; + font-face:"Trebuchet MS"; +} + +#display { + background: #BCE5AD; + opaque: true; + horizontalAlignment: right; + border: {BorderFactory.createBevelBorder(BevelBorder.LOWERED)}; + font-size:22; + font-weight: bold; +} + +#display:{object.getText().startsWith( "-" )} { +foreground: red; +} + +JButton { + font-size: 18; + width: 80; + height: 35; +} + +JButton.digit { + foreground: blue; +} + +JButton#dot { + font-size: 20; +} + +JButton.operator { + font-size: 16; + foreground: #009900; +} + +JButton.clear { + foreground: red; +} + +/*JButton:mouseover { + font-weight: bold; +}*/ + +JButton.operator:mouseover { + font-weight: bold; +} + +JButton.operator:mouseover { + font-weight: normal; +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jaxx new file mode 100644 index 0000000..bec411d --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorDemo.jaxx @@ -0,0 +1,146 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + java.awt.Color + javax.swing.BorderFactory + javax.swing.border.BevelBorder + </import> + + <!--<style source='CalculatorDemo.css'/>--> + <script><![CDATA[ + plus.setText("+"); + sign.setText("+/-"); + +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "CalculatorDemo.css", "CalculatorEngine.java" }; +} +]]> + </script> + <!-- use fully-qualified name just in case this is compiled into a different package --> + <CalculatorEngine id='engine'/> + + <Table fill='both'> + <row> + <cell columns='4'> + <JLabel id='display' text='{engine.getDisplayText()}'/> + </cell> + </row> + + <row> + <cell columns='2'> + <JButton id='c' text='C' onActionPerformed='engine.clear()' + styleClass='clear'/> + </cell> + <cell> + <JButton id='ce' text='CE' onActionPerformed='engine.clearEntry()' + styleClass='clear'/> + </cell> + <cell> + <JButton id='equals' text='=' onActionPerformed='engine.equal()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d7' text='7' onActionPerformed='engine.digit(7)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d8' text='8' onActionPerformed='engine.digit(8)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d9' text='9' onActionPerformed='engine.digit(9)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='plus' onActionPerformed='engine.add()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d4' text='4' onActionPerformed='engine.digit(4)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d5' text='5' onActionPerformed='engine.digit(5)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d6' text='6' onActionPerformed='engine.digit(6)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='subtract' text='-' onActionPerformed='engine.subtract()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d1' text='1' onActionPerformed='engine.digit(1)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d2' text='2' onActionPerformed='engine.digit(2)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='d3' text='3' onActionPerformed='engine.digit(3)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='multiply' text='x' onActionPerformed='engine.multiply()' + styleClass='operator'/> + </cell> + </row> + + <row> + <cell> + <JButton id='d0' text='0' onActionPerformed='engine.digit(0)' + styleClass='digit'/> + </cell> + <cell> + <JButton id='sign' onActionPerformed='engine.toggleSign()' + styleClass='operator'/> + </cell> + <cell> + <JButton id='dot' text='.' onActionPerformed='engine.dot()' + styleClass='digit'/> + </cell> + <cell> + <JButton id='divide' text='÷' onActionPerformed='engine.divide()' + styleClass='operator'/> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorEngine.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorEngine.java new file mode 100644 index 0000000..5084189 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CalculatorEngine.java @@ -0,0 +1,211 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.fun; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.math.BigDecimal; + +public class CalculatorEngine { + public static final String DISPLAY_TEXT_PROPERTY = "displayText"; + + public static final int ADD = 0; + + public static final int SUBTRACT = 1; + + public static final int MULTIPLY = 2; + + public static final int DIVIDE = 3; + + public static final int RESULT = 4; + + private int operation = -1; + + private boolean clear = true; // true to clear on next key + + private String displayText = "0"; + + private BigDecimal value; + + private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + + + public String getDisplayText() { + return displayText; + } + + + public void setDisplayText(String displayText) { + String oldDisplayText = this.displayText; + this.displayText = displayText; + firePropertyChange(DISPLAY_TEXT_PROPERTY, oldDisplayText, displayText); + } + + + public void clear() { + clearEntry(); + value = new BigDecimal(0); + operation = -1; + } + + + public void clearEntry() { + setDisplayText("0"); + clear = true; + } + + + private void checkClear() { + if (clear) { + setDisplayText(""); + clear = false; + } + } + + + public void digit(int digit) { + checkClear(); + setDisplayText(getDisplayText() + String.valueOf(digit)); + } + + + public void dot() { + checkClear(); + if (getDisplayText().indexOf('.') == -1) { + if (getDisplayText().length() == 0) { + setDisplayText("0."); + } else { + setDisplayText(getDisplayText() + '.'); + } + } + } + + + public void toggleSign() { + String text = getDisplayText(); + if (text.startsWith("-")) { + text = text.substring(1); + } else if (!text.equals("0")) { + text = '-' + text; + } + setDisplayText(text); + } + + + public void equal() { + BigDecimal displayValue = new BigDecimal(getDisplayText()); + BigDecimal newValue = displayValue; + switch (operation) { + case ADD: + newValue = value.add(displayValue); + break; + case SUBTRACT: + newValue = value.subtract(displayValue); + break; + case MULTIPLY: + newValue = value.multiply(displayValue); + break; + case DIVIDE: + newValue = value.divide(displayValue, 8, BigDecimal.ROUND_HALF_UP); + break; + } + value = newValue; + setDisplayText(toString(newValue)); + clear = true; + operation = -1; + } + + + public static String toString(BigDecimal decimal) { + // can't use stripTrailingZeros, as it wasn't introduced until 1.5 + String result = decimal.toString(); + if (result.indexOf(".") != -1) { + while (result.endsWith("0")) { + result = result.substring(0, result.length() - 1); + } + if (result.endsWith(".")) { + result = result.substring(0, result.length() - 1); + } + } + return result; + } + + + public void operation(int operation) { + if (this.operation != -1) { + equal(); + } else { + value = new BigDecimal(getDisplayText()); + clear = true; + } + this.operation = operation; + } + + + public void add() { + operation(ADD); + } + + + public void subtract() { + operation(SUBTRACT); + } + + + public void multiply() { + operation(MULTIPLY); + } + + + public void divide() { + operation(DIVIDE); + } + + + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(listener); + } + + + public void addPropertyChangeListener(String property, PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(property, listener); + } + + + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(listener); + } + + + public void removePropertyChangeListener(String property, PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(property, listener); + } + + + protected void firePropertyChange(String property, Object oldValue, Object newValue) { + propertyChangeSupport.firePropertyChange(property, oldValue, newValue); + } +} diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CounterDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CounterDemo.jaxx new file mode 100644 index 0000000..3b27cf2 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/CounterDemo.jaxx @@ -0,0 +1,34 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel> + <script>int count;</script> + <JTextField text='{count+""}' constraints='BorderLayout.NORTH'/> + <HBox constraints='BorderLayout.SOUTH'> + <JButton text='Dec (-)' onActionPerformed='count--'/> + <JButton text='Reset' onActionPerformed='count = 0'/> + <JButton text='Inc (+)' onActionPerformed='count++'/> + </HBox> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.css b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.css new file mode 100644 index 0000000..3f84901 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.css @@ -0,0 +1,58 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +JSlider { + paintTicks: true; +} + +JSlider.color { + minorTickSpacing: 10; + majorTickSpacing: 50; + border: {BorderFactory.createEmptyBorder(1, 1, 1, 1)}; +} + +JSlider.color:focused { + border: {BorderFactory.createLineBorder(Color.BLACK, 1)}; +} + +JSlider#red:focused { + background: #E7ADAD; +} + +JSlider#green:focused { + background: #B2E7AD; +} + +JSlider#blue:focused { + background: #ADB2E7; +} + +JSlider#dummySize { + minorTickSpacing: 2; + majorTickSpacing: 6; +} + +JRadioButton { + enabled: {backgroundCheckbox.isSelected()}; +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jaxx b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jaxx new file mode 100644 index 0000000..4855960 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/fun/LabelStyleDemo.jaxx @@ -0,0 +1,133 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<jaxx.demo.DemoPanel layout='{new BorderLayout()}'> + + <import> + java.awt.Color + javax.swing.BorderFactory + </import> + + <!--<style source="LabelStyleDemo.css"/>--> + <script><![CDATA[ +@Override +protected String[] getSources() { + return new String[]{ getDefaultSource(), "LabelStyleDemo.css" }; +} + +]]> + </script> + <Table id='demoPanel' anchor='north' fill='both'> + <row> + <cell weightx='1' weighty='1' insets='6, 3, 0, 0'> + <Table anchor='west' fill='both'> + <row> + <cell> + <JLabel text='Text:'/> + </cell> + <cell weightx='1'> + <JTextField id='text' text='Data Binding'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Red:'/> + </cell> + <cell> + <JSlider id='red' value='128' maximum='255' styleClass='color'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Green:'/> + </cell> + <cell> + <JSlider id='green' value='0' maximum='255' styleClass='color'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Blue:'/> + </cell> + <cell> + <JSlider id='blue' value='255' maximum='255' styleClass='color'/> + </cell> + </row> + + <row> + <cell> + <JLabel text='Size:'/> + </cell> + <cell> + <JSlider id='dummySize' value='36' minimum='6' maximum='60'/> + </cell> + </row> + + <row> + <cell columns='2' fill='both' weighty='1'> + <JPanel border='{BorderFactory.createTitledBorder("Preview")}' + height='90' + layout='{new BorderLayout()}'> + <VBox + background='{(Color)( backgroundCheckbox.isSelected() ? backgroundColor.getSelectedValue() : null)}' + margin='0' + horizontalAlignment='center' + verticalAlignment='middle'> + <JLabel text='{text.getText()}' + font-size='{dummySize.getValue()}' + foreground='{new Color(red.getValue(), green.getValue(), blue.getValue())}'/> + </VBox> + </JPanel> + </cell> + </row> + </Table> + </cell> + + <cell> + <VBox spacing='0' + border='{BorderFactory.createTitledBorder("Background")}'> + <JCheckBox id='backgroundCheckbox' text='Show Background'/> + <JRadioButton text='Red' buttonGroup='backgroundColor' + value='{Color.RED}' selected='true'/> + <JRadioButton text='Orange' buttonGroup='backgroundColor' + value='{Color.ORANGE}'/> + <JRadioButton text='Yellow' buttonGroup='backgroundColor' + value='{Color.YELLOW}'/> + <JRadioButton text='Green' buttonGroup='backgroundColor' + value='{Color.GREEN}'/> + <JRadioButton text='Cyan' buttonGroup='backgroundColor' + value='{Color.CYAN}'/> + <JRadioButton text='Blue' buttonGroup='backgroundColor' + value='{Color.BLUE}'/> + <JRadioButton text='Purple' buttonGroup='backgroundColor' + value='{new Color(160, 30, 255)}'/> + </VBox> + </cell> + </row> + </Table> +</jaxx.demo.DemoPanel> diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java new file mode 100644 index 0000000..09ed8b8 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoCellRenderer.java @@ -0,0 +1,107 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.tree; + +import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeModel; +import java.awt.Component; + +import static org.nuiton.i18n.I18n._; + +/** + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class DemoCellRenderer extends AbstractNavTreeCellRenderer<DefaultTreeModel, DemoNode> { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(DemoCellRenderer.class); + + + public DemoCellRenderer(jaxx.demo.tree.DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public jaxx.demo.entities.DemoDataProvider getDataProvider() { + return (jaxx.demo.entities.DemoDataProvider) super.getDataProvider(); + } + + @Override + protected String computeNodeText(DemoNode node) { + + if (node == null) { + return ""; + } + + + String toDecorate; + + String id = node.getId(); + + if (node.isStringNode()) { + + // String node + toDecorate = _(id); + } else { + + // Demo node + toDecorate = id; + } + + if (log.isDebugEnabled()) { + log.debug("Compute text for node " + node + + " (" + node.getInternalClass() + ") = " + toDecorate); + } + + return toDecorate; + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, int row, + boolean hasFocus) { + + // get node + DemoNode node = (DemoNode) value; + + // get text for node + String text = getNodeText(node); + + // Render node + return super.getTreeCellRendererComponent(tree, text, sel, + expanded, leaf, + row, hasFocus); + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java new file mode 100644 index 0000000..99a0d2f --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoDataProvider.java @@ -0,0 +1,208 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.tree; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import jaxx.demo.component.jaxx.BoxedDecoratorDemo; +import jaxx.demo.component.jaxx.StatusMessagePanelDemo; +import jaxx.demo.component.jaxx.editor.ComboEditorDemo; +import jaxx.demo.component.jaxx.editor.DatePickerDemo; +import jaxx.demo.component.jaxx.editor.FileEditorDemo; +import jaxx.demo.component.jaxx.editor.ListSelectorDemo; +import jaxx.demo.component.jaxx.editor.I18nEditorDemo; +import jaxx.demo.component.jaxx.editor.NumberEditorDemo; +import jaxx.demo.component.jaxx.editor.TimeEditorDemo; +import jaxx.demo.component.swing.HidorButtonDemo; +import jaxx.demo.component.swing.JButtonDemo; +import jaxx.demo.component.swing.JCheckBoxDemo; +import jaxx.demo.component.swing.JCheckBoxMenuItemDemo; +import jaxx.demo.component.swing.JComboBoxDemo; +import jaxx.demo.component.swing.JDialogDemo; +import jaxx.demo.component.swing.JListDemo; +import jaxx.demo.component.swing.JMenuItemDemo; +import jaxx.demo.component.swing.JPasswordFieldDemo; +import jaxx.demo.component.swing.JProgressBarDemo; +import jaxx.demo.component.swing.JRadioButtonDemo; +import jaxx.demo.component.swing.JRadioButtonMenuItemDemo; +import jaxx.demo.component.swing.JSliderDemo; +import jaxx.demo.component.swing.JSpinnerDemo; +import jaxx.demo.component.swing.JSplitPaneDemo; +import jaxx.demo.component.swing.JTextAreaDemo; +import jaxx.demo.component.swing.JTextFieldDemo; +import jaxx.demo.component.swing.JToggleButtonDemo; +import jaxx.demo.feature.databinding.BeanDataBindingDemo; +import jaxx.demo.feature.databinding.BindingExtremeDemo; +import jaxx.demo.feature.nav.NavDemo; +import jaxx.demo.feature.validation.ValidationListDemo; +import jaxx.demo.feature.validation.ValidationTableDemo; +import jaxx.demo.fun.CalculatorDemo; +import jaxx.demo.fun.CounterDemo; +import jaxx.demo.fun.LabelStyleDemo; +import jaxx.runtime.swing.nav.NavDataProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import static org.nuiton.i18n.I18n.n_; + +/** + * Data provider of the navigation tree. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public class DemoDataProvider implements NavDataProvider { + + /** Logger */ + static private final Log log = LogFactory.getLog(DemoDataProvider.class); + + /** mapping of demo per package */ + protected Map<String, List<Object>> mapping; + + public DemoDataProvider() { + + mapping = new HashMap<String, List<Object>>(); + + if (log.isDebugEnabled()) { + log.debug("for " + this); + } + + addMapping("jaxxdemo.tree", + n_("jaxxdemo.component.swing"), + n_("jaxxdemo.component.jaxx"), + n_("jaxxdemo.feature"), + n_("jaxxdemo.fun") + ); + + addMapping(n_("jaxxdemo.component.swing"), + n_("jaxxdemo.component.swing.buttons"), + n_("jaxxdemo.component.swing.form"), + n_("jaxxdemo.component.swing.layout"), + n_("jaxxdemo.component.swing.menu"), + n_("jaxxdemo.component.swing.window"), + JProgressBarDemo.class + ); + + addMapping(n_("jaxxdemo.component.swing.buttons"), + JButtonDemo.class, + JCheckBoxDemo.class, + JRadioButtonDemo.class, + JToggleButtonDemo.class + ); + + addMapping(n_("jaxxdemo.component.swing.form"), + n_("jaxxdemo.component.swing.form.text"), + JComboBoxDemo.class, + JListDemo.class, + JSliderDemo.class, + JSpinnerDemo.class + ); + + addMapping(n_("jaxxdemo.component.swing.form.text"), + JPasswordFieldDemo.class, + JTextFieldDemo.class, + JTextAreaDemo.class + ); + + addMapping(n_("jaxxdemo.component.swing.layout"), + JSplitPaneDemo.class + ); + + addMapping(n_("jaxxdemo.component.swing.menu"), + JMenuItemDemo.class, + JCheckBoxMenuItemDemo.class, + JRadioButtonMenuItemDemo.class + ); + + addMapping(n_("jaxxdemo.component.swing.window"), + JDialogDemo.class + ); + + addMapping(n_("jaxxdemo.component.jaxx"), + HidorButtonDemo.class, + n_("jaxxdemo.component.jaxx.editor"), + StatusMessagePanelDemo.class, + BoxedDecoratorDemo.class + ); + + addMapping(n_("jaxxdemo.component.jaxx.editor"), + TimeEditorDemo.class, + NumberEditorDemo.class, + ComboEditorDemo.class, + I18nEditorDemo.class, + DatePickerDemo.class, + FileEditorDemo.class, + ListSelectorDemo.class + ); + + addMapping(n_("jaxxdemo.feature"), + n_("jaxxdemo.feature.databinding"), + n_("jaxxdemo.feature.validation"), + n_("jaxxdemo.feature.nav") + ); + + addMapping(n_("jaxxdemo.feature.databinding"), + BindingExtremeDemo.class, + BeanDataBindingDemo.class + ); + + addMapping(n_("jaxxdemo.feature.validation"), + ValidationListDemo.class, + ValidationTableDemo.class + ); + + addMapping(n_("jaxxdemo.feature.nav"), + NavDemo.class + ); + + addMapping(n_("jaxxdemo.fun"), + LabelStyleDemo.class, + CounterDemo.class, + CalculatorDemo.class + ); + } + + protected void addMapping(String packageName, Object... classes) { + List<Object> list = Arrays.asList(classes); + if (log.isDebugEnabled()) { + log.debug("Adding mapping [" + packageName + "] : " + list); + } + mapping.put(packageName, list); + } + + @Override + public boolean isEnabled() { + return true; + } + + public List<Object> getImplementations(String packageName) { + return mapping.get(packageName); + } + + +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNode.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNode.java new file mode 100644 index 0000000..bb928fc --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNode.java @@ -0,0 +1,69 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.tree; + +import jaxx.runtime.swing.nav.tree.NavTreeNode; + +/** + * Basic node of the demo. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public class DemoNode extends NavTreeNode<DemoNode> { + + private static final long serialVersionUID = 1L; + + public DemoNode(String id) { + super(String.class, + id, + null, + DemoTreeHelper.getChildLoador(DemoNodeLoador.class) + ); + } + + @Override + public DemoNode getContainerNode() { + if (isStringNode()) { + // on est sur un noeud de type String, donc on regarde sur le parent + return this; + } + + // fallback (should never comme here since root is Stringnode) + if (isRoot()) { + // si on arrive sur le root, quelque chose ne va pas, + // on bloque par null, a defaut de declancher une exception + return null; + } + + // cas final : sur un noeud de donnee + classe interne de donnee + return getParent().getContainerNode(); + } + + public DemoNode(Class<?> internalClass) { + super(internalClass, internalClass.getSimpleName(), null, null); + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNodeLoador.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNodeLoador.java new file mode 100644 index 0000000..e0211a1 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoNodeLoador.java @@ -0,0 +1,87 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.tree; + +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.NavNodeChildLoador; +import jaxx.runtime.swing.nav.tree.NavTreeNodeChildLoador; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.List; + +/** + * @author tchemit <tchemit@codelutin.com> + * @since 2.1 + */ +public class DemoNodeLoador extends NavTreeNodeChildLoador<Object, Object, DemoNode> { + + private static final long serialVersionUID = 1L; + + /** Logger */ + static private final Log log = LogFactory.getLog(NavNodeChildLoador.class); + + public DemoNodeLoador() { + super(Object.class); + } + + @Override + public List<Object> getData(Class<?> parentClass, + String packageName, + NavDataProvider dataProvider) throws Exception { + + DemoDataProvider provider = (DemoDataProvider) dataProvider; + List<Object> implementations = provider.getImplementations(packageName); + return implementations; + } + + @Override + public DemoNode createNode(Object data, NavDataProvider dataProvider) { + + if (log.isDebugEnabled()) { + log.debug("Creating node for object : " + data); + } + + DemoNode node = null; + + if (data instanceof String) { + // package node + node = new DemoNode((String) data); + } + + if (data instanceof Class<?>) { + // demo node + node = new DemoNode((Class<?>) data); + } + + if (node == null) { + throw new IllegalArgumentException("Data [" + data + "] can not be use to build a node"); + } + + + return node; + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java new file mode 100644 index 0000000..0629924 --- /dev/null +++ b/trunk/jaxx-demo/src/main/java/jaxx/demo/tree/DemoTreeHelper.java @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo.tree; + +import jaxx.runtime.swing.nav.tree.NavTreeHelper; + +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeModel; + +/** + * @author tchemit <tchemit@codelutin.com> + * @since 2.1 + */ +public class DemoTreeHelper extends NavTreeHelper<DemoNode> { + + public DemoTreeHelper(DemoDataProvider provider) { + setDataProvider(provider); + } + + @Override + public DemoDataProvider getDataProvider() { + return (DemoDataProvider) super.getDataProvider(); + } + + public TreeModel createModel() { + + // Create root static node + DemoNode root = new DemoNode("jaxxdemo.tree"); + + // Create model + DefaultTreeModel model = createModel(root); + + // load all nodes of model + loadAllNodes(root, getDataProvider()); + + return model; + } +} \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_en_GB.properties b/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_en_GB.properties new file mode 100644 index 0000000..0694d5d --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_en_GB.properties @@ -0,0 +1,270 @@ +-= +.= +0= +1= +10= +12= +14= +18= +2= +24= +3= +4= +5= +6= +7= +8= +9= +\== +Age\:= +Animal= +Blue= +Blue\:= +Bold= +Button\ label\:= +C= +CE= +Cancel= +Comments\:= +Config\ file\ \:= +Config\ file\:= +Cyan= +Dec\ (-)= +Demo= +Directory\ file\:= +Editable= +Email\ Address\:= +Email\:= +Enabled= +EnumEditor\ (country)\ \:= +EnumEditor\ (language)\ \:= +Fancy\ Button= +First\ Name\:= +FirstName\:= +Font\ size= +Font\ size\:\ = +Fool\ me\ once= +Fool\ me\ twice= +Green= +Green\:= +Greet= +Help= +Inc\ (+)= +Italic= +JAXX\ Demo= +JMenu\ demo= +Label\ 1= +Label\ 2= +Last\ Name\:= +LastName\:= +Locale\ editor\:= +Message\ Box= +Mineral= +Normal\ text\:= +OK= +Orange= +Password\:= +Purple= +Ratio\:= +Red= +Red\:= +Reset= +Show\ Background= +Show\ password\ dialog= +Sign\ on= +Simple\ Button= +Size\:= +Sources= +Spacing\:= +Start= +Stop= +Supported\ Swing\ components\:= +Text2\:= +Text\:= +Total\:\ = +Underline= +Upper\ case\ text\:= +Use\ the\ spinner\ to= +Username\:= +Vegetable= +View= +Welcome\ to\ the\ JAXX\ framework\!= +Working\ directory\:= +Yellow= +You\ entered\:\ = +Your\ name\:= +\\u00f7= +adjust\ the\ spacing= +between\ these\ lines= +button\ A= +button\ B= +button\ C\ (full\ block)= +button\ D\ (full\ block\ 2)= +cancel= +close=Disable +close2=Disable 2 +close3=Disable 3 +demo.action.reload.application=Reload application +demo.action.reload.logAppender= +demo.action.reload.ui=Reload UI +edit=Edit +edit2=Edit 2 +edit3=Edit 3 +f0= +f1= +file...= +form.ratio=Ratio +form.text=Text +form.text2=Text 2 +form2.ratio=Form 2 Ratio +form2.text=Form 2 Text +form2.text2=Form 2 Text 2 +getModel0().isF0()= +getModel0().isF0()\ &&\ getModel0().isF1()= +getModel0().isF0()\ ||\ getModel0().isF1()= +getModel0().isF1()= +getModel1().isF0()= +getModel1().isF0()\ &&\ getModel1().isF1()= +getModel1().isF0()\ ||\ getModel1().isF1()= +getModel1().isF1()= +getT0().isSelected()= +getT0().isSelected()\ &&\ getT1().isSelected()= +getT0().isSelected()\ ||\ getT1().isSelected()= +getT1().isSelected()= +isF0()= +isF0()\ &&\ isF1()= +isF0()\ ||\ isF1()= +isF1()= +jaxxdemo.about.message=<h3>JAXX Demo</h3><hr/>For more informations, visit the <a href\="http\://maven-site.nuiton.org/jaxx/jaxx-demo">website of the project</a>. +jaxxdemo.action.about=About... +jaxxdemo.action.about.tip=About JAXXDemo... +jaxxdemo.action.add=Add +jaxxdemo.action.configuration=Preferences +jaxxdemo.action.configuration.tip=Change the preferences of the application +jaxxdemo.action.exit=Quit +jaxxdemo.action.exit.tip=Quit JAXXDemo +jaxxdemo.action.fullscreen=Full screen +jaxxdemo.action.fullscreen.tip=Change to full screen mode +jaxxdemo.action.help= +jaxxdemo.action.help.tip=Display help +jaxxdemo.action.locale.fr=French +jaxxdemo.action.locale.fr.tip=Change to french language +jaxxdemo.action.locale.uk=English +jaxxdemo.action.locale.uk.tip=Change to english language +jaxxdemo.action.normalscreen=Normal screen +jaxxdemo.action.normalscreen.tip=Change to normal screen mode +jaxxdemo.action.remove=Remove +jaxxdemo.action.show=show +jaxxdemo.action.site=Web site +jaxxdemo.action.site.tip=Go to the web site +jaxxdemo.common.actors=Actors +jaxxdemo.common.age=Age +jaxxdemo.common.firstName=First name +jaxxdemo.common.id=Id +jaxxdemo.common.image=Image +jaxxdemo.common.lastName=Last name +jaxxdemo.common.movie=Movie +jaxxdemo.common.movies=Movies +jaxxdemo.common.people=People +jaxxdemo.common.title=Title +jaxxdemo.common.year=Year +jaxxdemo.component.jaxx=JAXX Components +jaxxdemo.component.jaxx.editor=Editors +jaxxdemo.component.swing=Swing Components +jaxxdemo.component.swing.buttons=Buttons +jaxxdemo.component.swing.form=Form elements +jaxxdemo.component.swing.form.text=Text +jaxxdemo.component.swing.layout=Layouts +jaxxdemo.component.swing.menu=Menus +jaxxdemo.component.swing.window=windows +jaxxdemo.config.category.directories=Files +jaxxdemo.config.category.directories.description=Files used by application +jaxxdemo.config.category.other=Others +jaxxdemo.config.category.other.description=Others preferences +jaxxdemo.config.configFileName.description=Configuration file name +jaxxdemo.config.ui.demo.path=Path of demo to select when starting application +jaxxdemo.config.ui.fontSize=default font size to use in sources +jaxxdemo.config.ui.fullscreen=To change the screen mode (true for full screen) +jaxxdemo.config.ui.keyOpenConfig=To change key for open config ui +jaxxdemo.config.ui.locale=Language used in application +jaxxdemo.config.ui.logLevel=Log level +jaxxdemo.config.ui.logPatternLayout=Log pattern +jaxxdemo.datePickerEditor.dateResult=Result display +jaxxdemo.datePickerEditor.patternLayout=Date pattern +jaxxdemo.datePickerEditor.showPopupButton=Display popup button +jaxxdemo.feature=Features +jaxxdemo.feature.databinding=Data Binding +jaxxdemo.feature.nav=Jaxx nav API +jaxxdemo.feature.validation=Validation +jaxxdemo.fileEditor.acceptAllFileFilterUsed=Allow all FileFilter +jaxxdemo.fileEditor.directoryEnabled=Enable directory selection +jaxxdemo.fileEditor.extsDescLbl=Extensions description (separated by comma, ex \: text (*.txt), images (*.png)) +jaxxdemo.fileEditor.extsLbl=Extensions (separated by comma, ex \: txt, png) +jaxxdemo.fileEditor.fileEnabled=Enable file selection +jaxxdemo.fileEditor.titleLbl=Open dialog title +jaxxdemo.fun=Fun +jaxxdemo.i18neditor.configuration=Configuration +jaxxdemo.i18neditor.popup.title=Title of popup +jaxxdemo.i18neditor.popupBorderText=Popup title +jaxxdemo.i18neditor.selected.locale=Selected Language +jaxxdemo.i18neditor.showIcon=Show icons +jaxxdemo.i18neditor.showPopupIcon=Show icons in popup +jaxxdemo.i18neditor.showPopupText=Show texts in popup +jaxxdemo.i18neditor.showText=Show text +jaxxdemo.init.closed=JAXXDemo was closed at %1$s +jaxxdemo.init.context.done=Context initialized in %1$s +jaxxdemo.init.ui.done=UI initialized. +jaxxdemo.listSelector.addToolTipLbl=Add button toolTip +jaxxdemo.listSelector.removeToolTipLbl=Remove button toolTip +jaxxdemo.menu.file=File +jaxxdemo.menu.file.locale=Languages +jaxxdemo.menu.help= +jaxxdemo.menu.showLogs=Show logs +jaxxdemo.message.config.loaded=Configuration of JAXXDemo v. %1$s loaded. +jaxxdemo.message.goto.site=Go to JAXXDemo Web site +jaxxdemo.navigation.actor.title=Actor +jaxxdemo.navigation.actors.title=Actors +jaxxdemo.navigation.movie.title=Movie +jaxxdemo.navigation.movies.title=Movies +jaxxdemo.numbereditor.applyNumberPattern=Apply pattern +jaxxdemo.numbereditor.autoPopup=Show automatic popup +jaxxdemo.numbereditor.configuration=Configuration +jaxxdemo.numbereditor.model=Result +jaxxdemo.numbereditor.model.float=Float result \: %1$s +jaxxdemo.numbereditor.model.int=Integer result \: %1$s +jaxxdemo.numbereditor.model.numberPattern=Editor pattern \: %s +jaxxdemo.numbereditor.numberPattern.configuration=Number Pattern +jaxxdemo.numbereditor.showPopupButton=Show Popup button +jaxxdemo.numbereditor.showReset=Show reset button +jaxxdemo.numbereditor.useFloat=Use float +jaxxdemo.numbereditor.useSign=Use Sign +jaxxdemo.timeeditor.editor=Time Editor +jaxxdemo.timeeditor.label=Label +jaxxdemo.timeeditor.model=Result +jaxxdemo.timeeditor.value=Selected time \: %1$tH\:%1$tM +jaxxdemo.title.about=About JAXXDemo... +jaxxdemo.title.showLog=JAXXDemo logs +jaxxdemo.tree.tabtitle=Tree +jaxxdemo.treeTable.tabtitle=TreeTable +jaxxdemo.warning.nimbus.landf=Could not init nymbus look and feel, you need at leasr version 1.6u10 of java. +jaxxdemo.warning.no.ui=No ui environnement detected +model0.f0= +model0.f1= +model0.file...= +model0.isF0()= +model0.isF0()\ &&\ model0.isF1()= +model0.isF0()\ ||\ model0.isF1()= +model0.isF1()= +model1.f0= +model1.f1= +model1.file...= +model1.isF0()= +model1.isF0()\ &&\ model1.isF1()= +model1.isF0()\ ||\ model1.isF1()= +model1.isF1()= +t0.isSelected()= +t0.isSelected()\ &&\ t1.isSelected()= +t0.isSelected()\ ||\ t1.isSelected()= +t1.isSelected()= +valid= +x= diff --git a/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_es_ES.properties b/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_es_ES.properties new file mode 100644 index 0000000..5fc08fd --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_es_ES.properties @@ -0,0 +1,270 @@ +-=- +.=. +0=0 +1=1 +10=10 +12=12 +14=14 +18=18 +2=2 +24=24 +3=3 +4=4 +5=5 +6=6 +7=7 +8=8 +9=9 +\== +Age\:=Age \: +Animal=Animal +Blue=Bleu +Blue\:=bleu \: +Bold=En gras +Button\ label\:=Libellé de l'action +C=C +CE=CE +Cancel=Annuler +Comments\:=Commentaire +Config\ file\ \:=Fichier de configuration +Config\ file\:=Fichier de configuration \: +Cyan=Bleu cyan +Dec\ (-)= +Demo=Demonstration +Directory\ file\:= +Editable=Editable +Email\ Address\:=Courriel +Email\:=Courriel +Enabled=Activé +EnumEditor\ (country)\ \:=Editeur de pays +EnumEditor\ (language)\ \:=Editeur de langue +Fancy\ Button=Bouton 'Fancy' +First\ Name\:=Prénom +FirstName\:=Prénom \: +Font\ size=Taille de la police +Font\ size\:\ = +Fool\ me\ once= +Fool\ me\ twice= +Green=Vert +Green\:=Vert \: +Greet= +Help= +Inc\ (+)=Incrémenter (+) +Italic=Italique +JAXX\ Demo= +JMenu\ demo= +Label\ 1= +Label\ 2= +Last\ Name\:=Nom \: +LastName\:=Nom +Locale\ editor\:=Editeur de locale +Message\ Box= +Mineral= +Normal\ text\:= +OK= +Orange= +Password\:=Mot de passe +Purple=Pourpre +Ratio\:= +Red=Rouge +Red\:=rouge \: +Reset=Reinitialiser +Show\ Background=Voir le fond +Show\ password\ dialog=Voir l'éditeur de mot de passe +Sign\ on=Signer +Simple\ Button=Bouton simple +Size\:=Taille \: +Sources=Sources +Spacing\:=Espacement \: +Start=Démarrer +Stop=Arrêter +Supported\ Swing\ components\:=Composants Swing supportés +Text2\:=Text 2 +Text\:=Texte \: +Total\:\ = +Underline=souligné +Upper\ case\ text\:=Texte en majuscule +Use\ the\ spinner\ to=Utiliser la jauge pour +Username\:=Utilisateur \: +Vegetable=Légumes +View=Vue +Welcome\ to\ the\ JAXX\ framework\!=Bienvenu dans le framework JAXX +Working\ directory\:=Répertoire de travail +Yellow=Jaune +You\ entered\:\ = +Your\ name\:=Votre nom \: +\\u00f7= +adjust\ the\ spacing= +between\ these\ lines= +button\ A=Bouton A +button\ B=Bouton B +button\ C\ (full\ block)=Bouton C (blocage complêt) +button\ D\ (full\ block\ 2)=Bouton D (blocage complêt) +cancel=Annuler +close=Fermer +close2=Fermer 2 +close3=Fermer 3 +demo.action.reload.application=Redemarrer l'application +demo.action.reload.logAppender= +demo.action.reload.ui=Recharger l'interface graphique +edit=Editer +edit2=Editer 2 +edit3=Editer 3 +f0= +f1= +file...= +form.ratio=Form \: ratio +form.text=Form \: text +form.text2=Form \: text2 +form2.ratio=Form2 \: ratio +form2.text=Form2 \: text +form2.text2=Form2 \: text2 +getModel0().isF0()= +getModel0().isF0()\ &&\ getModel0().isF1()= +getModel0().isF0()\ ||\ getModel0().isF1()= +getModel0().isF1()= +getModel1().isF0()= +getModel1().isF0()\ &&\ getModel1().isF1()= +getModel1().isF0()\ ||\ getModel1().isF1()= +getModel1().isF1()= +getT0().isSelected()= +getT0().isSelected()\ &&\ getT1().isSelected()= +getT0().isSelected()\ ||\ getT1().isSelected()= +getT1().isSelected()= +isF0()= +isF0()\ &&\ isF1()= +isF0()\ ||\ isF1()= +isF1()= +jaxxdemo.about.message=<h3>JAXX Demo</h3><hr/>Pour plus d'informations, vous pouvez visiter le <a href\="http\://maven-site.nuiton.org/jaxx/jaxx-demo">site du projet</a>. +jaxxdemo.action.about=A propos +jaxxdemo.action.about.tip=A propos de JAXX Demo... +jaxxdemo.action.add=Ajouter +jaxxdemo.action.configuration=Configuration +jaxxdemo.action.configuration.tip=Modifier la configuration +jaxxdemo.action.exit=Quitter +jaxxdemo.action.exit.tip=Quitter JAXX Demo +jaxxdemo.action.fullscreen=Plein écran +jaxxdemo.action.fullscreen.tip=Passer en mode pleine écran +jaxxdemo.action.help=Aide +jaxxdemo.action.help.tip=Affichier l'aide +jaxxdemo.action.locale.fr=Français +jaxxdemo.action.locale.fr.tip=Changer la langue en français +jaxxdemo.action.locale.uk=Anglais +jaxxdemo.action.locale.uk.tip=Changer la langue en anglais +jaxxdemo.action.normalscreen=Ecran normal +jaxxdemo.action.normalscreen.tip=Revenir en mode normal +jaxxdemo.action.remove=Supprimer +jaxxdemo.action.show=Voir +jaxxdemo.action.site=Site internet +jaxxdemo.action.site.tip=Accéder au site de l'application sur internet +jaxxdemo.common.actors=Acteurs +jaxxdemo.common.age=Age +jaxxdemo.common.firstName=Prénom +jaxxdemo.common.id=Identifiant +jaxxdemo.common.image=Image +jaxxdemo.common.lastName=Nom +jaxxdemo.common.movie=Film +jaxxdemo.common.movies=Films +jaxxdemo.common.people=Acteur +jaxxdemo.common.title=Titre +jaxxdemo.common.year=Année +jaxxdemo.component.jaxx=Composants JAXX +jaxxdemo.component.jaxx.editor=Editeurs +jaxxdemo.component.swing=Composants Swing +jaxxdemo.component.swing.buttons=Boutons +jaxxdemo.component.swing.form=Elements de formulaire +jaxxdemo.component.swing.form.text=Texte +jaxxdemo.component.swing.layout=Layouts +jaxxdemo.component.swing.menu=Menus +jaxxdemo.component.swing.window=Fenêtres +jaxxdemo.config.category.directories=Répertoires +jaxxdemo.config.category.directories.description=Répertoires de l'application +jaxxdemo.config.category.other=Autre +jaxxdemo.config.category.other.description=Autres options +jaxxdemo.config.configFileName.description=Le nom du fichier de configuration +jaxxdemo.config.ui.demo.path=Chemin de la démo par défaut +jaxxdemo.config.ui.fontSize=La taille de la police à utiliser pour visualiser dans les sources +jaxxdemo.config.ui.fullscreen=Pour afficher l'aplication en mode pleine écran +jaxxdemo.config.ui.keyOpenConfig=Pour changer le racourcie clavier pour ouvrir l'écran de configuration +jaxxdemo.config.ui.locale=La langue utilisée par l'application +jaxxdemo.config.ui.logLevel=Level de log +jaxxdemo.config.ui.logPatternLayout=Pattern des log +jaxxdemo.datePickerEditor.dateResult=Affichage du résultat +jaxxdemo.datePickerEditor.patternLayout=Pattern de date +jaxxdemo.datePickerEditor.showPopupButton=Afficher le boutton pour ouvrir la popup +jaxxdemo.feature=Fonctionnalités +jaxxdemo.feature.databinding=Data binding +jaxxdemo.feature.nav=API JAXX pour les arbres +jaxxdemo.feature.validation=Validation +jaxxdemo.fileEditor.acceptAllFileFilterUsed=Accèpte tout les FileFilter +jaxxdemo.fileEditor.directoryEnabled=Activer la sélection des files +jaxxdemo.fileEditor.extsDescLbl=Description des extensions (séparées par des virgules, ex \: Texte (*.txt), Images (*.png)) +jaxxdemo.fileEditor.extsLbl=Extensions (separated by comma, ex \: txt, png) +jaxxdemo.fileEditor.fileEnabled=Activer la sélection des fichiers +jaxxdemo.fileEditor.titleLbl=Titre du dialog d'ouverture de fichier +jaxxdemo.fun=Fun +jaxxdemo.i18neditor.configuration=Configuration +jaxxdemo.i18neditor.popup.title=Titre de la popup +jaxxdemo.i18neditor.popupBorderText=Titre de la popup +jaxxdemo.i18neditor.selected.locale=Langue sélectionnée +jaxxdemo.i18neditor.showIcon=Afficher les icones +jaxxdemo.i18neditor.showPopupIcon=Afficher les icones dans la popup +jaxxdemo.i18neditor.showPopupText=Afficher les textes dans la popup +jaxxdemo.i18neditor.showText=Afficher le text +jaxxdemo.init.closed=JAXX Demo a été fermé à %1$s +jaxxdemo.init.context.done=Initialisation du contexte terminée en %1$s. +jaxxdemo.init.ui.done=Initialisation de l'interface graphique terminée. +jaxxdemo.listSelector.addToolTipLbl=Add button toolTip +jaxxdemo.listSelector.removeToolTipLbl=Remove button toolTip +jaxxdemo.menu.file=Fichier +jaxxdemo.menu.file.locale=Langues +jaxxdemo.menu.help=Aide +jaxxdemo.menu.showLogs=Afficher les logs +jaxxdemo.message.config.loaded=Configuration de JAXX Demo v. %1$s chargée. +jaxxdemo.message.goto.site=Accéder au site de JAXX Demo (%1$s) +jaxxdemo.navigation.actor.title=Acteur +jaxxdemo.navigation.actors.title=Acteurs +jaxxdemo.navigation.movie.title=Film +jaxxdemo.navigation.movies.title=Films +jaxxdemo.numbereditor.applyNumberPattern=Appliquer le pattern +jaxxdemo.numbereditor.autoPopup=Affichage automatique popup +jaxxdemo.numbereditor.configuration=Configuration +jaxxdemo.numbereditor.model=Résultat +jaxxdemo.numbereditor.model.float=Valeur décimale \: %1$s +jaxxdemo.numbereditor.model.int=Valeur entière \: %1$s +jaxxdemo.numbereditor.model.numberPattern=Format de l'éditeur \: %s +jaxxdemo.numbereditor.numberPattern.configuration=Pattern du nombre +jaxxdemo.numbereditor.showPopupButton=Afficher le boutton de popup +jaxxdemo.numbereditor.showReset=Afficher le boutton de reset +jaxxdemo.numbereditor.useFloat=Utiliser les décimales +jaxxdemo.numbereditor.useSign=Utiliser le signe +jaxxdemo.timeeditor.editor=Editeur de temps +jaxxdemo.timeeditor.label=Label +jaxxdemo.timeeditor.model=Résultat +jaxxdemo.timeeditor.value=Heure sélectionnée \: %1$tH\:%1$tM +jaxxdemo.title.about=A propos de JAXX Demo... +jaxxdemo.title.showLog=Logs de JAXX Demo +jaxxdemo.tree.tabtitle=Arbre +jaxxdemo.treeTable.tabtitle=Arbre tableau +jaxxdemo.warning.nimbus.landf=Le look and Feel Nimbus n'a pas été trouvé, il faut au moins la version 1.6u10 de java. +jaxxdemo.warning.no.ui=Aucun environnement graphique détecté +model0.f0= +model0.f1= +model0.file...= +model0.isF0()= +model0.isF0()\ &&\ model0.isF1()= +model0.isF0()\ ||\ model0.isF1()= +model0.isF1()= +model1.f0= +model1.f1= +model1.file...= +model1.isF0()= +model1.isF0()\ &&\ model1.isF1()= +model1.isF0()\ ||\ model1.isF1()= +model1.isF1()= +t0.isSelected()= +t0.isSelected()\ &&\ t1.isSelected()= +t0.isSelected()\ ||\ t1.isSelected()= +t1.isSelected()= +valid=valide +x=x diff --git a/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_fr_FR.properties b/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_fr_FR.properties new file mode 100644 index 0000000..dd65135 --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/i18n/jaxx-demo_fr_FR.properties @@ -0,0 +1,270 @@ +-=- +.=. +0=0 +1=1 +10=10 +12=12 +14=14 +18=18 +2=2 +24=24 +3=3 +4=4 +5=5 +6=6 +7=7 +8=8 +9=9 +\== +Age\:=Age \: +Animal=Animal +Blue=Bleu +Blue\:=bleu \: +Bold=En gras +Button\ label\:=Libellé de l'action +C=C +CE=CE +Cancel=Annuler +Comments\:=Commentaire +Config\ file\ \:=Fichier de configuration +Config\ file\:=Fichier de configuration \: +Cyan=Bleu cyan +Dec\ (-)= +Demo=Demonstration +Directory\ file\:= +Editable=Editable +Email\ Address\:=Courriel +Email\:=Courriel +Enabled=Activé +EnumEditor\ (country)\ \:=Editeur de pays +EnumEditor\ (language)\ \:=Editeur de langue +Fancy\ Button=Bouton 'Fancy' +First\ Name\:=Prénom +FirstName\:=Prénom \: +Font\ size=Taille de la police +Font\ size\:\ = +Fool\ me\ once= +Fool\ me\ twice= +Green=Vert +Green\:=Vert \: +Greet= +Help= +Inc\ (+)=Incrémenter (+) +Italic=Italique +JAXX\ Demo= +JMenu\ demo= +Label\ 1= +Label\ 2= +Last\ Name\:=Nom \: +LastName\:=Nom +Locale\ editor\:=Editeur de locale +Message\ Box= +Mineral= +Normal\ text\:= +OK= +Orange= +Password\:=Mot de passe +Purple=Pourpre +Ratio\:= +Red=Rouge +Red\:=rouge \: +Reset=Reinitialiser +Show\ Background=Voir le fond +Show\ password\ dialog=Voir l'éditeur de mot de passe +Sign\ on=Signer +Simple\ Button=Bouton simple +Size\:=Taille \: +Sources=Sources +Spacing\:=Espacement \: +Start=Démarrer +Stop=Arrêter +Supported\ Swing\ components\:=Composants Swing supportés +Text2\:=Text 2 +Text\:=Texte \: +Total\:\ = +Underline=souligné +Upper\ case\ text\:=Texte en majuscule +Use\ the\ spinner\ to=Utiliser la jauge pour +Username\:=Utilisateur \: +Vegetable=Légumes +View=Vue +Welcome\ to\ the\ JAXX\ framework\!=Bienvenu dans le framework JAXX +Working\ directory\:=Répertoire de travail +Yellow=Jaune +You\ entered\:\ = +Your\ name\:=Votre nom \: +\\u00f7= +adjust\ the\ spacing= +between\ these\ lines= +button\ A=Bouton A +button\ B=Bouton B +button\ C\ (full\ block)=Bouton C (blocage complêt) +button\ D\ (full\ block\ 2)=Bouton D (blocage complêt) +cancel=Annuler +close=Fermer +close2=Fermer 2 +close3=Fermer 3 +demo.action.reload.application=Redemarrer l'application +demo.action.reload.logAppender= +demo.action.reload.ui=Recharger l'interface graphique +edit=Editer +edit2=Editer 2 +edit3=Editer 3 +f0= +f1= +file...= +form.ratio=Form \: ratio +form.text=Form \: text +form.text2=Form \: text2 +form2.ratio=Form2 \: ratio +form2.text=Form2 \: text +form2.text2=Form2 \: text2 +getModel0().isF0()= +getModel0().isF0()\ &&\ getModel0().isF1()= +getModel0().isF0()\ ||\ getModel0().isF1()= +getModel0().isF1()= +getModel1().isF0()= +getModel1().isF0()\ &&\ getModel1().isF1()= +getModel1().isF0()\ ||\ getModel1().isF1()= +getModel1().isF1()= +getT0().isSelected()= +getT0().isSelected()\ &&\ getT1().isSelected()= +getT0().isSelected()\ ||\ getT1().isSelected()= +getT1().isSelected()= +isF0()= +isF0()\ &&\ isF1()= +isF0()\ ||\ isF1()= +isF1()= +jaxxdemo.about.message=<h3>JAXX Demo</h3><hr/>Pour plus d'informations, vous pouvez visiter le <a href\="http\://maven-site.nuiton.org/jaxx/jaxx-demo">site du projet</a>. +jaxxdemo.action.about=A propos +jaxxdemo.action.about.tip=A propos de JAXX Demo... +jaxxdemo.action.add=Ajouter +jaxxdemo.action.configuration=Configuration +jaxxdemo.action.configuration.tip=Modifier la configuration +jaxxdemo.action.exit=Quitter +jaxxdemo.action.exit.tip=Quitter JAXX Demo +jaxxdemo.action.fullscreen=Plein écran +jaxxdemo.action.fullscreen.tip=Passer en mode pleine écran +jaxxdemo.action.help=Aide +jaxxdemo.action.help.tip=Affichier l'aide +jaxxdemo.action.locale.fr=Français +jaxxdemo.action.locale.fr.tip=Changer la langue en français +jaxxdemo.action.locale.uk=Anglais +jaxxdemo.action.locale.uk.tip=Changer la langue en anglais +jaxxdemo.action.normalscreen=Ecran normal +jaxxdemo.action.normalscreen.tip=Revenir en mode normal +jaxxdemo.action.remove=Supprimer +jaxxdemo.action.show=Voir +jaxxdemo.action.site=Site internet +jaxxdemo.action.site.tip=Accéder au site de l'application sur internet +jaxxdemo.common.actors=Acteurs +jaxxdemo.common.age=Age +jaxxdemo.common.firstName=Prénom +jaxxdemo.common.id=Identifiant +jaxxdemo.common.image=Image +jaxxdemo.common.lastName=Nom +jaxxdemo.common.movie=Film +jaxxdemo.common.movies=Films +jaxxdemo.common.people=Acteur +jaxxdemo.common.title=Titre +jaxxdemo.common.year=Année +jaxxdemo.component.jaxx=Composants JAXX +jaxxdemo.component.jaxx.editor=Editeurs +jaxxdemo.component.swing=Composants Swing +jaxxdemo.component.swing.buttons=Boutons +jaxxdemo.component.swing.form=Elements de formulaire +jaxxdemo.component.swing.form.text=Texte +jaxxdemo.component.swing.layout=Layouts +jaxxdemo.component.swing.menu=Menus +jaxxdemo.component.swing.window=Fenêtres +jaxxdemo.config.category.directories=Répertoires +jaxxdemo.config.category.directories.description=Répertoires de l'application +jaxxdemo.config.category.other=Autre +jaxxdemo.config.category.other.description=Autres options +jaxxdemo.config.configFileName.description=Le nom du fichier de configuration +jaxxdemo.config.ui.demo.path=Chemin de la démo par défaut +jaxxdemo.config.ui.fontSize=La taille de la police à utiliser pour visualiser dans les sources +jaxxdemo.config.ui.fullscreen=Pour afficher l'aplication en mode pleine écran +jaxxdemo.config.ui.keyOpenConfig=Pour changer le racourcie clavier pour ouvrir l'écran de configuration +jaxxdemo.config.ui.locale=La langue utilisée par l'application +jaxxdemo.config.ui.logLevel=Level de log +jaxxdemo.config.ui.logPatternLayout=Pattern des log +jaxxdemo.datePickerEditor.dateResult=Affichage du résultat +jaxxdemo.datePickerEditor.patternLayout=Pattern de date +jaxxdemo.datePickerEditor.showPopupButton=Afficher le boutton pour ouvrir la popup +jaxxdemo.feature=Fonctionnalités +jaxxdemo.feature.databinding=Data binding +jaxxdemo.feature.nav=API JAXX pour les arbres +jaxxdemo.feature.validation=Validation +jaxxdemo.fileEditor.acceptAllFileFilterUsed=Accèpte tout les FileFilter +jaxxdemo.fileEditor.directoryEnabled=Activer la sélection des files +jaxxdemo.fileEditor.extsDescLbl=Description des extensions (séparées par des virgules, ex \: Texte (*.txt), Images (*.png)) +jaxxdemo.fileEditor.extsLbl=Extensions (separated by comma, ex \: txt, png) +jaxxdemo.fileEditor.fileEnabled=Activer la sélection des fichiers +jaxxdemo.fileEditor.titleLbl=Titre de la fenêtre de sélection de fichier +jaxxdemo.fun=Fun +jaxxdemo.i18neditor.configuration=Configuration +jaxxdemo.i18neditor.popup.title=Titre de la popup +jaxxdemo.i18neditor.popupBorderText=Titre de la popup +jaxxdemo.i18neditor.selected.locale=Langue sélectionnée +jaxxdemo.i18neditor.showIcon=Afficher les icones +jaxxdemo.i18neditor.showPopupIcon=Afficher les icones dans la popup +jaxxdemo.i18neditor.showPopupText=Afficher les textes dans la popup +jaxxdemo.i18neditor.showText=Afficher le text +jaxxdemo.init.closed=JAXX Demo a été fermé à %1$s +jaxxdemo.init.context.done=Initialisation du contexte terminée en %1$s. +jaxxdemo.init.ui.done=Initialisation de l'interface graphique terminée. +jaxxdemo.listSelector.addToolTipLbl=Tooltip du boutton ajouter +jaxxdemo.listSelector.removeToolTipLbl=Tooltip du boutton enlever +jaxxdemo.menu.file=Fichier +jaxxdemo.menu.file.locale=Langues +jaxxdemo.menu.help=Aide +jaxxdemo.menu.showLogs=Afficher les logs +jaxxdemo.message.config.loaded=Configuration de JAXX Demo v. %1$s chargée. +jaxxdemo.message.goto.site=Accéder au site de JAXX Demo (%1$s) +jaxxdemo.navigation.actor.title=Acteur +jaxxdemo.navigation.actors.title=Acteurs +jaxxdemo.navigation.movie.title=Film +jaxxdemo.navigation.movies.title=Films +jaxxdemo.numbereditor.applyNumberPattern=Appliquer le pattern +jaxxdemo.numbereditor.autoPopup=Affichage automatique popup +jaxxdemo.numbereditor.configuration=Configuration +jaxxdemo.numbereditor.model=Résultat +jaxxdemo.numbereditor.model.float=Valeur décimale \: %1$s +jaxxdemo.numbereditor.model.int=Valeur entière \: %1$s +jaxxdemo.numbereditor.model.numberPattern=Format de l'éditeur \: %s +jaxxdemo.numbereditor.numberPattern.configuration=Pattern du nombre +jaxxdemo.numbereditor.showPopupButton=Afficher le boutton de popup +jaxxdemo.numbereditor.showReset=Afficher le boutton de reset +jaxxdemo.numbereditor.useFloat=Utiliser les décimales +jaxxdemo.numbereditor.useSign=Utiliser le signe +jaxxdemo.timeeditor.editor=Editeur de temps +jaxxdemo.timeeditor.label=Label +jaxxdemo.timeeditor.model=Résultat +jaxxdemo.timeeditor.value=Heure sélectionnée \: %1$tH\:%1$tM +jaxxdemo.title.about=A propos de JAXX Demo... +jaxxdemo.title.showLog=Logs de JAXX Demo +jaxxdemo.tree.tabtitle=Arbre +jaxxdemo.treeTable.tabtitle=Arbre tableau +jaxxdemo.warning.nimbus.landf=Le look and Feel Nimbus n'a pas été trouvé, il faut au moins la version 1.6u10 de java. +jaxxdemo.warning.no.ui=Aucun environnement graphique détecté +model0.f0= +model0.f1= +model0.file...= +model0.isF0()= +model0.isF0()\ &&\ model0.isF1()= +model0.isF0()\ ||\ model0.isF1()= +model0.isF1()= +model1.f0= +model1.f1= +model1.file...= +model1.isF0()= +model1.isF0()\ &&\ model1.isF1()= +model1.isF0()\ ||\ model1.isF1()= +model1.isF1()= +t0.isSelected()= +t0.isSelected()\ &&\ t1.isSelected()= +t0.isSelected()\ ||\ t1.isSelected()= +t1.isSelected()= +valid=valide +x=x diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-about.png b/trunk/jaxx-demo/src/main/resources/icons/action-about.png new file mode 100644 index 0000000..0d826bb Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-about.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-accept.png b/trunk/jaxx-demo/src/main/resources/icons/action-accept.png new file mode 100644 index 0000000..89c8129 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-accept.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-block.png b/trunk/jaxx-demo/src/main/resources/icons/action-block.png new file mode 100644 index 0000000..aba044b Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-block.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-close.png b/trunk/jaxx-demo/src/main/resources/icons/action-close.png new file mode 100644 index 0000000..2541d2b Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-close.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-config.png b/trunk/jaxx-demo/src/main/resources/icons/action-config.png new file mode 100644 index 0000000..9460dfc Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-config.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-exit.png b/trunk/jaxx-demo/src/main/resources/icons/action-exit.png new file mode 100644 index 0000000..a77152b Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-exit.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-fullscreen.png b/trunk/jaxx-demo/src/main/resources/icons/action-fullscreen.png new file mode 100644 index 0000000..6845e04 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-fullscreen.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-help.png b/trunk/jaxx-demo/src/main/resources/icons/action-help.png new file mode 100644 index 0000000..4ed65a9 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-help.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-i18n-fr.png b/trunk/jaxx-demo/src/main/resources/icons/action-i18n-fr.png new file mode 100644 index 0000000..8332c4e Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-i18n-fr.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-i18n-uk.png b/trunk/jaxx-demo/src/main/resources/icons/action-i18n-uk.png new file mode 100644 index 0000000..ff701e1 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-i18n-uk.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-leave-fullscreen.png b/trunk/jaxx-demo/src/main/resources/icons/action-leave-fullscreen.png new file mode 100644 index 0000000..fc6638e Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-leave-fullscreen.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-reload-application.png b/trunk/jaxx-demo/src/main/resources/icons/action-reload-application.png new file mode 100644 index 0000000..e002141 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-reload-application.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-reload-log.png b/trunk/jaxx-demo/src/main/resources/icons/action-reload-log.png new file mode 100644 index 0000000..cf347c7 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-reload-log.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-reload-ui.png b/trunk/jaxx-demo/src/main/resources/icons/action-reload-ui.png new file mode 100644 index 0000000..ab92010 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-reload-ui.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-show-help.png b/trunk/jaxx-demo/src/main/resources/icons/action-show-help.png new file mode 100644 index 0000000..f6bc721 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-show-help.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-site.png b/trunk/jaxx-demo/src/main/resources/icons/action-site.png new file mode 100644 index 0000000..ac5957a Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-site.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/action-translate.png b/trunk/jaxx-demo/src/main/resources/icons/action-translate.png new file mode 100644 index 0000000..63ce64d Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/action-translate.png differ diff --git a/trunk/jaxx-demo/src/main/resources/icons/jaxx.png b/trunk/jaxx-demo/src/main/resources/icons/jaxx.png new file mode 100644 index 0000000..c3d68c9 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/icons/jaxx.png differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-error-validation.xml b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-error-validation.xml new file mode 100644 index 0000000..371fd8a --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-error-validation.xml @@ -0,0 +1,73 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + <field name="firstName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a firstName.</message> + </field-validator> + </field> + <field name="lastName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a lastName.</message> + </field-validator> + </field> + + <field name="email"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a value for email.</message> + </field-validator> + <field-validator type="email" short-circuit="true"> + <message>Not a valid e-mail.</message> + </field-validator> + </field> + + <field name="config"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for config.</message> + </field-validator> + <field-validator type="existingFile" short-circuit="true"> + <message>The configuration file ${config} does not exist.</message> + </field-validator> + </field> + + <field name="dir"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for dir.</message> + </field-validator> + <field-validator type="existingDirectory" short-circuit="true"> + <message>The directory ${dir} does not exist.</message> + </field-validator> + </field> + + <field name="age"> + <field-validator type="int"> + <param name="min">18</param> + <message>Your are too young (min ${min} )</message> + </field-validator> + </field> +</validators> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-info-validation.xml b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-info-validation.xml new file mode 100644 index 0000000..57c9c94 --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-info-validation.xml @@ -0,0 +1,73 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + <!--field name="firstName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a firstName.</message> + </field-validator> + </field> + <field name="lastName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a lastName.</message> + </field-validator> + </field> + + <field name="email"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a value for email.</message> + </field-validator> + <field-validator type="email" short-circuit="true"> + <message>Not a valid e-mail.</message> + </field-validator> + </field> + + <field name="config"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for config.</message> + </field-validator> + <field-validator type="existingFile" short-circuit="true"> + <message>The configuration file ${config} does not exist.</message> + </field-validator> + </field> + + <field name="dir"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for dir.</message> + </field-validator> + <field-validator type="existingDirectory" short-circuit="true"> + <message>The directory ${dir} does not exist.</message> + </field-validator> + </field--> + + <field name="age"> + <field-validator type="int"> + <param name="min">25</param> + <message>You are still young ( old ${min} ) </message> + </field-validator> + </field> +</validators> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-warning-validation.xml b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-warning-validation.xml new file mode 100644 index 0000000..888335a --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Identity-warning-validation.xml @@ -0,0 +1,73 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + <!--field name="firstName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a firstName.</message> + </field-validator> + </field> + <field name="lastName"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a lastName.</message> + </field-validator> + </field> + + <field name="email"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a value for email.</message> + </field-validator> + <field-validator type="email" short-circuit="true"> + <message>Not a valid e-mail.</message> + </field-validator> + </field> + + <field name="config"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for config.</message> + </field-validator> + <field-validator type="existingFile" short-circuit="true"> + <message>The configuration file ${config} does not exist.</message> + </field-validator> + </field> + + <field name="dir"> + <field-validator type="requiredFile" short-circuit="true"> + <message>You must enter a value for dir.</message> + </field-validator> + <field-validator type="existingDirectory" short-circuit="true"> + <message>The directory ${dir} does not exist.</message> + </field-validator> + </field--> + + <field name="age"> + <field-validator type="int"> + <param name="max">88</param> + <message>Info : Your are older than ${max} !</message> + </field-validator> + </field> +</validators> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-error-validation.xml b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-error-validation.xml new file mode 100644 index 0000000..199dd78 --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-error-validation.xml @@ -0,0 +1,59 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + <!-- Field Validators for email field --> + <field name="text"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a value for text.</message> + </field-validator> + </field> + + <field name="text2"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a value for text2.</message> + </field-validator> + </field> + + <field name="ratio"> + <field-validator type="int"> + <param name="min">20</param> + <param name="max">50</param> + <message>Ratio needs to be between ${min} and ${max}</message> + </field-validator> + </field> + + <!-- Plain Validator 1 --> + <validator type="expression"> + <param name="expression">text.startsWith("poussin")</param> + <message>Email not starts with poussin</message> + </validator> + <validator type="expression"> + <param name="expression">text2.startsWith("chemit")</param> + <message>Email not starts with chemit</message> + </validator> +</validators> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-info-validation.xml b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-info-validation.xml new file mode 100644 index 0000000..6fbb762 --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-info-validation.xml @@ -0,0 +1,37 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + <!-- Field Validators for email field --> + <field name="text"> + <field-validator type="fieldexpression"> + <param name="expression"><![CDATA[ text != null && text.length() > 10]]></param> + <message>Text should have more than 10 caracters</message> + </field-validator> + </field> + +</validators> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-warning-validation.xml b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-warning-validation.xml new file mode 100644 index 0000000..1046dd0 --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/jaxx/demo/entities/Model-warning-validation.xml @@ -0,0 +1,42 @@ +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator 1.0.3//EN" + "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> +<validators> + <!-- Field Validators for email field --> + <field name="text"> + <field-validator type="email" short-circuit="true"> + <message>Not a valid e-mail for text.</message> + </field-validator> + </field> + + <field name="text2"> + <field-validator type="requiredstring" short-circuit="true"> + <message>You must enter a value for text2.</message> + </field-validator> + </field> + +</validators> \ No newline at end of file diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Amethyst.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Amethyst.jpg new file mode 100644 index 0000000..72aabd2 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Amethyst.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Lynx.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Lynx.jpg new file mode 100644 index 0000000..779ef43 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Lynx.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Tomato.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Tomato.jpg new file mode 100644 index 0000000..f6223b2 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/Tomato.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/ana.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/ana.jpg new file mode 100644 index 0000000..dafe5ba Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/ana.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/hector.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/hector.jpg new file mode 100644 index 0000000..9ee1f27 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/hector.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/jack.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/jack.jpg new file mode 100644 index 0000000..61bed7b Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/jack.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/joe.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/joe.jpg new file mode 100644 index 0000000..9319a64 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/joe.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/nacho.jpg b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/nacho.jpg new file mode 100644 index 0000000..ea76448 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/nacho.jpg differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/nacho2.png b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/nacho2.png new file mode 100644 index 0000000..618e177 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/nacho2.png differ diff --git a/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/pencil_black.gif b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/pencil_black.gif new file mode 100644 index 0000000..1dae579 Binary files /dev/null and b/trunk/jaxx-demo/src/main/resources/jaxx/demo/images/pencil_black.gif differ diff --git a/trunk/jaxx-demo/src/main/resources/log4j.properties b/trunk/jaxx-demo/src/main/resources/log4j.properties new file mode 100644 index 0000000..56977aa --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/log4j.properties @@ -0,0 +1,40 @@ +### +# #%L +# JAXX :: Demo +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +# Global logging configuration +log4j.rootLogger=ERROR, stdout, jaxxDemoAppender +# 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=INFO +#log4j.logger.jaxx.demo=INFO +log4j.logger.jaxx.demo.tree=DEBUG +log4j.logger.jaxx.runtime.swing.tree=DEBUG +#log4j.logger.jaxx.demo.component.jaxx.tree=DEBUG +#log4j.logger.jaxx.demo.config.DemoConfig=DEBUG +#log4j.logger.jaxx.runtime.swing.editor.config=INFO +#log4j.logger.jaxx.runtime.swing.editor.config.model.ConfigUIModelBuilder=DEBUG +log4j.logger.org.nuiton=WARN diff --git a/trunk/jaxx-demo/src/main/resources/validators.xml b/trunk/jaxx-demo/src/main/resources/validators.xml new file mode 100644 index 0000000..eaecbf7 --- /dev/null +++ b/trunk/jaxx-demo/src/main/resources/validators.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + ObServe :: Services + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 IRD, Codelutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator Config 1.0//EN" + "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd"> +<validators> + <!-- les validateurs fournis par XWork --> + <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/> + <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/> + <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/> + <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/> + <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/> + <validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/> + <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/> + <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/> + <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/> + <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/> + <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/> + <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/> + + <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/> + <validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/> + + <!-- les validateurs fournis par Nuiton-validator --> + <validator name="collectionFieldExpression" class="org.nuiton.validator.xwork2.field.CollectionFieldExpressionValidator"/> + <validator name="collectionUniqueKey" class="org.nuiton.validator.xwork2.field.CollectionUniqueKeyValidator"/> + <validator name="requiredFile" class="org.nuiton.validator.xwork2.field.RequiredFileFieldValidator"/> + <validator name="existingFile" class="org.nuiton.validator.xwork2.field.ExistingFileFieldValidator"/> + <validator name="notExistingFile" class="org.nuiton.validator.xwork2.field.NotExistingFileFieldValidator"/> + <validator name="existingDirectory" class="org.nuiton.validator.xwork2.field.ExistingDirectoryFieldValidator"/> + <validator name="notExistingDirectory" class="org.nuiton.validator.xwork2.field.NotExistingDirectoryFieldValidator"/> + <validator name="fieldexpressionwithparams" class="org.nuiton.validator.xwork2.field.FieldExpressionWithParamsValidator"/> + +</validators> diff --git a/trunk/jaxx-demo/src/site/rst/images/Components-screenshot.gif b/trunk/jaxx-demo/src/site/rst/images/Components-screenshot.gif new file mode 100644 index 0000000..68bec67 Binary files /dev/null and b/trunk/jaxx-demo/src/site/rst/images/Components-screenshot.gif differ diff --git a/trunk/jaxx-demo/src/site/rst/index.rst b/trunk/jaxx-demo/src/site/rst/index.rst new file mode 100644 index 0000000..3441827 --- /dev/null +++ b/trunk/jaxx-demo/src/site/rst/index.rst @@ -0,0 +1,71 @@ +.. - +.. * #%L +.. * JAXX :: Demo +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +=================== +Examples/Components +=================== + + +The Components demo displays many different Swing components being used in a variety of ways; it is JAXX's equivalent +of the SwingSet demo. Various pages use advanced features such as data binding, scripting, event handling, and +CSS stylesheets. + +Examples/Calculator +=================== + +This is an implementation of Challenge #2 from the `XUL Grand Coding Challenge 2004`_ . Because this example program +has been implemented in so many different languages, you can easily compare JAXX's +syntax against the competition and decide for yourself which you prefer. + +Screen shot +----------- + +.. image:: ./images/Components-screenshot.gif + +Set it in action +---------------- + +|webstart| + +To run this example in `Java Web Start`_, click the `following link`_. + +For more details about the `Jaxx Demo webstart`_. + +Source code +----------- + +Unlike the other examples, the source code for Components is too big to display here. You can view it yourself by +downloading JAXX, and you can also view the source code for the individual demos by clicking the "Source" tabs. + + +.. _Java Web Start: http://java.sun.com/products/javawebstart/ + +.. |webstart| image:: http://maven-site.nuiton.org/public/images/logos//webstart.gif + +.. _following link: ./jnlp/launch.jnlp + +.. _Jaxx Demo webstart: jnlp-report.html + +.. _XUL Grand Coding Challenge 2004: http://xul.sourceforge.net/challenge.html diff --git a/trunk/jaxx-demo/src/site/site_fr.xml b/trunk/jaxx-demo/src/site/site_fr.xml new file mode 100644 index 0000000..aa7faba --- /dev/null +++ b/trunk/jaxx-demo/src/site/site_fr.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Demo + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <src>http://maven-site.chorem.org/public/images/logos/jaxx-logo.png</src> + <href>index.html</href> + </bannerLeft> + + <poweredBy> + <logo href="http://maven-site.nuiton.org/jaxx/" name="Jaxx" + img="http://maven-site.chorem.org/public/images/logos/jaxx-logo.png"/> + </poweredBy> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="index.html"/> + </breadcrumbs> + + <menu ref="parent"/> + + <menu name="Utilisateur"> + <item name="Accueil" href="index.html"/> + <item name="Lancer la démo" href="jnlp/launch.jnlp"/> + </menu> + + <menu ref="reports"/> + + <menu ref="modules"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> diff --git a/trunk/jaxx-demo/src/test/java/jaxx/demo/BeanValidatorDetectorTest.java b/trunk/jaxx-demo/src/test/java/jaxx/demo/BeanValidatorDetectorTest.java new file mode 100644 index 0000000..47dcf3b --- /dev/null +++ b/trunk/jaxx-demo/src/test/java/jaxx/demo/BeanValidatorDetectorTest.java @@ -0,0 +1,82 @@ +/* + * #%L + * JAXX :: Demo + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.demo; + +import jaxx.demo.entities.Identity; +import jaxx.demo.entities.Model; +import org.junit.Assert; +import org.junit.Test; +import org.nuiton.validator.AbstractValidatorDetectorTest; +import org.nuiton.validator.NuitonValidator; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.xwork2.XWork2NuitonValidatorProvider; + +import java.io.File; +import java.util.Iterator; +import java.util.SortedSet; + +/** @author tchemit <chemit@codelutin.com> */ +public class BeanValidatorDetectorTest extends AbstractValidatorDetectorTest { + + public BeanValidatorDetectorTest() { + // prefer do tests on target copy instead of original files + super(XWork2NuitonValidatorProvider.PROVIDER_NAME); + } + + @Test + public void detectAllValidators() { + SortedSet<NuitonValidator<?>> result; + NuitonValidator<?> validator; + Iterator<NuitonValidator<?>> iterator; + + // test with all context and all scopes : 2 validators (Identity+ Model) + + result = detectValidators(Identity.class, Model.class); + + Assert.assertNotNull(result); + Assert.assertEquals(2, result.size()); + + + iterator = result.iterator(); + validator = iterator.next(); + + assertValidatorModel(validator, null, Identity.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); +// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Person.PROPERTY_NAME, Person.PROPERTY_FIRSTNAME); +// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.WARNING, Person.PROPERTY_PET); + + validator = iterator.next(); + assertValidatorModel(validator, null, Model.class, NuitonValidatorScope.values()); + assertValidatorEffectiveScopes(validator, NuitonValidatorScope.ERROR, NuitonValidatorScope.WARNING, NuitonValidatorScope.INFO); +// ValidatorTestHelper.assertValidatorEffectiveFields(validator, NuitonValidatorScope.ERROR, Pet.PROPERTY_NAME); + + } + + @Override + protected File getRootDirectory(File basedir) { + return new File(basedir, "target" + File.separator + "classes"); + } +} diff --git a/trunk/jaxx-maven-plugin/LICENSE.txt b/trunk/jaxx-maven-plugin/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/jaxx-maven-plugin/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/jaxx-maven-plugin/README.txt b/trunk/jaxx-maven-plugin/README.txt new file mode 100644 index 0000000..d2e50d3 --- /dev/null +++ b/trunk/jaxx-maven-plugin/README.txt @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install diff --git a/trunk/jaxx-maven-plugin/changelog.txt b/trunk/jaxx-maven-plugin/changelog.txt new file mode 100644 index 0000000..a177b80 --- /dev/null +++ b/trunk/jaxx-maven-plugin/changelog.txt @@ -0,0 +1,37 @@ +1.3 chemit 20090409 + * 20090327 [chemit] - add javax help mecanism + * 20090301 [chemit] - add a profile mode (-Djaxx.profile) + +1.2 letelier 2009022? + +1.1 chemit 20090220 + * 20090203 [chemit] - mojo's property src is now by default in src/main/java + * 20090202 [chemit] - introduce a property validatorClass to specify the validator implementation + * 20090124 [chemit] - introduce a flag useUIManagerForIcon to retreave icons from UIManager + - clean mojo getter and setter (not used here) + * 20090123 [chemit] - add tests for icon improvment + * 20090122 [chemit] - refactor poms (sibling dependencies, pluginsManagment,...) + - rename i18n bundles according artifactId + * 20090113 [chemit] - fix bug : when using addProjectClassPath property, sometimes does not retreave + dependancies, force it to work whatever is the phase :) + +1.0 chemit 20090111 + +0.8 chemit 200812?? + * 20081219 [chemit] - add addProjectClassPath property to add project compile class-path in plugin class-path + * 20081214 [chemit] - add addSourcesToClassPath property to add sources directories in class-path + +0.7 chemit 20081210 + * 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 + +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... diff --git a/trunk/jaxx-maven-plugin/pom.xml b/trunk/jaxx-maven-plugin/pom.xml new file mode 100644 index 0000000..bc9a516 --- /dev/null +++ b/trunk/jaxx-maven-plugin/pom.xml @@ -0,0 +1,260 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jaxx</artifactId> + <version>2.5.2</version> + </parent> + + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + + <dependencies> + + <!-- sibling dependencies --> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-validator</artifactId> + <version>${project.version}</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-compiler</artifactId> + <version>${project.version}</version> + </dependency> + + <!-- maven plugin project dependencies --> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + </dependency> + + <!-- other dependencies --> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>helper-maven-plugin</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <dependency> + <groupId>javax.help</groupId> + <artifactId>javahelp</artifactId> + </dependency> + + <!-- pour acceder aux BeansInfos swing via Introspector --> + <dependency> + <groupId>com.sun</groupId> + <artifactId>dt</artifactId> + <scope>system</scope> + <systemPath>/${java.home}/../lib/dt.jar</systemPath> + </dependency> + + <!-- tests dependencies --> + + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-verifier</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.maven.plugin-testing</groupId> + <artifactId>maven-plugin-testing-harness</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>helper-maven-plugin</artifactId> + <classifier>tests</classifier> + </dependency> + + <!-- FIXME si on ne le rajoute pas, on se retrouve avec la version 1.1 qui ne convient pas --> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>runtime</scope> + </dependency> + + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JAXX :: Maven plugin</name> + <description> + Maven 2 plugin to generate java sources from JAXX files. + </description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>maven-plugin</packaging> + + <build> + <plugins> + + <plugin> + <artifactId>maven-plugin-plugin</artifactId> + <configuration> + <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> + </configuration> + <executions> + <execution> + <goals> + <goal>helpmojo</goal> + <goal>descriptor</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + + </build> + + <profiles> + + <profile> + <id>reporting</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <reporting> + <plugins> + + <plugin> + <artifactId>maven-plugin-plugin</artifactId> + <version>${pluginPluginVersion}</version> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>${javadocPluginVersion}</version> + <configuration> + <quiet>true</quiet> + <tagletArtifacts> + <tagletArtifact> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-tools-javadoc</artifactId> + <version>${pluginPluginVersion}</version> + </tagletArtifact> + <tagletArtifact> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-component-javadoc</artifactId> + <version>1.5.5</version> + </tagletArtifact> + </tagletArtifacts> + </configuration> + <reportSets> + <reportSet> + <reports> + <report>javadoc</report> + <report>test-javadoc</report> + </reports> + </reportSet> + </reportSets> + </plugin> + + </plugins> + </reporting> + + </profile> + + </profiles> + +</project> diff --git a/trunk/jaxx-maven-plugin/src/license/THIRD-PARTY.properties b/trunk/jaxx-maven-plugin/src/license/THIRD-PARTY.properties new file mode 100644 index 0000000..faee3a3 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/license/THIRD-PARTY.properties @@ -0,0 +1,29 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - BSD License +# - BSD style +# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 +# - Common Public License Version 1.0 +# - GNU General Public License - Version 2 with the class path exception +# - Indiana University Extreme! Lab Software License, vesion 1.1.1 +# - Lesser General Public License (LGPL) +# - Lesser General Public License (LGPL) v 3.0 +# - Lesser General Public License (LPGL) +# - Lesser General Public License (LPGL) v 2.1 +# - MIT License +# - MPL 1.1 +# - Public Domain +# - The Apache Software License, Version 2.0 +# - http://classworlds.codehaus.org/license.html +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Fri Jun 29 10:40:24 CEST 2012 +classworlds--classworlds--1.1-alpha-2=http\://classworlds.codehaus.org/license.html +commons-cli--commons-cli--1.0=The Apache Software License, Version 2.0 +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 +org.codehaus.plexus--plexus-container-default--1.0-alpha-9-stable-1=The Apache Software License, Version 2.0 +org.codehaus.plexus--plexus-interactivity-api--1.0-alpha-4=The Apache Software License, Version 2.0 +oro--oro--2.0.8=The Apache Software License, Version 2.0 diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/AbstractGenerateHelpMojo.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/AbstractGenerateHelpMojo.java new file mode 100644 index 0000000..799c03d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/AbstractGenerateHelpMojo.java @@ -0,0 +1,278 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Parameter; +import org.nuiton.i18n.I18nUtil; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +/** + * Abstract Mojo to generate help stuff. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public abstract class AbstractGenerateHelpMojo extends AbstractJaxxMojo { + + /** + * The locales to generate for help, separeted by comma. + * <p/> + * The first locale given is the default locale. + * + * @since 2.0.0 + */ + @Parameter(property = "jaxx.locales", required = true) + protected String locales; + + /** + * Where to generate helpIds files. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.outputHelpIds", defaultValue = "target/generated-sources/jaxx", required = true) + private File outputHelpIds; + + /** + * The store of helpIds generated by the goal {@link GenerateMojo} and then + * used by the goal {@link GenerateHelpMojo}. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.helpIdsFilename", defaultValue = "helpIds.properties", required = true) + private String helpIdsFilename; + + /** + * The store of cumulate helpIds generated by the goal {@link GenerateMojo} + * and then used by the goal {@link GenerateHelpMojo}. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.mergeHelpIdsFilename", defaultValue = "helpIds-all.properties", required = true) + private String mergeHelpIdsFilename; + + /** + * Flag to generate the search index. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.generateSearch", defaultValue = "true", required = true) + protected boolean generateSearch; + + /** Default locale (the first locale in {@link #localesToTreate}. */ + private Locale defaultLocale; + + /** Locales to treate */ + private Locale[] localesToTreate; + + /** + * Do the action for the given locale. + * + * @param locale the locale to treate + * @param isDefaultLocale {@code true} if given locale is de the default + * locale + * @param source where are stored help files for the given locale + * @param localePath the locale path to use (is {@code default} if + * given locale is default). + * @throws Exception if any pb + */ + protected abstract void doActionForLocale( + Locale locale, + boolean isDefaultLocale, + File source, + String localePath) throws Exception; + + /** Call back after doing all stuff for all locales declared */ + protected abstract void postDoAction(); + + @Override + protected void init() throws Exception { + + if (StringUtils.isEmpty(locales)) { + throw new MojoFailureException( + "You must set the 'locales' property properly (was " + + locales + ")."); + } + + // check there is a outHelp + if (getTargetDirectory() == null) { + throw new MojoFailureException( + "You must set the 'outputHelpXXX' property."); + } + + List<Locale> tmp = new ArrayList<Locale>(); + for (String loc : locales.split(",")) { + Locale l = I18nUtil.newLocale(loc); + tmp.add(l); + } + + if (tmp.isEmpty()) { + throw new MojoFailureException( + "No locale to react, you must set the 'locales' property."); + } + + localesToTreate = tmp.toArray(new Locale[tmp.size()]); + defaultLocale = localesToTreate[0]; + + createDirectoryIfNecessary(getTargetDirectory()); + } + + @Override + protected boolean checkSkip() { + if (!generateHelp) { + getLog().info("generateHelp flag is off, will skip goal."); + return false; + } + return true; + } + + @Override + protected void doAction() throws Exception { + + for (Locale locale : localesToTreate) { + + boolean isDefaultLocale = defaultLocale.equals(locale); + + String language = locale.getLanguage(); + + String localePath = isDefaultLocale ? "default" : language; + + File source = new File(getTargetDirectory(), localePath); + + createDirectoryIfNecessary(source); + + doActionForLocale(locale, isDefaultLocale, source, localePath); + + } + + postDoAction(); + } + + public File getOutputHelpIds() { + return outputHelpIds; + } + + public void setOutputHelpIds(File outputHelpIds) { + this.outputHelpIds = outputHelpIds; + } + + public File getHelpIdsStoreFile() { + return outputHelpIds == null ? null : + new File(outputHelpIds, helpIdsFilename); + } + + public File getMergeHelpIdsStoreFile() { + return outputHelpIds == null ? null : + new File(outputHelpIds, mergeHelpIdsFilename); + } + + public String getHelpIdsFilename() { + return helpIdsFilename; + } + + public void setHelpIdsFilename(String helpIdsFilename) { + this.helpIdsFilename = helpIdsFilename; + } + + public String getMergeHelpIdsFilename() { + return mergeHelpIdsFilename; + } + + public void setMergeHelpIdsFilename(String mergeHelpIdsFilename) { + this.mergeHelpIdsFilename = mergeHelpIdsFilename; + } + + protected void cleanHelpIdsStore() throws IOException { + File idsStore = getHelpIdsStoreFile(); + if (idsStore.exists()) { + if (getLog().isDebugEnabled()) { + getLog().debug("delete id store " + idsStore); + } + boolean b = idsStore.delete(); + if (!b) { + throw new IOException("could not delete file " + idsStore); + } + } + } + + protected Set<String> loadHelpIds(File file) throws IOException { + + BufferedReader reader = null; + Set<String> result = new HashSet<String>(); + reader = new BufferedReader(new InputStreamReader( + new FileInputStream(file), getEncoding())); + try { + String id; + while ((id = reader.readLine()) != null) { + result.add(id.trim()); + } + if (isVerbose()) { + getLog().info("load " + result.size() + + " help ids from file " + file); + } + return result; + } finally { + reader.close(); + } + } + + protected void storeHelpIds(File file, Set<String> ids) throws IOException { + + createDirectoryIfNecessary(file.getParentFile()); + + StringBuilder buffer = new StringBuilder(); + + for (String helpId : ids) { + buffer.append(removeQuote(helpId)).append('\n'); + } + writeFile(file, buffer.toString(), getEncoding()); + if (isVerbose()) { + getLog().info("stored " + ids.size() + " help ids in " + file); + } + } + + protected String removeQuote(String txt) { + if (txt.startsWith("\"")) { + txt = txt.substring(1); + } + if (txt.endsWith("\"")) { + txt = txt.substring(0, txt.length() - 1); + } + return txt; + } + +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/AbstractJaxxMojo.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/AbstractJaxxMojo.java new file mode 100644 index 0000000..4276b9b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/AbstractJaxxMojo.java @@ -0,0 +1,187 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin; + +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.nuiton.io.MirroredFileUpdater; +import org.nuiton.plugin.AbstractPlugin; +import org.nuiton.plugin.PluginWithEncoding; +import org.nuiton.util.FileUtil; + +import java.io.File; + +/** + * Abstract Jaxx Mojo. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public abstract class AbstractJaxxMojo extends AbstractPlugin implements PluginWithEncoding { + + public abstract File getTargetDirectory(); + + public abstract void setTargetDirectory(File targetDirectory); + + /** Current maven project. */ + @Component + private MavenProject project; + + /** + * Encoding used for file generation. + * <p/> + * <b>Note:</b> If nothing is filled here, we will use the system + * property {@code file.encoding}. + * + * @since 2.0.0 + */ + @Parameter(property = "jaxx.encoding", defaultValue = "${project.build.sourceEncoding}") + private String encoding; + + /** + * Verbose flag. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.verbose", defaultValue = "false") + private boolean verbose; + + /** + * To force generation of java source for any jaxx files with no timestamp checking. + * <p/> + * By default, never force generation. + */ + @Parameter(property = "jaxx.force", defaultValue = "false") + private boolean force; + + /** + * Flag to activate help id detection while parsing jaxx files. + * <p/> + * By default, not active. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.generateHelp", defaultValue = "false") + protected boolean generateHelp; + + @Override + protected boolean checkPackaging() { + // not accept pom modules + return hasClassPath(); + } + + @Override + public MavenProject getProject() { + return project; + } + + @Override + public boolean isVerbose() { + return verbose; + } + + @Override + public void setProject(MavenProject project) { + this.project = project; + } + + @Override + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + @Override + public String getEncoding() { + return encoding; + } + + @Override + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public boolean isForce() { + return force; + } + + public void setForce(boolean force) { + this.force = force; + } + + class GetLastModifiedFileAction implements FileUtil.FileAction { + + protected File lastFile; + + public GetLastModifiedFileAction(File lastFile) { + this.lastFile = lastFile; + } + + @Override + public boolean doAction(File f) { + + if (f.lastModified() > lastFile.lastModified()) { + lastFile = f; + } + return true; + } + + public File getLastFile() { + return lastFile; + } + } + + protected Long getLastModified(File dir) { + if (!dir.exists()) { + return null; + } + GetLastModifiedFileAction fileAction = + new GetLastModifiedFileAction(dir); + FileUtil.walkAfter(dir, fileAction); + return fileAction.getLastFile().lastModified(); + } + + /** + * To test if a jaxx source (or his css ) file is newser than his generated + * java source file. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ + public static class JaxxFileUpdater extends MirroredFileUpdater { + + protected JaxxFileUpdater(File sourceDirectory, File destinationDirectory) { + super(".jaxx|*.css", ".java", sourceDirectory, destinationDirectory); + } + + @Override + public File getMirrorFile(File f) { + String file = f.getAbsolutePath().substring(prefixSourceDirecotory); + String extension = FileUtil.extension(f); + String mirrorRelativePath = file.substring(0, file.length() - extension.length()) + "java"; + return new File(destinationDirectory + File.separator + mirrorRelativePath); + } + } +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpFilesMojo.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpFilesMojo.java new file mode 100644 index 0000000..b3db19e --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpFilesMojo.java @@ -0,0 +1,521 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.apache.commons.io.FileUtils; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.nuiton.plugin.VelocityTemplateGenerator; +import org.nuiton.util.SortedProperties; + +import java.io.File; +import java.net.URL; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; + +/** + * Mojo to generate javax help files for your project. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +@Mojo(name = "generate-help-files", + defaultPhase = LifecyclePhase.PROCESS_SOURCES, + requiresProject = true, + requiresDependencyResolution = ResolutionScope.COMPILE) +@Execute(goal = "generate-help-ids") +public class GenerateHelpFilesMojo extends AbstractGenerateHelpMojo { + + protected static final String AUTOREMOVE_LINE = + "REMOVE THS LINE TO DISABLE AUTO-REGENERATE THE FILE"; + + /** + * The directory where to create or update help files. + * + * @since 2.0.0 + */ + @Parameter(property = "jaxx.outputHelp", defaultValue = "${project.basedir}/src/main/help", required = true) + protected File outputHelp; + + /** + * The name of the helpset to generate. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.helpsetName", defaultValue = "${project.artifactId}", required = true) + protected String helpsetName; + + /** + * The template used to generate helpset file. + * <p/> + * Must be an existing file or a ressource in class-path + * + * @since 1.3 + */ + @Parameter(property = "jaxx.helpsetTemplate", defaultValue = "/defaultHelpSet.hs.vm", required = true) + protected File helpsetTemplate; + + /** + * The template used to generate helpset map file. + * <p/> + * Must be an existing file or a ressource in class-path + * + * @since 1.3 + */ + @Parameter(property = "jaxx.mapTemplate", defaultValue = "/defaultMap.jhm.vm", required = true) + protected File mapTemplate; + + /** + * The template used to generate helpset index file. + * <p/> + * Must be an existing file or a ressource in class-path + * + * @since 1.3 + */ + @Parameter(property = "jaxx.indexTemplate", defaultValue = "/defaultIndex.xml.vm", required = true) + protected File indexTemplate; + + /** + * The template used to generate helpset toc file. + * <p/> + * Must be an existing file or a ressource in class-path + * + * @since 1.3 + */ + @Parameter(property = "jaxx.tocTemplate", defaultValue = "/defaultToc.xml.vm", required = true) + protected File tocTemplate; + + /** + * The template used to generate helpset content file. + * <p/> + * Must be an existing file or a ressource in class-path + * + * @since 1.3 + */ + @Parameter(property = "jaxx.contentTemplate", defaultValue = "/defaultContent.html.vm", required = true) + protected File contentTemplate; + + protected String mapFileName; + + protected String indexFileName; + + protected String tocFileName; + + protected int touchedFiles; + + protected File idsFile; + + /** The help ids discovered. */ + protected Properties helpIds; + + @Override + public File getTargetDirectory() { + return outputHelp; + } + + @Override + public void setTargetDirectory(File targetDirectory) { + outputHelp = targetDirectory; + } + + @Override + public void init() throws Exception { + if (!generateHelp) { + return; + } + + // check ressources + checkResource(helpsetTemplate); + checkResource(mapTemplate); + checkResource(indexTemplate); + checkResource(tocTemplate); + checkResource(contentTemplate); + + mapFileName = helpsetName + "Map.jhm"; + indexFileName = helpsetName + "Index.xml"; + tocFileName = helpsetName + "TOC.xml"; + touchedFiles = 0; + + super.init(); + + // load ids from idsStore file + + if (isForce()) { + idsFile = getMergeHelpIdsStoreFile(); + } else { + idsFile = getHelpIdsStoreFile(); + } + + if (!idsFile.exists()) { + return; + } + + helpIds = new SortedProperties(); + + // loading all ids + Set<String> ids = loadHelpIds(idsFile); + + for (String id : ids) { + String path = id.replaceAll("\\.", File.separator) + ".html"; + helpIds.put(id, path); + } + } + + @Override + protected boolean checkSkip() { + boolean b = super.checkSkip(); + if (b) { + + if (!idsFile.exists()) { + // pas de fichier a traiter + if (isForce()) { + getLog().info("Force flag is on, but no helpIdStore-all" + + " to react at " + idsFile); + } else { + getLog().info("no helpIdStore to react at " + idsFile); + } + return false; + } + if (helpIds == null || helpIds.isEmpty()) { + getLog().info("No help ids to treate."); + return false; + } + } + return b; + } + + @Override + protected void postDoAction() { + getLog().info(touchedFiles + " file(s) treated."); + } + + @Override + protected void doActionForLocale(Locale locale, + boolean isDefaultLocale, + File localizedTarget, + String localePath) throws Exception { + + String language = locale.getLanguage(); + + getLog().info("Generate help for language " + language); + if (isVerbose()) { + getLog().info(" Localized target : " + localizedTarget); + } + + Properties env = new Properties(); + + env.put("helpSetName", helpsetName); + env.put("locale", language); + env.put("localePath", localePath); + env.put("separator", " "); + env.put("autoremoveLine", AUTOREMOVE_LINE); + + String localeSuffix = isDefaultLocale ? "" : "_" + language; + String helpsetFileName = helpsetName + localeSuffix + ".hs"; + + env.put("helpSetFileName", helpsetFileName); + + env.put("mapFileName", mapFileName); + env.put("indexFileName", indexFileName); + env.put("tocFileName", tocFileName); + env.put("generateSearch", generateSearch); + + // --------------------------------------------------------------- + // --- main helpset file ----------------------------------------- + // --------------------------------------------------------------- + + File file = new File(getTargetDirectory(), helpsetFileName); + + boolean doCreate = generateHelpsetFile(file, env); + + if (doCreate) { + touchedFiles++; + } + + // --------------------------------------------------------------- + // --- helpset map file ------------------------------------------ + // --------------------------------------------------------------- + + file = new File(localizedTarget, mapFileName); + + generateMapFile(file, env); + touchedFiles++; + + // --------------------------------------------------------------- + // --- helpset index file ---------------------------------------- + // --------------------------------------------------------------- + + file = new File(localizedTarget, indexFileName); + + generateIndexFile(file, env); + touchedFiles++; + + // --------------------------------------------------------------- + // --- helpset toc file ------------------------------------------ + // --------------------------------------------------------------- + + file = new File(localizedTarget, tocFileName); + + generateTocFile(file, env); + touchedFiles++; + + // --------------------------------------------------------------- + // --- helpset content files ------------------------------------- + // --------------------------------------------------------------- + + touchedFiles += generateContentFiles(localizedTarget, env, localePath); + } + + protected int generateContentFiles(File localizedTarget, + Properties env, + String localePath) throws Exception { + + int touchedFiles = 0; + VelocityTemplateGenerator gen = prepareGenerator(contentTemplate); + Enumeration<?> keys = helpIds.keys(); + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + String url = (String) helpIds.get(key); + url = helpsetName + File.separator + url; + File f = new File(localizedTarget, url); + boolean exist = f.exists(); + if (exist) { + // check if there is a autoremoveLine in content + String content = FileUtils.readFileToString(f); + if (!content.contains(AUTOREMOVE_LINE)) { + // no regenerate marker detected, so skip this file + if (isVerbose()) { + getLog().debug("skip existing file " + f); + } + continue; + } + } + createDirectoryIfNecessary(f.getParentFile()); + if (isVerbose()) { + if (exist) { + getLog().info("regenerate content file " + f); + } else { + getLog().info("generate content file " + f); + } + } + env.put("helpId", key); + env.put("helpIdUrl", localePath + "/" + url); + gen.generate(env, f); + touchedFiles++; + } + return touchedFiles; + } + + protected boolean generateHelpsetFile(File file, + Properties env) throws Exception { + + if (file.exists()) { + // check the autoremove line presence + String content = FileUtils.readFileToString(file); + if (!content.contains(AUTOREMOVE_LINE)) { + // no regenerate marker detected, so skip this file + if (isVerbose()) { + getLog().info("skip existing helpset main file " + file); + } + return false; + } + } + + if (isVerbose()) { + if (file.exists()) { + getLog().info("regenerate helpset main file " + file); + } else { + getLog().info("generate helpset main file " + file); + } + } + doGen(helpsetTemplate, file, env); + return true; + } + + protected Properties generateMapFile(File file, + Properties env) throws Exception { + + boolean create; + + Properties mergedHelpIds; + if (file.exists()) { + + // get back the exisiting data and merge it with incoming ones + + if (isVerbose()) { + getLog().info("loading existing helpset map file " + file); + } + + mergedHelpIds = XmlHelper.getExistingHelpIds(file, isVerbose(), + getLog()); + create = false; + + } else { + + mergedHelpIds = new SortedProperties(); + create = true; + } + + // inject new helpIds + + for (Object k : helpIds.keySet()) { + mergedHelpIds.put(k, helpsetName + "/" + helpIds.get(k)); + } + + if (!mergedHelpIds.contains("top")) { + + // on ajoute une entree vers le root du helpset + + String topUrl = helpsetName + ".html"; + helpIds.put("top", topUrl); + mergedHelpIds.put("top", helpsetName + "/" + topUrl); + if (isVerbose()) { + getLog().debug("add top entry with url " + topUrl); + } + } + + if (isVerbose()) { + if (create) { + getLog().info("generate helpset map file " + file); + } else { + getLog().info("udpate helpset map file " + file); + } + } + + env.put("helpIds", mergedHelpIds); + doGen(mapTemplate, file, env); + env.remove("helpIds"); + return mergedHelpIds; + } + + protected NodeItem generateIndexFile(File file, + Properties env) throws Exception { + NodeItem rootItem = null; + + boolean create; + + if (file.exists()) { + + create = false; + + rootItem = XmlHelper.getExistingItems("indexitem", file); + } else { + create = true; + } + + if (rootItem == null) { + rootItem = new NodeItem("top", helpsetName); + } + + // inject new index entries + + for (Object k : helpIds.keySet()) { + NodeItem toc = rootItem.findChild(k + ""); + if (isVerbose()) { + getLog().debug("index " + k + " : " + toc); + } + } + + if (isVerbose()) { + if (create) { + getLog().info("generate helpset index file " + file); + } else { + getLog().info("udpate helpset index file " + file); + } + } + + env.put("rootItem", rootItem); + doGen(indexTemplate, file, env); + env.remove("rootItem"); + return rootItem; + } + + protected NodeItem generateTocFile(File file, + Properties env) throws Exception { + NodeItem rootItem = null; + + boolean create; + + if (file.exists()) { + + create = false; + + rootItem = XmlHelper.getExistingItems("tocitem", file); + } else { + create = true; + } + + if (rootItem == null) { + rootItem = new NodeItem("top", helpsetName); + } + // inject new toc entries + + for (Object k : helpIds.keySet()) { + NodeItem toc = rootItem.findChild(k + ""); + if (isVerbose()) { + getLog().debug("toc " + k + " : " + toc); + } + } + + if (isVerbose()) { + if (create) { + getLog().info("generate helpset toc file " + file); + } else { + getLog().info("udpate helpset toc file " + file); + } + } + + env.put("rootItem", rootItem); + doGen(tocTemplate, file, env); + env.remove("rootItem"); + return rootItem; + } + + + protected void doGen(File template, File f, + Properties env) throws Exception { + VelocityTemplateGenerator gen = prepareGenerator(template); + gen.generate(env, f); + } + + protected VelocityTemplateGenerator prepareGenerator( + File template) throws Exception { + URL templateURL = getTemplate(template); + + if (isVerbose()) { + getLog().info("using template " + templateURL); + } + VelocityTemplateGenerator gen = + new VelocityTemplateGenerator(getProject(), templateURL); + return gen; + } + +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpIdsMojo.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpIdsMojo.java new file mode 100644 index 0000000..186313e --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpIdsMojo.java @@ -0,0 +1,142 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin; + +import jaxx.compiler.decorators.HelpRootCompiledObjectDecorator; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; + +import java.io.File; +import java.util.Locale; +import java.util.Set; + +/** + * Generate the help ids files from the previous jaxx generation. + * <p/> + * Created: 22 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +@Mojo(name = "generate-help-ids", + defaultPhase = LifecyclePhase.PROCESS_SOURCES, requiresProject = true) +public class GenerateHelpIdsMojo extends AbstractGenerateHelpMojo { + + /** help ids to react. */ + protected Set<String> helpIds; + + @Override + public void init() throws Exception { + if (!generateHelp) { + + return; + } + + super.init(); + + // check there is some bundle + if (getHelpIdsFilename() == null) { + throw new MojoFailureException( + "you must set the 'helpIdStore' property."); + } + if (getMergeHelpIdsFilename() == null) { + throw new MojoFailureException( + "you must set the 'helpIdStoreAll' property."); + } + + helpIds = HelpRootCompiledObjectDecorator.getHelpIds(); + + // always clean helpIdsStore before all + cleanHelpIdsStore(); + + } + + @Override + protected boolean checkSkip() { + boolean b = super.checkSkip(); + if (b) { + + if (helpIds.isEmpty()) { +// if (isVerbose()) { + // no ids detected in this compilation round + getLog().info("No help ids to treate, will skip goal."); +// } + return false; + } + } + return b; + } + + @Override + public void doAction() throws Exception { + + // store current jaxx session detected help ids + + File idsStore = getHelpIdsStoreFile(); + getLog().info("Store detected help ids to " + idsStore); + + storeHelpIds(idsStore, helpIds); + + // store merged help ids (to make possible a force on help generation) + + + File idsStoreAll = getMergeHelpIdsStoreFile(); + getLog().info("Merge help ids to " + idsStoreAll); + + if (idsStoreAll.exists()) { + Set<String> allIds = loadHelpIds(idsStoreAll); + helpIds.addAll(allIds); + allIds.clear(); + } + + storeHelpIds(idsStoreAll, helpIds); + + helpIds.clear(); + + } + + @Override + protected void doActionForLocale(Locale locale, + boolean isDefaultLocale, + File source, + String localePath) throws Exception { + // nothing to do specific to locale + } + + @Override + protected void postDoAction() { + } + + @Override + public File getTargetDirectory() { + return getOutputHelpIds(); + } + + @Override + public void setTargetDirectory(File targetDirectory) { + setOutputHelpIds(targetDirectory); + } +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpMojo.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpMojo.java new file mode 100644 index 0000000..f4a6f05 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpMojo.java @@ -0,0 +1,77 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; + +import java.io.File; +import java.util.Locale; + +/** + * Mojo to generate all the javax help stuff for your project. + * <p/> + * This mojo will chain all others help mojo required. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +@Mojo(name = "generate-help", + defaultPhase = LifecyclePhase.PROCESS_SOURCES, + requiresProject = true, + requiresDependencyResolution = ResolutionScope.COMPILE) +@Execute(goal = "generate-help-search") +public class GenerateHelpMojo extends AbstractGenerateHelpMojo { + + @Override + public File getTargetDirectory() { + return null; + } + + @Override + public void setTargetDirectory(File targetDirectory) { + } + + @Override + public void doAction() throws Exception { + + } + + @Override + protected void postDoAction() { + } + + @Override + protected void doActionForLocale(Locale locale, + boolean isDefaultLocale, + File localizedTarget, + String localePath) throws Exception { + + } + +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpSearchMojo.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpSearchMojo.java new file mode 100644 index 0000000..9018743 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateHelpSearchMojo.java @@ -0,0 +1,237 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import com.sun.java.help.search.Indexer; +import org.apache.maven.plugins.annotations.Execute; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.codehaus.plexus.util.FileUtils; +import org.nuiton.plugin.PluginHelper; + +import java.io.File; +import java.io.PrintStream; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * Generate the javax search index help for your project. + * <p/> + * The current files should be generated always in a generated directory and not in + * your src directories (this is mainly binary files not to be stored in scm system)... + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +@Mojo(name = "generate-help-search", + defaultPhase = LifecyclePhase.PROCESS_SOURCES, + requiresProject = true, + requiresDependencyResolution = ResolutionScope.COMPILE) +@Execute(goal = "generate-help-files") +public class GenerateHelpSearchMojo extends AbstractGenerateHelpMojo { + + /** + * The directory where to create or update help search index files. + * + * @since 2.0.0 + */ + @Parameter(property = "jaxx.outputHelpSearch", defaultValue = "${project.basedir}/target/generated-sources/help", required = true) + protected File outputHelpSearch; + + /** + * The directory where to pick content files to generate the index. + * + * @since 2.0.0 + */ + @Parameter(property = "jaxx.inputHelp", defaultValue = "${project.basedir}/src/main/help", required = true) + protected File inputHelp; + + protected String timestamp; + + @Override + public void init() throws Exception { + if (!generateHelp || !generateSearch) { + + return; + } + + timestamp = "-" + System.currentTimeMillis(); + super.init(); + } + + @Override + public File getTargetDirectory() { + return outputHelpSearch; + } + + @Override + public void setTargetDirectory(File targetDirectory) { + outputHelpSearch = targetDirectory; + } + + @Override + protected boolean checkSkip() { + boolean b = super.checkSkip(); + if (b) { + if (!generateSearch) { + getLog().info("generateSearch flag is off, will skip goal."); + return false; + } + } + return b; + } + + @Override + protected void doActionForLocale(Locale locale, + boolean isDefaultLocale, + File localizedTarget, + String localePath) throws Exception { + + String language = locale.getLanguage(); + + File source = new File(inputHelp, localePath); + + File target = new File(localizedTarget, "JavaHelpSearch"); +// File target = new File(getTargetDirectory(), localePath + File.separator + "JavaHelpSearch"); + + // detect if need to generate + + boolean generate = false; + + if (isForce()) { + + // always generate if force flag is no + generate = true; + + } else if (!target.exists()) { + + // target does not exist, must generate it + generate = true; + + } else { + + // see if there is something new in source + + Long sourceLast = getLastModified(source); + Long targetLast = getLastModified(target); + + if (isVerbose()) { + + getLog().info("lastModified of source : " + sourceLast); + getLog().info("lastModified of target : " + targetLast); + } + + if (targetLast == null || sourceLast == null || + targetLast < sourceLast) { + + // something is newer in source than in target + + generate = true; + } + + } + + if (!generate) { + getLog().info("Nothing to generate for language " + language + + " - all files are up to date."); + return; + } + + getLog().info("Generate help search index for language " + language); + + if (isVerbose()) { + getLog().info(" from " + source); + getLog().info(" to " + target); + } + + createDirectoryIfNecessary(source); +// createDirectoryIfNecessary(localizedTarget); + createDirectoryIfNecessary(target); + + // --------------------------------------------------------------- + // --- generate search index ------------------------------------- + // --------------------------------------------------------------- + + generateSearchIndex(source, target, locale); + } + + @Override + protected void postDoAction() { + + // add resources to the project + addResourceDir(getTargetDirectory(), "**/*"); + } + + protected void generateSearchIndex(File source, + File target, + Locale locale) throws Exception { + + long t0 = System.nanoTime(); + + Method m = Indexer.class.getDeclaredMethod("main", String[].class); + + // remove old index + FileUtils.deleteDirectory(target); + + //copy resources to a tmp dir (without any VCS infos) + File tmpDir = getFileFromBasedir("target", "jaxx-tmp", "indexer-" + locale + timestamp); + if (isVerbose()) { + getLog().info("copy files to " + tmpDir + " for indexing them."); + } + FileUtils.copyDirectoryStructure(source, tmpDir); +// FileUtils.copyDirectory(source, tmpDir, "**/*", StringUtils.join(DirectoryScanner.DEFAULTEXCLUDES, ",")+",**/*.jpg"); + + // prepare arguments of Indexer.main calling + List<String> params = new ArrayList<String>(); + params.add("-verbose"); + params.add("-db"); + params.add(target.getAbsolutePath()); + params.add("-logfile"); + File logFile = getFileFromBasedir("target", "generated-sources", "jaxx", "indexer-" + locale + ".log"); + params.add(logFile.getAbsolutePath()); + params.add(tmpDir.getAbsolutePath()); + PrintStream out = System.out; + PrintStream err = System.err; + + // invoke Indexer.main + try { + m.invoke(null, (Object) params.toArray(new String[params.size()])); + } finally { + System.setOut(out); + System.setErr(err); + } + if (isVerbose()) { + getLog().info( + "Search Index generated for " + locale + " in " + + PluginHelper.convertTime(System.nanoTime() - t0)); + } + } + +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateMojo.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateMojo.java new file mode 100644 index 0000000..b890822 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/GenerateMojo.java @@ -0,0 +1,683 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import jaxx.compiler.CompiledObjectDecorator; +import jaxx.compiler.CompilerConfiguration; +import jaxx.compiler.I18nHelper; +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXEngine; +import jaxx.compiler.JAXXFactory; +import jaxx.compiler.beans.BeanInfoUtil; +import jaxx.compiler.binding.DataBindingHelper; +import jaxx.compiler.finalizers.JAXXCompilerFinalizer; +import jaxx.compiler.spi.DefaultInitializer; +import jaxx.compiler.spi.Initializer; +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.swing.help.JAXXHelpBroker; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.nuiton.i18n.I18n; +import org.nuiton.io.MirroredFileUpdater; +import org.nuiton.plugin.PluginHelper; + +import java.beans.Introspector; +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Generates some java code from jaxx files. + * + * @author tchemit <chemit@codelutin.com> + */ +@Mojo(name = "generate", defaultPhase = LifecyclePhase.PROCESS_SOURCES, + requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true) +public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfiguration { + + /** Default includes to use, if none provided */ + private static final String[] INCLUDES = {"**/*.jaxx", "**/*.css"}; + + /** + * Directory where jaxx files are located. + */ + @Parameter(property = "jaxx.src", defaultValue = "${basedir}/src/main/java") + protected File src; + + /** + * Where to generate java files. + */ + @Parameter(property = "jaxx.outJava", defaultValue = "${basedir}/target/generated-sources/java") + protected File outJava; + + /** + * To filter file to treat. + */ + @Parameter(property = "jaxx.includes") + protected String[] includes; + + /** + * To filter files to NOt treat. + */ + @Parameter(property = "jaxx.excludes") + protected String[] excludes; + + /** + * FQN of compiler to use (by default swing one). + */ + @Parameter(property = "jaxx.compilerFQN", defaultValue = "jaxx.compiler.JAXXCompiler", required = true) + protected String compilerFQN; + + /** + * The name of implementation of {@link JAXXContext}to be used on {@link JAXXObject}. + * <p/> + * Must not be abstract. + */ + @Parameter(property = "jaxx.jaxxContextFQN", defaultValue = "jaxx.runtime.context.DefaultJAXXContext", required = true) + protected String jaxxContextFQN; + + /** + * The FQN of the ui to use for error notification. + * <p/> + * If not given, will use the one defined in validator + */ + @Parameter(property = "jaxx.defaultErrorUIFQN") + protected String defaultErrorUIFQN; + + /** + * The FQN of the ui to use for error notification. + * <p/> + * If not given, will use the one defined in validator + * + * @see CompiledObjectDecorator + */ + @Parameter(property = "jaxx.defaultDecoratorFQN", defaultValue = "jaxx.compiler.decorators.DefaultCompiledObjectDecorator") + protected String defaultDecoratorFQN; + + /** + * Flag to include in compiler classpath the java sources directories (src + * and outJava). + * <p/> + * By default, false. + */ + @Parameter(property = "jaxx.addSourcesToClassPath", defaultValue = "false") + protected boolean addSourcesToClassPath; + + /** + * Flag to include in compiler classpath the java resources directories (src + * and outJava). + * <p/> + * By default, false. + * + * @since 1.6.0 + */ + @Parameter(property = "jaxx.addResourcesToClassPath", defaultValue = "false") + protected boolean addResourcesToClassPath; + + /** + * Flag to include in compiler classpath the compile class-path (can only be + * used in a test phase). + * <p/> + * By default, false. + * + * @since 1.6.0 + */ + @Parameter(property = "jaxx.addCompileClassPath", defaultValue = "false") + protected boolean addCompileClassPath; + + /** + * Flag to include in compiler classpath the project compile classpath. + * <p/> + * By default, false. + */ + @Parameter(property = "jaxx.addProjectClassPath", defaultValue = "false") + protected boolean addProjectClassPath; + + /** + * A flag to mark the mojo to be used in a test phase. This will permits to + * add generated sources in test compile roots. + * + * @since 1.6.0 + */ + @Parameter(property = "jaxx.testPhase", defaultValue = "false") + protected boolean testPhase; + + /** + * To make compiler i18nable, says add the {@link I18n#_(String, Object...)} + * method invocation on {@link I18nHelper#I18N_ATTRIBUTES} attributes. + * + * @see I18nHelper + */ + @Parameter(property = "jaxx.i18nable", defaultValue = "true") + protected boolean i18nable; + + /** + * To optimize generated code. + */ + @Parameter(property = "jaxx.optimize", defaultValue = "false") + protected boolean optimize; + + /** + * To auto import css files for a jaxx file. + * + * @since 2.0.2 + */ + @Parameter(property = "jaxx.autoImportCss", defaultValue = "false") + protected boolean autoImportCss; + + /** + * To let jaxx recurses in css when a JAXX Object auto import css files + * for a jaxx file. + * <p/> + * <b>Warning:</b> This option will be removed in version 3.0 or at least + * default value will become {@code false}. + * + * @since 2.0.2 + */ + @Parameter(property = "jaxx.autoRecurseInCss", defaultValue = "true") + protected boolean autoRecurseInCss; + + /** + * Flag to add logger to each generated jaxx file. + * <p/> + * By default, always add it. + */ + @Parameter(property = "jaxx.addLogger", defaultValue = "true") + protected boolean addLogger; + + /** + * Flag to keep compilers after the generate operation (usefull for tests. + * <p/> + * By default, always reset. + */ + @Parameter(property = "jaxx.resetAfterCompile", defaultValue = "true") + protected boolean resetAfterCompile; + + /** + * Extra path to be added in {@link Introspector#setBeanInfoSearchPath(String[])}. + * <p/> + * add beanInfoSearchPath to be registred by {@link BeanInfoUtil#addJaxxBeanInfoPath(String...)} + * <p/> + * and then will be use by {@link DefaultInitializer#initialize()}. + * <p/> + * <p/> + * This permit to use real beanInfo of imported graphic libraries. + */ + @Parameter(property = "jaxx.beanInfoSearchPath") + protected String[] beanInfoSearchPath; + + /** + * List of fqn of class toimport for all generated jaxx files. + */ + @Parameter(property = "jaxx.extraImportList") + protected String extraImportList; + + /** + * A flag to use UIManager to retreave icons. + */ + @Parameter(property = "jaxx.useUIManagerForIcon", defaultValue = "false") + protected boolean useUIManagerForIcon; + + /** + * flag to activate profile mode. + * <p/> + * By default, not active. + */ + @Parameter(property = "jaxx.profile", defaultValue = "false") + protected boolean profile; + + /** + * To show detected bindings. + * <p/> + * By default, do not show them. + * + * @since 2.0.0 + */ + @Parameter(property = "jaxx.showBinding", defaultValue = "false") + protected boolean showBinding; + + /** + * the FQN of help broker + * <p/> + * By default, use the JAXX implementation {@link JAXXHelpBroker}. + * + * @since 1.3 + */ + @Parameter(property = "jaxx.helpBrokerFQN", defaultValue = "jaxx.runtime.swing.help.JAXXHelpBroker") + protected String helpBrokerFQN; + + /** + * To trace class descriptor loading. + * <p/> + * By default, do not trace it. + * + * @since 2.4 + */ + @Parameter(property = "jaxx.showClassDescriptorLoading", defaultValue = "false") + private boolean showClassDescriptorLoading; + + /** + * Decorators available in engine. + * + * @since 2.0.2 + */ + @Component(role = CompiledObjectDecorator.class) + protected Map<String, CompiledObjectDecorator> decorators; + + /** + * Finalizers available in engine. + * + * @since 2.0.2 + */ + @Component(role = JAXXCompilerFinalizer.class) + protected Map<String, JAXXCompilerFinalizer> finalizers; + + /** + * Initializers available to init engine. + * + * @since 2.0.2 + */ + @Component(role = Initializer.class) + protected Map<String, Initializer> initializers; + + /** detected jaxx files in {@link #init()} method */ + protected String[] files; + + /** + * file updater used to detect jaxx files. + * <p/> + * <b>Note:</b> if {@link #verbose} flag is on, will ne be used + */ + protected MirroredFileUpdater updater; + + /** type of error ui class (in validation) to use */ + private Class<?> defaultErrorUIClass; + + /** type of {@link CompiledObjectDecorator} to use */ + private Class<? extends CompiledObjectDecorator> defaultDecoratorClass; + + /** type of {@link JAXXContext} to use */ + private Class<? extends JAXXContext> jaxxContextClass; + + /** type of compiler to use */ + private Class<? extends JAXXCompiler> compilerClass; + + /** extra imports to always add in each generated java file */ + private String[] extraImports; + + /** internal state to known if a files has to be generated */ + private boolean nofiles; + + /** customized classloader to use in engine */ + protected ClassLoader cl; + + /** JAXX engine */ + private JAXXEngine engine; + + @SuppressWarnings("unchecked") + @Override + public void init() throws Exception { + + if (getLog().isDebugEnabled()) { + // if debug is on, then verbose also + setVerbose(true); + } + fixCompileSourceRoots(); + + if (includes == null || includes.length == 0) { + // use default includes + includes = INCLUDES; + } + updater = new JaxxFileUpdater(src, outJava); + + Map<File, String[]> result = new HashMap<File, String[]>(); + getFilesToTreateForRoots( + includes, + excludes, + Arrays.asList(src.getAbsolutePath()), + result, + isForce() ? null : updater); + + files = result.get(src); + + // Evolution #435: Regenerates jaxx files when his css file is modified + // filter css and jaxx files to obtain only jaxx files + // if a css is modified, try to find the corresponding jaxx files + if (files != null && files.length > 0) { + Set<String> filterFiles = new HashSet<String>(files.length); + for (String path : files) { + if (path.endsWith(".css")) { + // take the jaxx file + String jaxxFilePath = + path.substring(0, path.length() - 4) + ".jaxx"; + File f = new File(src, jaxxFilePath); + if (f.exists()) { + if (isVerbose()) { + getLog().info("will treate jaxx file from css " + + f); + } + filterFiles.add(jaxxFilePath); + } else { + getLog().warn("can not find jaxx file corresponding " + + "to modified css file " + path); + } + continue; + } + if (path.endsWith(".jaxx")) { + filterFiles.add(path); + } + } + files = filterFiles.toArray(new String[filterFiles.size()]); + } + + nofiles = files == null || files.length == 0; + if (nofiles) { + if (getLog().isDebugEnabled()) { + getLog().debug("No file to treate."); + } + return; + } + + cl = initClassLoader(getProject(), + src, + addSourcesToClassPath, + testPhase, + addResourcesToClassPath, + addCompileClassPath, + addProjectClassPath); + + Thread.currentThread().setContextClassLoader(cl); + + compilerClass = (Class<? extends JAXXCompiler>) + Class.forName(compilerFQN, false, cl); + defaultDecoratorClass = (Class<? extends CompiledObjectDecorator>) + Class.forName(defaultDecoratorFQN, false, cl); + jaxxContextClass = (Class<? extends JAXXContext>) + Class.forName(jaxxContextFQN, false, cl); + if (!JAXXContext.class.isAssignableFrom(jaxxContextClass)) { + throw new MojoExecutionException( + "jaxxContextFQN must be an implementation of " + + JAXXContext.class + " but was : " + jaxxContextClass); + } +// validatorClass = Class.forName(validatorFQN, false, cl); + + if (defaultErrorUIFQN != null && !defaultErrorUIFQN.trim().isEmpty()) { + defaultErrorUIClass = Class.forName(defaultErrorUIFQN, false, cl); + } + + if (beanInfoSearchPath != null && beanInfoSearchPath.length > 0) { + // register extra path + BeanInfoUtil.addJaxxBeanInfoPath(beanInfoSearchPath); + } + + createDirectoryIfNecessary(getTargetDirectory()); + + // compute extra imports (can not use java classes since some of + // imports can not be still compiled) + if (extraImportList != null && !extraImportList.isEmpty()) { + String[] imports = extraImportList.split(","); + int i = 0; + for (String importS : imports) { + imports[i++] = importS.trim(); + } + if (isVerbose()) { + getLog().info("extra imports " + Arrays.toString(imports)); + } + extraImports = imports; + } + + if (isVerbose()) { +// getLog().info(toString()); + getLog().info("includes : " + Arrays.toString(includes)); + for (String file : files) { + getLog().info("will parse " + file); + } + } + } + + @Override + protected boolean checkSkip() { + if (nofiles) { + getLog().info("Nothing to generate - all files are up to date."); + return false; + } + return true; + } + + @Override + public void doAction() throws Exception { + + getLog().info("Detects " + files.length + " modified jaxx file(s). "); + + if (showBinding) { + DataBindingHelper.SHOW_LOG = showBinding; + } + try { + long t0 = System.nanoTime(); + + // register configuration to factory + JAXXFactory.setConfiguration(this); + + // create new engine + engine = JAXXFactory.newEngine(src, files); + + //FIXME-TC20100502 remove this managment by -1 for error! + // run engine + int nbFiles = engine.run(); + + // report engine results (errors, warnings,...) + report(engine); + + if (nbFiles == -1) { + throw new MojoExecutionException( + "Aborting due to errors reported by jaxxc"); + } + String delay = PluginHelper.convertTime(System.nanoTime() - t0); + getLog().info("Generated " + nbFiles + " file(s) in " + delay); + } finally { + DataBindingHelper.SHOW_LOG = false; + } + } + + @Override + public File getTargetDirectory() { + return outJava; + } + + @Override + public void setTargetDirectory(File targetDirectory) { + outJava = targetDirectory; + } + + @Override + public boolean getOptimize() { + return optimize; + } + + @Override + public boolean isAutoImportCss() { + return autoImportCss; + } + + @Override + public boolean isAutoRecurseInCss() { + return autoRecurseInCss; + } + + @Override + public boolean isI18nable() { + return i18nable; + } + + @Override + public boolean isUseUIManagerForIcon() { + return useUIManagerForIcon; + } + + @Override + public boolean isAddLogger() { + return addLogger; + } + + @Override + public boolean isShowClassDescriptorLoading() { + return showClassDescriptorLoading; + } + + @Override + public Class<? extends JAXXContext> getJaxxContextClass() { + return jaxxContextClass; + } + + @Override + public String[] getExtraImports() { + return extraImports; + } + + @Override + public boolean isResetAfterCompile() { + return resetAfterCompile; + } + + @Override + public boolean isOptimize() { + return optimize; + } + + @Override + public Class<?> getDefaultErrorUI() { + return defaultErrorUIClass; + } + + @Override + public ClassLoader getClassLoader() { + return cl; + } + + @Override + public Class<? extends JAXXCompiler> getCompilerClass() { + return compilerClass; + } + + @Override + public Class<? extends CompiledObjectDecorator> getDefaultDecoratorClass() { + return defaultDecoratorClass; + } + + @Override + public boolean isProfile() { + return profile; + } + + @Override + public boolean isGenerateHelp() { + return generateHelp; + } + + @Override + public String getHelpBrokerFQN() { + return helpBrokerFQN; + } + + @Override + public Map<String, CompiledObjectDecorator> getDecorators() { + return decorators; + } + + @Override + public Map<String, JAXXCompilerFinalizer> getFinalizers() { + return finalizers; + } + + @Override + public Map<String, Initializer> getInitializers() { + return initializers; + } + + public JAXXEngine getEngine() { + return engine; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString( + this, ToStringStyle.MULTI_LINE_STYLE); + } + + protected void fixCompileSourceRoots() { + //FIXME TC20091222 : why this test ? should always have a project ? + // even in tests... + if (getProject() == null) { + // no project defined, can not fix anything + // this case could appear if we wanted to do some tests of the plugin + return; + } + + if (testPhase) { + addTestCompileSourceRoots(getTargetDirectory()); + } else { + addCompileSourceRoots(getTargetDirectory()); + } + } + + protected void report(JAXXEngine engine) { + List<String> warnings = engine.getWarnings(); + if (!warnings.isEmpty()) { + StringBuilder buffer = new StringBuilder( + "JAXX detects " + + (warnings.size() == 1 ? "1 warning" : + warnings.size() + " warnings")); + buffer.append(" :"); + for (String s : warnings) { + buffer.append("\n").append(s); + } + getLog().warn(buffer.toString()); + } + List<String> errors = engine.getErrors(); + if (!errors.isEmpty()) { + StringBuilder buffer = new StringBuilder( + "JAXX detects " + + (errors.size() == 1 ? "1 error" : + errors.size() + " errors")); + buffer.append(" :"); + for (String s : errors) { + buffer.append("\n").append(s); + } + getLog().error(buffer.toString()); + } + } +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/NodeItem.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/NodeItem.java new file mode 100644 index 0000000..cc08536 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/NodeItem.java @@ -0,0 +1,167 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import static org.nuiton.i18n.I18n._; + +public class NodeItem { + + String absoluteTarget; + private String target; + private String text; + private List<NodeItem> childs; + + public NodeItem(String target, String text) { + this.target = target; + absoluteTarget = target; + + this.text = text; + } + + public String getTarget() { + return target; + } + + public String getAbsoluteTarget() { + return absoluteTarget; + } + + public String getText() { + return text; + } + + public List<NodeItem> getChilds() { + return childs; + } + + public void setText(String text) { + this.text = text; + } + + public NodeItem findChild(String path) { + NodeItem result = null; + String[] paths = path.split("\\."); + for (int i = 0, j = paths.length; i < j; i++) { + String p = paths[i]; + if (result == null) { + + // first node + if (target.equals(p)) { + result = this; + continue; + } + result = getChild(p); + if (result == null) { + result = new NodeItem(p, null); + addChild(result); + adjutsAbsoluteTarget(result); + } + continue; + } + NodeItem child = result.getChild(p); + if (child == null) { + child = new NodeItem(p, null); + result.addChild(child); + result.adjutsAbsoluteTarget(child); + result = child; + } else { + result = child; + } + } + return result; + } + + public NodeItem getChild(int index) { + return childs.get(index); + } + + public NodeItem getChild(String target) { + if (isLeaf()) { + return null; + } + for (NodeItem i : childs) { + if (i.target.equals(target)) { + return i; + } + } + return null; + } + + public void addChild(NodeItem child) { + if (childs == null) { + childs = new ArrayList<NodeItem>(); + } + + childs.add(child); + } + + public void adjutsAbsoluteTarget(NodeItem child) { + if (!"top".equals(target)) { + // on ne prefixe pas les fils direct du root + child.absoluteTarget = absoluteTarget + "." + child.target; + } + } + + public void adjustTarget() { + int index = target.lastIndexOf("."); + if (index > -1) { + target = target.substring(index + 1); + } + } + + public boolean isLeaf() { + return childs == null || childs.isEmpty(); + } + + public void applyI18n(String prefix, String suffix) { + String key = prefix + getAbsoluteTarget() + suffix; + text = _(key); + if (!isLeaf()) { + for (NodeItem i : getChilds()) { + i.applyI18n(prefix, suffix); + } + } + } + + public void extractI18n(Set<String> keys, String prefix, String suffix) { + String key = prefix + getAbsoluteTarget() + suffix; + keys.add(key); + if (!isLeaf()) { + for (NodeItem i : getChilds()) { + i.extractI18n(keys, prefix, suffix); + } + } + } + + @Override + public String toString() { + return super.toString() + "<target:" + target + ", text:" + text + + ", nbChilds:" + (isLeaf() ? 0 : childs.size()) + ">"; + } +} diff --git a/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/XmlHelper.java b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/XmlHelper.java new file mode 100644 index 0000000..a3ba1fd --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/java/org/nuiton/jaxx/plugin/XmlHelper.java @@ -0,0 +1,234 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import java.util.Stack; +import org.apache.maven.plugin.logging.Log; +import org.nuiton.util.SortedProperties; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * To load {@link NodeItem} from xml. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class XmlHelper { + + public static Properties getExistingHelpIds(File file, + final boolean verbose, + final Log log) + throws SAXException, IOException { + + final Properties result = new SortedProperties(); + + XMLReader parser = XMLReaderFactory.createXMLReader(); + + parser.setContentHandler(new ContentHandlerAdapter() { + + String target; + String url; + + @Override + public void startElement(String uri, + String localName, + String qName, + Attributes atts) throws SAXException { + if ("mapID".equals(localName)) { + target = atts.getValue("target"); + url = atts.getValue("url"); + if (verbose) { + log.debug("detect map entry : " + target + " : " + url); + } + result.put(target, url); + } + } + }); + + InputStream s = new FileInputStream(file); + try { + parser.parse(new InputSource(s)); + } finally { + s.close(); + } + return result; + } + + public static NodeItem getExistingItems(String tagName, + File file) + throws SAXException, IOException { + + XMLReader parser = XMLReaderFactory.createXMLReader(); + NodeItemHandler handler = new NodeItemHandler(tagName); + + parser.setContentHandler(handler); + + NodeItem rootItem = null; + InputStream s = new FileInputStream(file); + try { + parser.parse(new InputSource(s)); + rootItem = handler.rootItem; + } finally { + s.close(); + } + return rootItem; + } + + static class NodeItemHandler extends ContentHandlerAdapter { + + NodeItem rootItem; + NodeItem currentItem; + final Stack<NodeItem> stack; + final String tagName; + + public NodeItemHandler(String tagName) { + this.tagName = tagName; + stack = new Stack<NodeItem>(); + } + + @Override + public void startDocument() throws SAXException { + rootItem = new NodeItem("top", null); + } + + @Override + public void startElement(String uri, + String localName, + String qName, + Attributes atts) throws SAXException { + if (tagName.equals(localName)) { + + String target = atts.getValue("target"); + String text = atts.getValue("text"); + + // debut d'un item + if (currentItem == null) { + // premier item + if (rootItem.getTarget().equals(target)) { + // le premier item est bien top + rootItem.setText(text); + currentItem = rootItem; + } else { + // le premier noeud n'est pas top + // en l'encapsule + stack.push(rootItem); + currentItem = new NodeItem(target, text); + rootItem.addChild(currentItem); + } + } else { + NodeItem newItem = new NodeItem(target, text); + currentItem.addChild(newItem); + currentItem = newItem; + } + currentItem.adjustTarget(); + stack.push(currentItem); + + } + } + + @Override + public void endElement(String uri, + String localName, + String qName) throws SAXException { + if (tagName.equals(localName)) { + // fin d'un item + stack.pop(); + if (!stack.isEmpty()) { + currentItem = stack.peek(); + } + } + } + } + + static class ContentHandlerAdapter implements ContentHandler { + + @Override + public void setDocumentLocator(Locator locator) { + } + + @Override + public void startDocument() throws SAXException { + } + + @Override + public void endDocument() throws SAXException { + } + + @Override + public void startPrefixMapping(String prefix, + String uri) throws SAXException { + } + + @Override + public void endPrefixMapping(String prefix) throws SAXException { + } + + @Override + public void startElement(String uri, + String localName, + String qName, + Attributes atts) throws SAXException { + } + + @Override + public void endElement(String uri, + String localName, + String qName) throws SAXException { + } + + @Override + public void characters(char[] ch, + int start, + int length) throws SAXException { + } + + @Override + public void ignorableWhitespace(char[] ch, + int start, + int length) throws SAXException { + } + + @Override + public void processingInstruction(String target, + String data) throws SAXException { + } + + @Override + public void skippedEntity(String name) throws SAXException { + } + } +} diff --git a/trunk/jaxx-maven-plugin/src/main/resources/defaultContent.html.vm b/trunk/jaxx-maven-plugin/src/main/resources/defaultContent.html.vm new file mode 100644 index 0000000..ac806dc --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/resources/defaultContent.html.vm @@ -0,0 +1,14 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> +<TITLE> +$helpId +</TITLE> +</HEAD> +<BODY BGCOLOR="#ffffff"> +<H1>$helpId</H1> + +<!-- $autoremoveLine --> + +</BODY> +</HTML> diff --git a/trunk/jaxx-maven-plugin/src/main/resources/defaultHelpSet.hs.vm b/trunk/jaxx-maven-plugin/src/main/resources/defaultHelpSet.hs.vm new file mode 100644 index 0000000..5b941b4 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/resources/defaultHelpSet.hs.vm @@ -0,0 +1,44 @@ +<?xml version='1.0' encoding='UTF-8' ?> +<!DOCTYPE helpset + PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 1.0//EN" + "http://java.sun.com/products/javahelp/helpset_1_0.dtd"> + +<helpset version="1.0" xml:lang="$locale"> + + <!-- $autoremoveLine --> + + <!-- title --> + <title>${helpSetTitle}</title> + + <!-- maps --> + <maps> + <homeID>top</homeID> + <mapref location="$localePath/$mapFileName"/> + </maps> + + <!-- views --> + <view> + <name>TOC</name> + <label>Table Of Contents</label> + <type>javax.help.TOCView</type> + <data>$localePath/$tocFileName</data> + </view> + + <view> + <name>Index</name> + <label>Index</label> + <type>javax.help.IndexView</type> + <data>$localePath/$indexFileName</data> + </view> + +#if ( $generateSearch ) + <view> + <name>Search</name> + <label>Search</label> + <type>javax.help.SearchView</type> + <data engine="com.sun.java.help.search.DefaultSearchEngine"> + $localePath/JavaHelpSearch + </data> + </view> +#end +</helpset> diff --git a/trunk/jaxx-maven-plugin/src/main/resources/defaultI18n.java.vm b/trunk/jaxx-maven-plugin/src/main/resources/defaultI18n.java.vm new file mode 100644 index 0000000..b11615e --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/resources/defaultI18n.java.vm @@ -0,0 +1,16 @@ +package $packageName; + +$!commentaire +public class $className { // $className + +{ +// BEGIN DO NOT REMOVE : used to detect helper i18n keys +// +#foreach( $key in $keys ) +// _("$key"); +#end +// +// END DO NOT REMOVE : used to detect helper i18n keys +} + +} // $className \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/main/resources/defaultIndex.xml.vm b/trunk/jaxx-maven-plugin/src/main/resources/defaultIndex.xml.vm new file mode 100644 index 0000000..e880e18 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/resources/defaultIndex.xml.vm @@ -0,0 +1,21 @@ +<?xml version='1.0' encoding='UTF-8' ?> +<!DOCTYPE index + PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Index Version 1.0//EN" + "http://buix.labs.libre-entreprise.org/javahelp/index_1_0.dtd"> + +## pour afficher un org.nuiton.jaxx.NodeItem +#macro ( renderItem $item $prefix ) +#if ( $item.isLeaf() ) +$prefix<indexitem target="$item.absoluteTarget" text="$!item.text"/> +#else +$prefix<indexitem target="$item.absoluteTarget" text="$!item.text"> +#foreach( $child in $item.getChilds() ) +#renderItem( $child "$prefix$separator" ) +#end +$prefix</indexitem> +#end +#end + +<index version="1.0"> +#renderItem( $rootItem $separator ) +</index> diff --git a/trunk/jaxx-maven-plugin/src/main/resources/defaultMap.jhm.vm b/trunk/jaxx-maven-plugin/src/main/resources/defaultMap.jhm.vm new file mode 100644 index 0000000..83fe6ee --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/resources/defaultMap.jhm.vm @@ -0,0 +1,16 @@ +<?xml version='1.0' encoding='UTF-8' ?> +<!DOCTYPE map + PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN" + "http://java.sun.com/products/javahelp/map_1_0.dtd"> +<map version="1.0"> + +#if ( !$helpIds.get("toplevelfolder")) + <!-- use this entry to go up in navigation --> + <!--mapID target="toplevelfolder" url="images/toplevel.gif" /--> +#end + +#foreach( $key in $helpIds.keys() ) + <mapID target="$key" url="$helpIds.get($key)" /> +#end + +</map> diff --git a/trunk/jaxx-maven-plugin/src/main/resources/defaultToc.xml.vm b/trunk/jaxx-maven-plugin/src/main/resources/defaultToc.xml.vm new file mode 100644 index 0000000..d3e5e57 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/resources/defaultToc.xml.vm @@ -0,0 +1,20 @@ +<?xml version='1.0' encoding='UTF-8' ?> +<!DOCTYPE toc + PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 1.0//EN" + "http://buix.labs.libre-entreprise.org/javahelp/toc_1_0.dtd"> + +## pour afficher un org.nuiton.jaxx.NodeItem +#macro ( renderItem $item $prefix ) +#if ( $item.isLeaf() ) +$prefix<tocitem target="$item.absoluteTarget" text="$!item.text"/> +#else +$prefix<tocitem target="$item.absoluteTarget" text="$!item.text"> +#foreach( $child in $item.getChilds() ) +#renderItem( $child "$prefix$separator" ) +#end +$prefix</tocitem> +#end +#end +<toc version="1.0"> +#renderItem( $rootItem $separator ) +</toc> diff --git a/trunk/jaxx-maven-plugin/src/main/resources/log4j.properties b/trunk/jaxx-maven-plugin/src/main/resources/log4j.properties new file mode 100644 index 0000000..07574d0 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/main/resources/log4j.properties @@ -0,0 +1,35 @@ +### +# #%L +# JAXX :: Maven plugin +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +# Global logging configuration +log4j.rootLogger=WARN, 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.nuiton.i18n=ERROR +log4j.logger.jaxx=INFO +#log4j.logger.jaxx.compiler=DEBUG +#log4j.logger.jaxx.runtime=DEBUG diff --git a/trunk/jaxx-maven-plugin/src/site/rst/Todo.rst b/trunk/jaxx-maven-plugin/src/site/rst/Todo.rst new file mode 100644 index 0000000..4716bff --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/site/rst/Todo.rst @@ -0,0 +1,30 @@ +.. - +.. * #%L +.. * JAXX :: Maven plugin +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +==== +TODO +==== + + +a faire diff --git a/trunk/jaxx-maven-plugin/src/site/rst/index.rst b/trunk/jaxx-maven-plugin/src/site/rst/index.rst new file mode 100644 index 0000000..bfd3100 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/site/rst/index.rst @@ -0,0 +1,55 @@ +.. - +.. * #%L +.. * JAXX :: Maven plugin +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +================= +jaxx-maven-plugin +================= + +.. contents:: + + +Introduction +------------ + +The plugin permits to generate java files from jaxx files via the **generate** goal. + +You can also generate the java help system via the **generate-helpXXX* goals. + +for more information, consult the `documentation of each mojo`_. + + +Default layout +-------------- + +The plugin defines some directory layout convention, using them is a great +benefit. + + * the jaxx files should be under *src/main/java* + * the generated java files should be under *target/generated-sources/java* + * the java help files should be under *src/main/help* + * the generated help search index should be under *target/generated-sources/help* + + +.. _documentation of each mojo: ./plugin-info.html diff --git a/trunk/jaxx-maven-plugin/src/site/site_fr.xml b/trunk/jaxx-maven-plugin/src/site/site_fr.xml new file mode 100644 index 0000000..98d44a4 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/site/site_fr.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <src>http://maven-site.chorem.org/public/images/logos/jaxx-logo.png</src> + <href>index.html</href> + </bannerLeft> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="index.html"/> + </breadcrumbs> + + <menu ref="parent"/> + + <menu name="Utilisateur"> + <item name="Accueil" href="index.html"/> + <item name="Détail goals" href="plugin-info.html"> + <item name="generate" href="generate-mojo.html"/> + <item name="generate-help" href="generate-help-mojo.html"/> + <item name="generate-help-search" href="generate-help-search-mojo.html"/> + <item name="help" href="help-mojo.html"/> + </item> + </menu> + + <menu name="Développeur" inherit="top"> + <item name="A faire" href="Todo.html"/> + </menu> + + <menu ref="reports"/> + + <menu ref="modules"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1124Test.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1124Test.java new file mode 100644 index 0000000..f5fab1e --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1124Test.java @@ -0,0 +1,99 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin; + +import jaxx.compiler.I18nHelper; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.TableColumnModelEvent; +import javax.swing.event.TableColumnModelListener; +import javax.swing.table.DefaultTableColumnModel; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +/** + * Fix the bug http://nuiton.org/issues/show/1124 + * + * @author tchemit <chemit@codelutin.com> + * @since 2.2.4 + */ +public class Bug1124Test { + + protected static final Log log = LogFactory.getLog(Bug1124Test.class); + + int i; + @Test + public void testColumnMarginChanged() throws Exception { + + TableColumnModel model = new DefaultTableColumnModel(); + + TableColumnModelListener listener; + + listener = JAXXUtil.getEventListener( + TableColumnModelListener.class, + "columnAdded", + this, + "myColumnAdded" + ); + + Assert.assertNotNull(listener); + + model.addColumnModelListener(listener); + + Assert.assertEquals(0,i); + + model.addColumn(new TableColumn(0)); + + Assert.assertEquals(1,i); + + listener = JAXXUtil.getEventListener( + TableColumnModelListener.class, + "columnMarginChanged", + this, + "myColumnMarginChanged" + ); + Assert.assertNotNull(listener); + + model.addColumnModelListener(listener); + model.setColumnMargin(12); + Assert.assertEquals(2,i); +// listener.columnMarginChanged(new ChangeEvent(this)); + } + + public void myColumnAdded(TableColumnModelEvent evt) { + log.info(evt.getSource()); + i++; + } + + public void myColumnMarginChanged(ChangeEvent evt) { + log.info(evt.getSource()); + i++; + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1404Test.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1404Test.java new file mode 100644 index 0000000..9f16b78 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1404Test.java @@ -0,0 +1,47 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin; + +import org.junit.Test; + +/** + * Test the bug describe here http://nuiton.org/issues/show/1404 + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4.1 + */ +public class Bug1404Test extends JaxxBaseTest { + + @Test + public void Bug_1404() throws Exception { + + GenerateMojo mojo = getMojo(); + mojo.execute(); + assertNumberJaxxFiles(3); + + checkPattern(mojo, "import jaxx.runtime.SwingUtil;", true); + checkPattern(mojo, "import jaxx.runtime.JAXXUtil;", true); + } +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1722Test.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1722Test.java new file mode 100644 index 0000000..a942572 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1722Test.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.junit.Test; + +/** @author tchemit <chemit@codelutin.com> */ +public class Bug1722Test extends JaxxBaseTest { + + @Test + public void Bug_1722() throws Exception { + getMojo().execute(); + assertNumberJaxxFiles(2); + } + + +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1750Test.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1750Test.java new file mode 100644 index 0000000..25edf55 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1750Test.java @@ -0,0 +1,71 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import jaxx.runtime.Base64Coder; +import jaxx.compiler.JAXXCompiler; +import jaxx.runtime.JAXXObjectDescriptor; +import jaxx.runtime.JAXXUtil; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** @author tchemit <chemit@codelutin.com> */ +public class Bug1750Test extends JaxxBaseTest { + + @Test + public void Bug_1750() throws Exception { + getMojo().execute(); + assertNumberJaxxFiles(1); + + JAXXCompiler compiler = getMojo().getEngine().getJAXXCompiler("org.nuiton.jaxx.plugin.bug1750Test.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 = JAXXUtil.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 = JAXXUtil.decodeCompressedJAXXObjectDescriptor(data); + assertNotNull(descriptor2); + assertEquals(descriptor.toString(), descriptor2.toString()); + + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1751Test.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1751Test.java new file mode 100644 index 0000000..7b86926 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug1751Test.java @@ -0,0 +1,43 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.junit.Test; + +/** @author tchemit <chemit@codelutin.com> */ +public class Bug1751Test extends JaxxBaseTest { + + @Test + public void Bug_1751() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.execute(); + assertNumberJaxxFiles(3); + + checkPattern(mojo, "implements Serializable", true); + checkPattern(mojo, "setText(_(\"test\"))", true); + } + +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug184Test.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug184Test.java new file mode 100644 index 0000000..b689cda --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Bug184Test.java @@ -0,0 +1,47 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin; + +import org.junit.Test; + +/** + * Created: 4 janv. 2010 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public class Bug184Test extends JaxxBaseTest { + + @Test + public void Bug_184() throws Exception { + getMojo().execute(); + assertNumberJaxxFiles(1); + } + + +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerTest.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerTest.java new file mode 100644 index 0000000..51d5131 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerTest.java @@ -0,0 +1,325 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import jaxx.runtime.context.DefaultJAXXContext; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.junit.Test; + +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class CompilerTest extends JaxxBaseTest { + + @Test + public void InnerClasses() throws Exception { + getMojo().execute(); + assertNumberJaxxFiles(1); + } + + @Test + public void Icon() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.execute(); + checkPattern(mojo, ".createImageIcon(\"myIcon.png\")", true); + checkPattern(mojo, ".createActionIcon(\"myActionIcon.png\")", true); + checkPattern(mojo, ".getUIManagerIcon(\"myIcon.png\")", false); + checkPattern(mojo, ".getUIManagerActionIcon(\"myActionIcon.png\")", false); + assertNumberJaxxFiles(1); + mojo.useUIManagerForIcon = true; + mojo.execute(); + checkPattern(mojo, ".createImageIcon(\"myIcon.png\")", false); + checkPattern(mojo, ".createActionIcon(\"myActionIcon.png\")", false); + checkPattern(mojo, ".getUIManagerIcon(\"myIcon.png\")", true); + checkPattern(mojo, ".getUIManagerActionIcon(\"myActionIcon.png\")", true); + } + + @Test + public void ClientProperty() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.execute(); + checkPattern(mojo, ".putClientProperty(\"testOne\", \"oneTest\")", true); + checkPattern(mojo, ".putClientProperty(\"testTwo\", \"anotherTest\")", true); + } + + @Test + public void SpecialSubclassing() throws Exception { + getMojo().execute(); + assertNumberJaxxFiles(7); + } + + @Test + public void CSSTests() throws Exception { + executeMojo(); + assertNumberJaxxFiles(7); + } + + @Test + public void WithLog() throws Exception { + GenerateMojo mojo = getMojo(); + executeMojo(); + String[] files = mojo.files; + assertNumberJaxxFiles(2); + + String withLogFile = 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); + + withLogFile = files[1]; + 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); + } + + @Test + public void NoLog() throws Exception { + GenerateMojo mojo = getMojo(); + executeMojo(); + assertNumberJaxxFiles(2); + checkPattern(mojo, "Log log = LogFactory.getLog(", false); + checkPattern(mojo, "import org.apache.commons.logging.Log;", false); + checkPattern(mojo, "import org.apache.commons.logging.LogFactory;", false); + } + + @SuppressWarnings({"unchecked"}) + @Test + public void Errors() throws Exception { + GenerateMojo mojo = getMojo(); + // init mojo to get alls files to treate + mojo.init(); + + assertNumberJaxxFiles(33); + 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 + } + }); + + // execute mjo on each jaxx file to produce the error + for (String file : mojo.files) { + log.info("test bad file " + file); + mojo.files = new String[]{file}; + try { + mojo.doAction(); + // should never pass + fail(); + } catch (MojoExecutionException e) { + // ok jaxx compiler failed + assertTrue(true); + assertError(mojo.getEngine(), file, 1); + } + } + } + + + @SuppressWarnings({"unchecked"}) + @Test + public void ErrorsCss() throws Exception { + GenerateMojo mojo = getMojo(); + // init mojo to get alls files to treate + mojo.init(); + + assertNumberJaxxFiles(1); + 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 + } + }); + + // execute mjo on each jaxx file to produce the error + for (String file : mojo.files) { + log.info("test bad file " + file); + mojo.files = new String[]{file}; + try { + mojo.doAction(); + // should never pass + fail(); + } catch (MojoExecutionException e) { + // ok jaxx compiler failed + assertTrue(true); + assertError(mojo.getEngine(), file, 1); + } + } + } + + @Test + public void Initializers() throws Exception { + executeMojo(); + assertNumberJaxxFiles(1); + } + + + @Test + public void ImportTag() throws Exception { + executeMojo(); + assertNumberJaxxFiles(1); + } + + @Test + public void ErrorJaxxContextImplementorClass() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.jaxxContextFQN = null; + try { + mojo.init(); + fail(); + } catch (NullPointerException e) { + assertTrue(true); + } + + mojo.jaxxContextFQN = String.class.getName(); + try { + mojo.init(); + fail(); + } catch (MojoExecutionException e) { + assertTrue(true); + } +// +// mojo.jaxxContextFQN = JAXXContext.class.getName(); +// try { +// mojo.init(); +// fail(); +// } catch (IllegalArgumentException e) { +// assertTrue(true); +// } + + mojo.jaxxContextFQN = DefaultJAXXContext.class.getName(); + mojo.init(); + assertTrue(true); + + } + + @Test + public void Script() throws Exception { + executeMojo(); + assertNumberJaxxFiles(1); + } + + @Test + public void OverridingDataBindings() throws Exception { + executeMojo(); + assertNumberJaxxFiles(3); + } + + @Test + public void ClassReferences() throws Exception { + executeMojo(); + assertNumberJaxxFiles(6); + } + + @Test + public void Force() throws Exception { + + // first round, with force option so will generate theonly JButton.jaxx file + GenerateMojo mojo = getMojo(); + executeMojo(); + String[] files = mojo.files; + assertNumberJaxxFiles(1); + + File srcFile = new File(mojo.src, files[0]); + + File dstFile = mojo.updater.getMirrorFile(srcFile); + + long oldTime = dstFile.lastModified(); + // second round, no force so will not the file + mojo.setForce(false); + executeMojo(); + assertNumberJaxxFiles(0); + + Thread.sleep(1000); + + assertEquals(oldTime, mojo.updater.getMirrorFile(srcFile).lastModified()); + + // three round : modify a source with no force option + if (!srcFile.setLastModified(System.currentTimeMillis())) { + log.warn("failed to set LastModified for file " + srcFile); + } + + executeMojo(); + assertNumberJaxxFiles(1); + assertTrue(mojo.updater.getMirrorFile(srcFile).lastModified() > oldTime); + + // last round, reforce file generation for an no modify source + mojo.setForce(true); + executeMojo(); + assertNumberJaxxFiles(1); + assertTrue(mojo.updater.getMirrorFile(srcFile).lastModified() > oldTime); + } + + protected void executeMojo() throws MojoExecutionException, MojoFailureException { + + try { + getMojo().execute(); + } catch (MojoExecutionException e) { + log.error(e); + throw e; + } catch (MojoFailureException e) { + log.error(e); + throw e; + } + + } + +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerValidatorTest.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerValidatorTest.java new file mode 100644 index 0000000..e920333 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/CompilerValidatorTest.java @@ -0,0 +1,91 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.SystemStreamLog; + + + +import org.junit.Test; +import static org.junit.Assert.*; + +public class CompilerValidatorTest extends JaxxBaseTest { + + @Test + public void ValidatorOk() throws Exception { + getMojo().execute(); + assertNumberJaxxFiles(2); + + } + + @Test + @SuppressWarnings({"unchecked"}) + public void ValidatorErrors() throws Exception { + // init mojo to get alls files to treate + GenerateMojo mojo = getMojo(); + mojo.init(); + String[] files = mojo.files; + assertNumberJaxxFiles(19); + 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 + } + }); + + // execute mjo on each jaxx file to produce the error + for (String file : files) { + log.info("test bad file " + file); + mojo.files = new String[]{file}; + try { + mojo.doAction(); + // should never pass + fail("for file " + file); + } catch (MojoExecutionException e) { + // ok jaxx compiler failed + assertTrue(true); + assertError(mojo.getEngine(), file, 1); + } + } + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBinding/Bean.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBinding/Bean.java new file mode 100644 index 0000000..cec6a3c --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBinding/Bean.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin.DataBinding; + +import java.beans.PropertyChangeListener; + +public interface Bean { + + void addPropertyChangeListener(PropertyChangeListener listener); + + void addPropertyChangeListener(String propertyName, PropertyChangeListener listener); + + void removePropertyChangeListener(PropertyChangeListener listener); + + void removePropertyChangeListener(String propertyName, PropertyChangeListener listener); + + String getText(); +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBinding/BeanImpl.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBinding/BeanImpl.java new file mode 100644 index 0000000..67076f7 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBinding/BeanImpl.java @@ -0,0 +1,62 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin.DataBinding; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class BeanImpl implements Bean{ + + protected String text; + PropertyChangeSupport p; + + public BeanImpl() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBindingTest.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBindingTest.java new file mode 100644 index 0000000..362b695 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DataBindingTest.java @@ -0,0 +1,59 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import java.io.IOException; +import org.junit.Test; + +/** + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class DataBindingTest extends JaxxBaseTest { + + @Test + public void simpleBinding() throws Exception { + + GenerateMojo mojo = getMojo(); + mojo.execute(); + assertNumberJaxxFiles(1); + + // no bindings + checkPattern(mojo, "BINDING_NOBINDING1_TEXT", false); + checkPattern(mojo, "BINDING_NOBINDING2_TEXT", false); + + // with bindings + checkBinding(mojo, "BINDING_BINDING8_TEXT"); + } + + protected void checkBinding(GenerateMojo mojo, String... bindings) throws IOException { + for (String b : bindings) { + checkPattern(mojo, "public static final String " + b + " = ", true); +// checkPattern(mojo, "new DataBindingListener(this, " + b + ");", true); + } + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DecoratorTest.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DecoratorTest.java new file mode 100644 index 0000000..ece7653 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/DecoratorTest.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.junit.Test; + +public class DecoratorTest extends JaxxBaseTest { + + @Test + public void Decorator() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.execute(); + assertNumberJaxxFiles(1); + checkPattern(mojo, "add(SwingUtil.boxComponentWithJxLayer(boxedButton))", true); + } + +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Evolution74Test.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Evolution74Test.java new file mode 100644 index 0000000..4919f9d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/Evolution74Test.java @@ -0,0 +1,106 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.apache.maven.plugin.MojoExecutionException; + + +import org.apache.maven.plugin.logging.SystemStreamLog; +import org.junit.Test; +import static org.junit.Assert.*; + +public class Evolution74Test extends JaxxBaseTest { + + @Test + public void ok() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.execute(); + assertNumberJaxxFiles(6); + + checkPattern(mojo, "JComboBox", true, "org/nuiton/jaxx/plugin/evolution74Test/ok/swingcombo.java"); + checkPattern(mojo, "JComboBox", false, "org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxcombo.java"); + checkPattern(mojo, "JAXXComboBox", false, "org/nuiton/jaxx/plugin/evolution74Test/ok/swingcombo.java"); + checkPattern(mojo, "JAXXComboBox", true, "org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxcombo.java"); + + checkPattern(mojo, "JList", true, "org/nuiton/jaxx/plugin/evolution74Test/ok/swinglist.java"); + checkPattern(mojo, "JList", false, "org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxlist.java"); + checkPattern(mojo, "JAXXList", false, "org/nuiton/jaxx/plugin/evolution74Test/ok/swinglist.java"); + checkPattern(mojo, "JAXXList", true, "org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxlist.java"); + + checkPattern(mojo, "JTree", true, "org/nuiton/jaxx/plugin/evolution74Test/ok/swingtree.java"); + checkPattern(mojo, "JTree", false, "org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxtree.java"); + checkPattern(mojo, "JAXXTree", false, "org/nuiton/jaxx/plugin/evolution74Test/ok/swingtree.java"); + checkPattern(mojo, "JAXXTree", true, "org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxtree.java"); + } + + @SuppressWarnings({"unchecked"}) + @Test + public void error() throws Exception { + GenerateMojo mojo = getMojo(); + // init mojo to get alls files to treate + mojo.init(); + + assertNumberJaxxFiles(3); + + 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 + } + }); + + // execute mjo on each jaxx file to produce the error + for (String file : mojo.files) { + log.info("test bad file " + file); + mojo.files = new String[]{file}; + try { + mojo.doAction(); + // should never pass + fail(); + } catch (MojoExecutionException e) { + // ok jaxx compiler failed + assertTrue(true); + assertError(mojo.getEngine(), file, 1); + } + } + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/I18nTest.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/I18nTest.java new file mode 100644 index 0000000..6b04ab8 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/I18nTest.java @@ -0,0 +1,70 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.junit.Test; + +public class I18nTest extends JaxxBaseTest { + + @Test + public void I18nText() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.i18nable = false; + mojo.execute(); + checkPattern(mojo, "setText(_(\"test.text\"));", false); + + mojo.i18nable = true; + mojo.execute(); + checkPattern(mojo, "setText(_(\"test.text\"));", true); + checkPattern(mojo, "\"_(\\\"test.text\\\")\"", false); + } + + @Test + public void I18nTitle() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.i18nable = false; + mojo.execute(); + checkPattern(mojo, "setTitle(_(\"test.title\"));", false); + + mojo.i18nable = true; + mojo.execute(); + checkPattern(mojo, "setTitle(_(\"test.title\"));", true); + checkPattern(mojo, "\"_(\\\"test.title\\\")\"", false); + } + + @Test + public void I18nToolTipText() throws Exception { + GenerateMojo mojo = getMojo(); + mojo.i18nable = false; + mojo.execute(); + checkPattern(mojo, "setToolTipText(_(\"test.toolTipText\"));", false); + + mojo.i18nable = true; + mojo.execute(); + checkPattern(mojo, "setToolTipText(_(\"test.toolTipText\"));", true); + checkPattern(mojo, "\"_(\\\"test.toolTipText\\\")\"", false); + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/JaxxBaseTest.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/JaxxBaseTest.java new file mode 100644 index 0000000..a468a3a --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/JaxxBaseTest.java @@ -0,0 +1,111 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import jaxx.compiler.JAXXCompiler; +import jaxx.compiler.JAXXCompilerFile; +import jaxx.compiler.JAXXEngine; +import jaxx.compiler.decorators.DefaultCompiledObjectDecorator; +import jaxx.runtime.context.DefaultJAXXContext; +import org.apache.commons.io.FileUtils; +import org.nuiton.plugin.AbstractMojoTest; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Base test case for a jaxx:generate goal. + * <p/> + * Use {@link AbstractMojoTest} from {@code helper-maven-plugin}. + * + * @author tchemit <chemit@codelutin.com> + * @see AbstractMojoTest + * @see GenerateMojo + */ +public abstract class JaxxBaseTest extends AbstractMojoTest<GenerateMojo> { + + @Override + protected String getGoalName(String methodName) { + return "generate"; + } + + @Override + protected void setUpMojo(GenerateMojo mojo, File pomFile) throws Exception { + try { + super.setUpMojo(mojo, pomFile); + } catch (Exception e) { + if (log.isErrorEnabled()) { + log.error(e); + } + } + mojo.jaxxContextFQN = DefaultJAXXContext.class.getName(); + mojo.compilerFQN = JAXXCompiler.class.getName(); + mojo.defaultDecoratorFQN = DefaultCompiledObjectDecorator.class.getName(); + } + + protected void checkPattern(GenerateMojo mojo, + String pattern, + boolean required, + String... files) throws IOException { + if (files.length == 0) { + files = mojo.files; + } + for (String file : files) { + // check we have a the required/forbidden pattern + File f = new File(mojo.outJava, file.substring(0, file.length() - 4) + "java"); + if (mojo.isVerbose()) { + log.info("check generated file " + f); + } + + assertTrue("generated file " + f + " was not found...", f.exists()); + String content = FileUtils.readFileToString( 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 void assertNumberJaxxFiles(int expectedNbFiles) { + if (expectedNbFiles == 0) { + assertTrue(getMojo().files == null || getMojo().files.length == 0); + } else { + assertEquals(expectedNbFiles, getMojo().files.length); + } + } + + @SuppressWarnings("unchecked") + protected void assertError(JAXXEngine engine, String file, int nbCompiler) throws Exception { + + JAXXCompilerFile[] compilers = engine.getCompiledFiles(); + assertEquals(nbCompiler, compilers.length); + List<String> errors = engine.getErrors(); + assertTrue("should have found at least one error for " + file, errors != null && !errors.isEmpty()); + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/NodeItemTest.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/NodeItemTest.java new file mode 100644 index 0000000..5cad7a0 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/NodeItemTest.java @@ -0,0 +1,79 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jaxx.plugin; + +import org.junit.Assert; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author tchemit <chemit@codelutin.com> + */ +public class NodeItemTest { + + @Test + public void testFindChild() { + System.out.println("findChild"); + String path = "a"; + NodeItem instance = new NodeItem("a", "rootItem text"); + NodeItem expResult = new NodeItem("a", "rootItem text"); + NodeItem result = instance.findChild(path); + assertTocItemEquals(expResult, result); + + path = "a.b"; + expResult = new NodeItem("b", null); + result = instance.findChild(path); + assertTocItemEquals(expResult, result); + assertTrue(instance.getChild("b") == result); + assertTrue(instance.findChild("b") == result); + + NodeItem b = result; + + path = "ab"; + expResult = new NodeItem("ab", null); + result = instance.findChild(path); + assertTocItemEquals(expResult, result); + assertTrue(instance.getChild("ab") == result); + assertTrue(instance.findChild("ab") == result); + + path = "a.b.cd"; + expResult = new NodeItem("cd", null); + result = instance.findChild(path); + assertTocItemEquals(expResult, result); + assertTrue(b.getChild("cd") == result); + assertTrue(b.findChild("b.cd") == result); + assertTrue(b.findChild("cd") == result); + assertTrue(instance.findChild("b.cd") == result); + assertTrue(instance.findChild("a.b.cd") == result); + } + + protected void assertTocItemEquals(NodeItem t, NodeItem t2) { + Assert.assertEquals(t.getTarget(), t2.getTarget()); + Assert.assertEquals(t.getText(), t2.getText()); + + } +} diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerTest/classReferences/JavaTaist.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerTest/classReferences/JavaTaist.java new file mode 100644 index 0000000..e6fa9ba --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerTest/classReferences/JavaTaist.java @@ -0,0 +1,33 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin.compilerTest.classReferences; + +import javax.swing.*; + +public class JavaTaist extends JLabel { + public void setCustomProperty(String label) { + setText(label); + } +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Identity.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Identity.java new file mode 100644 index 0000000..bf43faf --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Identity.java @@ -0,0 +1,103 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin.compilerValidatorTest.validator.ok; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class Identity { + + protected String firstName = ""; + + protected String lastName = ""; + + protected String email = "dummy@codelutin.com"; + + protected int age = 51; + + + PropertyChangeSupport p; + + public Identity() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getEmail() { + return email; + } + + public int getAge() { + return age; + } + + public void setFirstName(String firstName) { + String oldFirstName = this.firstName; + this.firstName = firstName; + p.firePropertyChange("firstName", oldFirstName, firstName); + } + + public void setLastName(String lastName) { + String oldLastName = this.lastName; + this.lastName = lastName; + p.firePropertyChange("lastName", oldLastName, lastName); + } + + public void setEmail(String email) { + String oldEmail =this.email; + this.email = email; + p.firePropertyChange("email", oldEmail, email); + } + + public void setAge(int age) { + int oldAge = this.age; + this.age = age; + p.firePropertyChange("age", oldAge, age); + } +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Model.java b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Model.java new file mode 100644 index 0000000..3b0500b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/java/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Model.java @@ -0,0 +1,90 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin.compilerValidatorTest.validator.ok; + +import java.beans.*; + +public class Model { + + protected String text = "text"; + + protected String text2 = "text2"; + + protected int ratio = 51; + + + PropertyChangeSupport p; + + public Model() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + + public String getText() { + return text; + } + + public String getText2() { + return text2; + } + + public int getRatio() { + return ratio; + } + + public void setText(String text) { + String oldText = this.text; + this.text = text; + p.firePropertyChange("text", oldText, text); + } + + public void setText2(String text2) { + String oldText2 = this.text2; + this.text2 = text2; + p.firePropertyChange("text2", oldText2, text2); + } + + public void setRatio(int ratio) { + int oldRatio = this.ratio; + this.ratio = ratio; + p.firePropertyChange("ratio",oldRatio, ratio); + } +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/log4j.properties b/trunk/jaxx-maven-plugin/src/test/resources/log4j.properties new file mode 100644 index 0000000..cc35304 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/log4j.properties @@ -0,0 +1,35 @@ +### +# #%L +# JAXX :: Maven plugin +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +# 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.nuiton.plugin.AbstractMojoTest=INFO +log4j.logger.org.nuiton.jaxx=INFO +log4j.logger.jaxx.compiler=INFO +#log4j.logger.jaxx.compiler.binding=DEBUG diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Bug_1404.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Bug_1404.xml new file mode 100644 index 0000000..1a6c276 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Bug_1404.xml @@ -0,0 +1,53 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <i18nable>true</i18nable> + <force>true</force> + <!--<verbose>true</verbose>--> + <resetAfterCompile>false</resetAfterCompile> + <includes> + <value>**/bug1404Test/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Test1.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Test1.jaxx new file mode 100644 index 0000000..34c459c --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Test1.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + <TestParent> + <JLabel id='label' decorator='boxed'/> + </TestParent> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Test2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Test2.jaxx new file mode 100644 index 0000000..9fece16 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/Test2.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + <TestParent> + <JLabel id='icon' icon='myicon.png'/> + </TestParent> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/TestParent.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/TestParent.jaxx new file mode 100644 index 0000000..7276651 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1404Test/TestParent.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2011 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + <JPanel id='content'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/Bug_1722.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/Bug_1722.xml new file mode 100644 index 0000000..df1a512 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/Bug_1722.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <!--<verbose>true</verbose>--> + <includes> + <value>**/bug1722Test/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/DemoPanel.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/DemoPanel.jaxx new file mode 100644 index 0000000..e1824f5 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/DemoPanel.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JTabbedPane id='top'> + <tab title='Title'> + <JPanel id='demoPanel'> + <JLabel text='override'/> + </JPanel> + </tab> +</JTabbedPane> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/JButtonDemo.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/JButtonDemo.jaxx new file mode 100644 index 0000000..5e0fdf1 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1722Test/JButtonDemo.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<DemoPanel> + <JPanel id='demoPanel'> + <JLabel text='override'/> + </JPanel> +</DemoPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1750Test/Bug_1750.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1750Test/Bug_1750.xml new file mode 100644 index 0000000..20da642 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1750Test/Bug_1750.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <!--<verbose>true</verbose>--> + <resetAfterCompile>false</resetAfterCompile> + <includes> + <value>**/bug1750Test/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1750Test/ComboBox.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1750Test/ComboBox.jaxx new file mode 100644 index 0000000..a02f274 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1750Test/ComboBox.jaxx @@ -0,0 +1,42 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Table> + + <!-- selectedItem state --> + <Object id='selectedItem' javaBean=''/> + + <!-- check state --> + <Boolean id='check' constructorParams='false' javaBean=''/> + + <row> + <cell> + <JComboBox id='combobox' selectedItem='{getSelectedItem()}' + onItemStateChanged='setSelectedItem(combobox.getSelectedItem())'/> + </cell> + <cell> + <JCheckBox id='checkbox' selected='{isCheck()}' onActionPerformed='setCheck(checkbox.isSelected())'/> + </cell> + </row> +</Table> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Bug_1751.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Bug_1751.xml new file mode 100644 index 0000000..48e1975 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Bug_1751.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <i18nable>true</i18nable> + <force>true</force> + <!--<verbose>true</verbose>--> + <resetAfterCompile>false</resetAfterCompile> + <includes> + <value>**/bug1751Test/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test1.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test1.jaxx new file mode 100644 index 0000000..99e379b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test1.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JLabel implements="java.io.Serializable" text='test'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test2.jaxx new file mode 100644 index 0000000..e04d8e8 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test2.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JLabel text='test' implements="java.io.Serializable"/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test3.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test3.jaxx new file mode 100644 index 0000000..99e379b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug1751Test/Test3.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JLabel implements="java.io.Serializable" text='test'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug184Test/Bug_184.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug184Test/Bug_184.xml new file mode 100644 index 0000000..79e7256 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug184Test/Bug_184.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <force>true</force> + <verbose>true</verbose> + <includes> + <value>**/bug184Test/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug184Test/MyPanel.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug184Test/MyPanel.jaxx new file mode 100644 index 0000000..e1b0ec0 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/bug184Test/MyPanel.jaxx @@ -0,0 +1,37 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + +<script> + +private static final int[] yo = new int[]{65,66,67}; + +protected String myMethod(String a, String b, String c) { + return ""; +} + +</script> + <JButton constructorParams='myMethod("a", new String(yo, 1, 2), "c")'/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/CSSTests.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/CSSTests.xml new file mode 100644 index 0000000..492f951 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/CSSTests.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <i18nable>false</i18nable> + <verbose>true</verbose> + <includes> + <value>**/compilerTest/cSSTests/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ClassReferences.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ClassReferences.xml new file mode 100644 index 0000000..02bc96e --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ClassReferences.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/classReferences/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ClientProperty.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ClientProperty.xml new file mode 100644 index 0000000..05997ef --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ClientProperty.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <addLogger>false</addLogger> + <includes> + <value>**/compilerTest/clientProperty/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ErrorJaxxContextImplementorClass.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ErrorJaxxContextImplementorClass.xml new file mode 100644 index 0000000..8949a1d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ErrorJaxxContextImplementorClass.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <jaxxContextFQN>java.lang.String</jaxxContextFQN> + <force>true</force> + <includes> + <value>**/evolution74Test/ok/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Errors.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Errors.xml new file mode 100644 index 0000000..f598443 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Errors.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <autoRecurseInCss>true</autoRecurseInCss> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/errors/*.jaxx</value> + </includes> + <excludes> + <value>**/compilerTest/validator/errors/*.jaxx</value> + </excludes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ErrorsCss.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ErrorsCss.xml new file mode 100644 index 0000000..61c2da1 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ErrorsCss.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <autoRecurseInCss>false</autoRecurseInCss> + <force>true</force> + <includes> + <value>**/compilerTest/errors/css/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Force.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Force.xml new file mode 100644 index 0000000..799847b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Force.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/force/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Icon.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Icon.xml new file mode 100644 index 0000000..4f565e5 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Icon.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <i18nable>false</i18nable> + <force>true</force> + <!--<verbose>true</verbose>--> + <resetAfterCompile>true</resetAfterCompile> + <includes> + <value>**/compilerTest/icon/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ImportTag.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ImportTag.xml new file mode 100644 index 0000000..59ce1cb --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/ImportTag.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <force>true</force> + <includes> + <value>**/compilerTest/importTag/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Initializers.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Initializers.xml new file mode 100644 index 0000000..2fa285b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Initializers.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/initializers/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/InnerClasses.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/InnerClasses.xml new file mode 100644 index 0000000..371b156 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/InnerClasses.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/innerClasses/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/NoLog.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/NoLog.xml new file mode 100644 index 0000000..1ea1bd7 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/NoLog.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <addLogger>false</addLogger> + <includes> + <value>**/compilerTest/log/nolog/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/OverridingDataBindings.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/OverridingDataBindings.xml new file mode 100644 index 0000000..d0150c1 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/OverridingDataBindings.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/overridingDataBindings/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Script.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Script.xml new file mode 100644 index 0000000..efc7416 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/Script.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/script/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/SpecialSubclassing.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/SpecialSubclassing.xml new file mode 100644 index 0000000..2cb8bcc --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/SpecialSubclassing.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/compilerTest/specialSubclassing/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/WithLog.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/WithLog.xml new file mode 100644 index 0000000..fad6973 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/WithLog.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <addLogger>true</addLogger> + <includes> + <value>**/compilerTest/log/withlog/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/CSSTests.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/CSSTests.jaxx new file mode 100644 index 0000000..a01422f --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/CSSTests.jaxx @@ -0,0 +1,48 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application title='CSSTests'> + <style> + Application { lookAndFeel: {String.valueOf(lookAndFeel.getSelectedValue())}; } + </style> + + <JMenuBar> + <JMenu text='View'> + <JMenu text='Look and Feel'> + <JRadioButtonMenuItem text='Ocean' value='cross_platform' buttonGroup='lookAndFeel' selected='true'/> + <JRadioButtonMenuItem text='System' value='system' buttonGroup='lookAndFeel'/> + </JMenu> + </JMenu> + </JMenuBar> + + <JTabbedPane> + <tab title='Simple Tests'> + <SimpleCSS/> + </tab> + + <tab title='Pseudoclasses'> + <Pseudoclasses/> + </tab> + </JTabbedPane> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Child.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Child.jaxx new file mode 100644 index 0000000..9557c38 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Child.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton styleClass='yellow' id='child'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Child2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Child2.jaxx new file mode 100644 index 0000000..5cdb641 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Child2.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton foreground='#ffcccc'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/GrandChild.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/GrandChild.jaxx new file mode 100644 index 0000000..2a79897 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/GrandChild.jaxx @@ -0,0 +1,55 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new BorderLayout()}'> + <import> + java.awt.Color + </import> + <script> + public String getText() { + return grandChild.getText(); + } + + + public void setText(String Text) { + grandChild.setText(Text); + } + + + public Color getForeground() { + if (grandChild != null) + return grandChild.getForeground(); + else + return Color.BLACK; + } + + + public void setForeground(Color foreground) { + if (grandChild != null) + grandChild.setForeground(foreground); + } + </script> + + <GrandChildButton id='grandChild'/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/GrandChildButton.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/GrandChildButton.jaxx new file mode 100644 index 0000000..8186c70 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/GrandChildButton.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Pseudoclasses.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Pseudoclasses.jaxx new file mode 100644 index 0000000..001ab33 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/Pseudoclasses.jaxx @@ -0,0 +1,123 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new GridLayout(0, 2, 6, 6)}'> + <!-- each checkbox has both its own test and all of the ones that came before in order + to make sure that all of the pseudoclass overrides works properly - only the last + pair should have any effect --> + <style> + #test1:enabled { text: "Enabled"; } + #test1:disabled { text: "Disabled"; } + + #test2:enabled { text: "Enabled"; } + #test2:disabled { text: "Disabled"; } + #test2:focused { text: "Focused"; } + #test2:unfocused { text: "Unfocused"; } + + #test3:enabled { text: "Enabled"; } + #test3:disabled { text: "Disabled"; } + #test3:focused { text: "Focused"; } + #test3:unfocused { text: "Unfocused"; } + #test3:selected { text: "Selected"; } + #test3:deselected { text: "Deselected"; } + + #test4:enabled { text: "Enabled"; } + #test4:disabled { text: "Disabled"; } + #test4:focused { text: "Focused"; } + #test4:unfocused { text: "Unfocused"; } + #test4:selected { text: "Selected"; } + #test4:deselected { text: "Deselected"; } + #test4:mouseover { text: "Mouseover"; } + #test4:mouseout { text: "Mouseout"; } + + #test5:enabled { text: "Enabled"; } + #test5:disabled { text: "Disabled"; } + #test5:focused { text: "Focused"; } + #test5:unfocused { text: "Unfocused"; } + #test5:selected { text: "Selected"; } + #test5:deselected { text: "Deselected"; } + #test5:mouseover { text: "Mouseover"; } + #test5:mouseout { text: "Mouseout"; } + #test5:mousedown { text: "Mousedown"; } + #test5:mouseup { text: "Mouseup"; } + + #test6:{object.isSelected()} { text: "Selected"; } + + #test7:selected { text: { "you shouldn't see this".toUpperCase() } } + #test7:selected { text: { currentTime }; } + + #test8:mouseover { text: { test8Field.getText() }; } + </style> + + <script> + import java.text.*; + import javax.swing.Timer; + + DateFormat dateFormat = DateFormat.getTimeInstance(); + String currentTime = dateFormat.format(new Date()); + + Timer timer = new Timer(1000, new ActionListener() { + public void actionPerformed(ActionEvent e) { + currentTime = dateFormat.format(new Date()); + } + }); + + timer.start(); + </script> + + <JPanel border='{BorderFactory.createTitledBorder("Enabled/Disabled")}'> + <JCheckBox text="You shouldn't see this" enabled='{enabledCB.isSelected()}' id='test1'/> + </JPanel> + + <JPanel border='{BorderFactory.createTitledBorder("Focused/Unfocused")}'> + <JCheckBox text="You shouldn't see this" enabled='{enabledCB.isSelected()}' id='test2'/> + </JPanel> + + <JPanel border='{BorderFactory.createTitledBorder("Selected/Deselected")}'> + <JCheckBox text="You shouldn't see this" enabled='{enabledCB.isSelected()}' id='test3'/> + </JPanel> + + <JPanel border='{BorderFactory.createTitledBorder("Mouseover/Mouseout")}'> + <JCheckBox text="You shouldn't see this" enabled='{enabledCB.isSelected()}' id='test4'/> + </JPanel> + + <JPanel border='{BorderFactory.createTitledBorder("Mouseup/Mousedown")}'> + <JCheckBox text="You shouldn't see this" enabled='{enabledCB.isSelected()}' id='test5'/> + </JPanel> + + <JPanel border='{BorderFactory.createTitledBorder("Programmatic Selected")}'> + <JCheckBox text='Unselected' enabled='{enabledCB.isSelected()}' id='test6'/> + </JPanel> + + <JPanel border='{BorderFactory.createTitledBorder("Pseudoclass Data Binding")}'> + <JCheckBox text='Select to see current time' enabled='{enabledCB.isSelected()}' id='test7'/> + </JPanel> + + <VBox border='{BorderFactory.createTitledBorder("Pseudoclass Proxy Data Binding")}'> + <JCheckBox text='Mouse over to see the below text' enabled='{enabledCB.isSelected()}' id='test8'/> + <JTextField id='test8Field'/> + </VBox> + + <JCheckBox text='Enable checkboxes' id='enabledCB' selected='true'/> +</JPanel> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/SimpleCSS.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/SimpleCSS.jaxx new file mode 100644 index 0000000..38902dd --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/cSSTests/SimpleCSS.jaxx @@ -0,0 +1,56 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<VBox> + <JPanel layout='{new GridLayout(0, 1, 6, 6)}'> + <import> + java.awt.Color + </import> + <style> + JPanel { border: {null}; font-size: 18; } + + JButton { foreground: red } + JButton.green { foreground: green; } + AbstractButton.blue { foreground: blue } + .blue { foreground: white; } + #B4:enabled { foreground: { Color.orange } } + .yellow { foreground: yellow; } + #child.idTest { foreground: white } + #B7:{true} { foreground: cyan; } + #B8 { foreground: black } + #B8.yellow { foreground: { new Color(0, 0, 0) } } + </style> + + <JButton id='B1' text='Red'/> + <JButton id='B2' text='Green' styleClass='green'/> + <JButton id='B3' text='Blue' styleClass='blue'/> + <GrandChild id='B4' text='Orange'/> + <Child id='B5' text='Yellow'/> + <Child id='B6' text='White' styleClass='idTest'/> + <Child id='B7' text='Cyan'/> + <Child2 id='B8' text='Pink' styleClass='yellow'/> + <Child2 id='B9' text='Purple' foreground='#aa20ff'/> + <GrandChild text='Red'/> + </JPanel> +</VBox> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/ClassReferences.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/ClassReferences.jaxx new file mode 100644 index 0000000..19dd574 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/ClassReferences.jaxx @@ -0,0 +1,42 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<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 diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/ConstructorReferenceTest.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/ConstructorReferenceTest.jaxx new file mode 100644 index 0000000..3dda1af --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/ConstructorReferenceTest.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Object> + <script> + public String toString() { + return "Constructor reference worked"; + } + </script> +</Object> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/JAXXReferenceTest.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/JAXXReferenceTest.jaxx new file mode 100644 index 0000000..1995193 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/JAXXReferenceTest.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JLabel> + <script> + public void setCustomProperty(String label) { + setText(label); + } + </script> +</JLabel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/JAXXTest.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/JAXXTest.jaxx new file mode 100644 index 0000000..1995193 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/JAXXTest.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JLabel> + <script> + public void setCustomProperty(String label) { + setText(label); + } + </script> +</JLabel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/StaticMethodTest.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/StaticMethodTest.jaxx new file mode 100644 index 0000000..438daaf --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/StaticMethodTest.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Object> + <script> + public static String getText() { + return "Static method reference worked"; + } + </script> +</Object> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/TypeReference.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/TypeReference.jaxx new file mode 100644 index 0000000..2ead14c --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/classReferences/TypeReference.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Object/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/clientProperty/TestOne.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/clientProperty/TestOne.jaxx new file mode 100644 index 0000000..9fb34aa --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/clientProperty/TestOne.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel id='root'> + <JButton id='boxedButton' _testOne='"oneTest"' _testTwo='{"anotherTest"}'/> +</JPanel> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/AmbiguousName.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/AmbiguousName.jaxx new file mode 100644 index 0000000..7989118 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/AmbiguousName.jaxx @@ -0,0 +1,34 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <script> + import java.awt.*; + import java.sql.*; + import java.util.*; + </script> + + <List/> + <Date/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/BadTypeConversions.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/BadTypeConversions.jaxx new file mode 100644 index 0000000..bddf00f --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/BadTypeConversions.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton opaque='yellow' + margin='42, 1, 7' + mnemonic='AX' + border='true'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/CellOutsideOfRow.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/CellOutsideOfRow.jaxx new file mode 100644 index 0000000..2861111 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/CellOutsideOfRow.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <cell><JButton/></cell> + + <cell><JLabel/></cell> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ChildrenInNonContainer.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ChildrenInNonContainer.jaxx new file mode 100644 index 0000000..ae34d02 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ChildrenInNonContainer.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton> + <JPanel/> + <JMenuBar/> +</JButton> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ClassNotFound.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ClassNotFound.jaxx new file mode 100644 index 0000000..3fb7139 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ClassNotFound.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Frame> + <Glob/> +</Frame> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ConflictingPackages.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ConflictingPackages.jaxx new file mode 100644 index 0000000..e60671f --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ConflictingPackages.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<awt:javax.swing.JFrame xmlns:awt='java.awt.*'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ConstraintsParseError.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ConstraintsParseError.jaxx new file mode 100644 index 0000000..683902d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ConstraintsParseError.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <JLabel constraints='BorderLayout*%NORTH'/> + <JButton constraints='BorderLayout.SOUTH'/> + <JTabbedPane constraints='BorderLayout(CENTER'/> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/DataBindingParseError.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/DataBindingParseError.jaxx new file mode 100644 index 0000000..78d59e4 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/DataBindingParseError.jaxx @@ -0,0 +1,30 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <JButton text='{"Missing right brace"'/> + <JLabel text='{Math.PI + Math.E ~= Math.PIE}'/> + <JToolBar visible='{I like pie}'/> + <JButton text='{"This should compile"}}'/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/DuplicateIDs.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/DuplicateIDs.jaxx new file mode 100644 index 0000000..aaac790 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/DuplicateIDs.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel id='duplicate'> + <JPanel id='duplicate'/> + <JColorChooser id='duplicate'/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/EventHandlerParseError.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/EventHandlerParseError.jaxx new file mode 100644 index 0000000..905ca50 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/EventHandlerParseError.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <JButton onActionPerformed='!*'/> + <JPanel onMouseEntered='{System.out.println("Remember kids, only use curly braces where appropriate!")}'/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidID.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidID.jaxx new file mode 100644 index 0000000..f8529e7 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidID.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application id='1'> + <JButton id='Hello-'/> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidRootTag.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidRootTag.jaxx new file mode 100644 index 0000000..51fa3fe --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidRootTag.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<style source='test.css'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidXML.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidXML.jaxx new file mode 100644 index 0000000..8b1d941 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/InvalidXML.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<begin> + <valid/> + <so.is.this/> +</end> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ItemDuplicateValues.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ItemDuplicateValues.jaxx new file mode 100644 index 0000000..709a0a1 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ItemDuplicateValues.jaxx @@ -0,0 +1,32 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXList> + <item value='1'/> + <item value='2'/> + <item value='2'/> + <item value='3'/> + <item value='3'/> + <item value='3'/> +</JAXXList> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ItemNoValue.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ItemNoValue.jaxx new file mode 100644 index 0000000..34bd4ce --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ItemNoValue.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXList> + <item label='This item doesn&t have a value'/> + <item label='Neither does this one'/> +</JAXXList> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/MixedContent.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/MixedContent.jaxx new file mode 100644 index 0000000..2a3770a --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/MixedContent.jaxx @@ -0,0 +1,43 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + mixed1 + + <Table> + <row> + mixed2 + + <cell>mixed3</cell> + </row> + </Table> + + <JList> + <item>mixed4</item> + </JList> + + <JTabbedPane> + <tab>mixed5</tab> + </JTabbedPane> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/RowOutsideOfTable.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/RowOutsideOfTable.jaxx new file mode 100644 index 0000000..f03ca8b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/RowOutsideOfTable.jaxx @@ -0,0 +1,33 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <row> + <cell><JButton/></cell> + </row> + + <row> + <cell><JLabel/></cell> + </row> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/RowWrongChild.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/RowWrongChild.jaxx new file mode 100644 index 0000000..5b02b64 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/RowWrongChild.jaxx @@ -0,0 +1,33 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Table> + <row> + <JPanel/> + </row> + + <row> + <JScrollPane/> + </row> +</Table> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptNotFound.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptNotFound.jaxx new file mode 100644 index 0000000..8b04e60 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptNotFound.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<script source='notfound.script'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptParseError.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptParseError.jaxx new file mode 100644 index 0000000..7c7429d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptParseError.jaxx @@ -0,0 +1,30 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JFileChooser> + <script> + System.err.println("this is a valid line"); + System.err.println("this is an unclosed string literal); + </script> +</JFileChooser> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptSourceAndInline.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptSourceAndInline.jaxx new file mode 100644 index 0000000..57afa11 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/ScriptSourceAndInline.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<script source='dependencies/test.script'> + System.err.println("This should not compile"); +</script> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleNotFound.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleNotFound.jaxx new file mode 100644 index 0000000..cbdff96 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleNotFound.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<style source='notfound.css'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleParseError.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleParseError.jaxx new file mode 100644 index 0000000..b30e897 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleParseError.jaxx @@ -0,0 +1,33 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JFileChooser> + <style> + JButton { + foreground: blue; + label: "Parse error on next line"; + *: false; + } + </style> +</JFileChooser> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleSourceAndInline.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleSourceAndInline.jaxx new file mode 100644 index 0000000..f3d58bb --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/StyleSourceAndInline.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<style source='dependencies/test.css'> + JLabel { text: "this should not compile" } +</style> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TabOutsideOfTabbedPane.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TabOutsideOfTabbedPane.jaxx new file mode 100644 index 0000000..f2655a5 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TabOutsideOfTabbedPane.jaxx @@ -0,0 +1,33 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <tab> + <JButton/> + </tab> + + <tab> + <JLabel/> + </tab> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TabbedPaneWrongChild.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TabbedPaneWrongChild.jaxx new file mode 100644 index 0000000..027d605 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TabbedPaneWrongChild.jaxx @@ -0,0 +1,30 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <JTabbedPane> + <JPanel/> + <JScrollPane/> + </JTabbedPane> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TableWrongChild.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TableWrongChild.jaxx new file mode 100644 index 0000000..a37bfa5 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TableWrongChild.jaxx @@ -0,0 +1,30 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <Table> + <JPanel/> + <JScrollPane/> + </Table> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyCellChildren.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyCellChildren.jaxx new file mode 100644 index 0000000..daa0404 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyCellChildren.jaxx @@ -0,0 +1,39 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <Table> + <row> + <cell> + <JButton/> + <JButton/> + </cell> + + <cell> + <JPanel/> + <JToolBar/> + </cell> + </row> + </Table> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyScrollPaneChildren.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyScrollPaneChildren.jaxx new file mode 100644 index 0000000..49a9773 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyScrollPaneChildren.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JScrollPane> + <JButton/> + <JToolBar/> + <JPanel/> +</JScrollPane> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManySplitPaneChildren.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManySplitPaneChildren.jaxx new file mode 100644 index 0000000..1c4cf8f --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManySplitPaneChildren.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <JSplitPane> + <JButton text='one'/> + <JButton text='two'/> + <JButton text='three'/> + </JSplitPane> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyTabChildren.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyTabChildren.jaxx new file mode 100644 index 0000000..9a8e455 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/TooManyTabChildren.jaxx @@ -0,0 +1,37 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <JTabbedPane> + <tab> + <JButton/> + <JButton/> + </tab> + + <tab> + <JPanel/> + <JToolBar/> + </tab> + </JTabbedPane> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/UnsupportedAttribute.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/UnsupportedAttribute.jaxx new file mode 100644 index 0000000..9e4237f --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/UnsupportedAttribute.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel widgetCount='7'> + <JLabel mnemonic='A'/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/UnsupportedEvent.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/UnsupportedEvent.jaxx new file mode 100644 index 0000000..c7d69d4 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/UnsupportedEvent.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel onWink='7'> + <JLabel onWonLottery='A'/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/css/UnsupportedPseudoclass.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/css/UnsupportedPseudoclass.jaxx new file mode 100644 index 0000000..bf3cfdb --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/css/UnsupportedPseudoclass.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton> + <style> + :opaque { enabled: false; } + </style> +</JButton> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/dependencies/test.css b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/dependencies/test.css new file mode 100644 index 0000000..0232125 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/dependencies/test.css @@ -0,0 +1,25 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +JLabel { text: "This should not compile" } \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/dependencies/test.script b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/dependencies/test.script new file mode 100644 index 0000000..6b1b25c --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/errors/dependencies/test.script @@ -0,0 +1 @@ +System.err.println("This should not compile."); \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/force/JButton.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/force/JButton.jaxx new file mode 100644 index 0000000..0dc1d27 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/force/JButton.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<javax.swing.JButton id='testId' text='test.text'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/icon/Test1.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/icon/Test1.jaxx new file mode 100644 index 0000000..abdef92 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/icon/Test1.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <JLabel icon='myIcon.png'/> + <JLabel actionIcon='myActionIcon.png'/> +</JPanel> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/importTag/ImportTag.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/importTag/ImportTag.jaxx new file mode 100644 index 0000000..ea67649 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/importTag/ImportTag.jaxx @@ -0,0 +1,32 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + + <import> + java.io.File + </import> + + <File id="file"/> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/initializers/Initializers.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/initializers/Initializers.jaxx new file mode 100644 index 0000000..99b9689 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/initializers/Initializers.jaxx @@ -0,0 +1,61 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <script> + private static String staticInitializerText = "Static initializer FAILED"; + + static { + staticInitializerText = "Static initializer worked!"; + } + + { initializerTest.setText("Initializer worked!"); } + + public Initializers(String label) { + this(1, "Custom constructor test 2 worked!"); + constructorTest1.setText(label); + } + + + public Initializers(int dummy, String label) { + super("Test 3 worked! "+dummy); + constructorTest2.setText(label); + } + + + public static void main(String[] arg) { // test custom main method + Initializers test = new Initializers("Custom constructor test 1 worked!"); + test.mainTest.setText("Custom main method worked!"); + test.setVisible(true); + } + </script> + + <VBox> + <JLabel id='mainTest' text='Custom main method FAILED'/> + <JLabel id='constructorTest1' text='Custom constructor TEST 1 FAILED'/> + <JLabel id='constructorTest2' text='Custom constructor TEST 2 FAILED'/> + <JLabel id='initializerTest' text='Initializer FAILED'/> + <JLabel id='staticInitializerTest' text='{Initializers.staticInitializerText}'/> + </VBox> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/innerClasses/InnerClasses.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/innerClasses/InnerClasses.jaxx new file mode 100644 index 0000000..44452c3 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/innerClasses/InnerClasses.jaxx @@ -0,0 +1,41 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <JMenuBar> + <JMenu text='Test'> + <JMenuItem text='1'/> + <JPopupMenu.Separator/> + <JMenuItem text='2'/> + <javax.swing.JPopupMenu.Separator/> + <JMenuItem text='3'/> + <JPopupMenu.Separator xmlns="javax.swing.*"/> + <JMenuItem text='4'/> + <swing:JPopupMenu.Separator xmlns:swing="javax.swing.*"/> + <JMenuItem text='5'/> + <swing:javax.swing.JPopupMenu.Separator xmlns:swing="javax.swing.*"/> + <JMenuItem text='6'/> + </JMenu> + </JMenuBar> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/nolog/NoLog.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/nolog/NoLog.jaxx new file mode 100644 index 0000000..7fb5ddb --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/nolog/NoLog.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton id='testId' text='test.text'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/nolog/NoLogSon.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/nolog/NoLogSon.jaxx new file mode 100644 index 0000000..68779f2 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/nolog/NoLogSon.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<NoLog id='testId' text='test.text'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/withlog/WithLog.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/withlog/WithLog.jaxx new file mode 100644 index 0000000..7fb5ddb --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/withlog/WithLog.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JButton id='testId' text='test.text'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/withlog/WithLogTwo.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/withlog/WithLogTwo.jaxx new file mode 100644 index 0000000..9c14200 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/log/withlog/WithLogTwo.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<WithLog id='testId' text='test.text'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/CurrentTime.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/CurrentTime.jaxx new file mode 100644 index 0000000..c3b9616 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/CurrentTime.jaxx @@ -0,0 +1,41 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JLabel text='{currentTime}' foreground='blue'> + <script> + import java.text.*; + import javax.swing.Timer; + + DateFormat dateFormat = DateFormat.getTimeInstance(); + String currentTime = dateFormat.format(new Date()); + + Timer timer = new Timer(1000, new ActionListener() { + public void actionPerformed(ActionEvent e) { + currentTime = dateFormat.format(new Date()); + } + }); + + timer.start(); + </script> +</JLabel> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/OverriddenCurrentTime.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/OverriddenCurrentTime.jaxx new file mode 100644 index 0000000..4689faa --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/OverriddenCurrentTime.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<CurrentTime text='Parent Working'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/OverridingDataBindings.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/OverridingDataBindings.jaxx new file mode 100644 index 0000000..887d5a3 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/overridingDataBindings/OverridingDataBindings.jaxx @@ -0,0 +1,36 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <VBox> + <JLabel text='The text below should display the time'/> + <CurrentTime/> + + <JLabel text='The text below should read "Child Working"'/> + <CurrentTime text='Child Working'/> + + <JLabel text='The text below should read "Parent Working"'/> + <OverriddenCurrentTime/> + </VBox> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/script/JScriptInitializer.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/script/JScriptInitializer.jaxx new file mode 100644 index 0000000..f1a152b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/script/JScriptInitializer.jaxx @@ -0,0 +1,43 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JDialog> + <script> + protected boolean value + </script> + <script> + value=false + </script> + + <script> + value=getOk(); + + public boolean getOk() { + return true; + } + </script> + <VBox> + <JButton text='close' onActionPerformed="dispose()"/> + </VBox> +</JDialog> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JComboBoxTest1.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JComboBoxTest1.jaxx new file mode 100644 index 0000000..8d2b0af --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JComboBoxTest1.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXComboBox> + <item value='Working' selected='true'/> +</JAXXComboBox> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JComboBoxTest2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JComboBoxTest2.jaxx new file mode 100644 index 0000000..3cc6c6a --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JComboBoxTest2.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXComboBox> + <item value='Failed!'/> +</JAXXComboBox> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JListTest1.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JListTest1.jaxx new file mode 100644 index 0000000..967020a --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JListTest1.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXList> + <item value='Working' selected='true'/> +</JAXXList> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JListTest2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JListTest2.jaxx new file mode 100644 index 0000000..4dda453 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JListTest2.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXList> + <item value='Failed!'/> +</JAXXList> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JTreeTest1.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JTreeTest1.jaxx new file mode 100644 index 0000000..8e81b40 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JTreeTest1.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXTree> + <item value='Working' selected='true'/> +</JAXXTree> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JTreeTest2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JTreeTest2.jaxx new file mode 100644 index 0000000..70a2fc7 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/JTreeTest2.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JAXXTree> + <item value='Failed!'/> +</JAXXTree> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/SpecialSubclassing.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/SpecialSubclassing.jaxx new file mode 100644 index 0000000..b0a8f1d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerTest/specialSubclassing/SpecialSubclassing.jaxx @@ -0,0 +1,50 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application title='Special Subclassing'> + <VBox> + <JComboBoxTest1/> + <JComboBoxTest2> + <item value='Working' selected='true'/> + </JComboBoxTest2> + + <JScrollPane> + <JListTest1/> + </JScrollPane> + <JScrollPane> + <JListTest2> + <item value='Working' selected='true'/> + </JListTest2> + </JScrollPane> + + <JScrollPane width='80' height='80'> + <JTreeTest1/> + </JScrollPane> + <JScrollPane width='80' height='80'> + <JTreeTest2> + <item value='Working' selected='true'/> + </JTreeTest2> + </JScrollPane> + </VBox> +</Application> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/ValidatorErrors.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/ValidatorErrors.xml new file mode 100644 index 0000000..4133cfe --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/ValidatorErrors.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <!--<verbose>true</verbose>--> + <includes> + <value>**/compilerValidatorTest/validator/errors/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/ValidatorOk.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/ValidatorOk.xml new file mode 100644 index 0000000..2d909b4 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/ValidatorOk.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <!--<verbose>true</verbose>--> + <includes> + <value>**/compilerValidatorTest/validator/ok/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/AutoFieldComponentNotFound.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/AutoFieldComponentNotFound.jaxx new file mode 100644 index 0000000..55f2439 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/AutoFieldComponentNotFound.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model" autoField='true' strictMode='true'/> + <JTextField id='text'/> + <JTextField id='text2'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedBean.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedBean.jaxx new file mode 100644 index 0000000..140d56b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedBean.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator bean='model' errorListModel='errors' bean='yo'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedBean2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedBean2.jaxx new file mode 100644 index 0000000..0b4484f --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedBean2.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <Model id='model'/> + <BeanValidator bean='model'/> + <BeanValidator bean='model'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedErrorListModel.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedErrorListModel.jaxx new file mode 100644 index 0000000..0958319 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedErrorListModel.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <jaxx.runtime.validator.swing.SwingValidatorMessageListModel id='errors'/> + <BeanValidator beanClass='org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model' errorListModel='errors' errorListModel='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedErrorTableModel.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedErrorTableModel.jaxx new file mode 100644 index 0000000..e885816 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedErrorTableModel.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <jaxx.runtime.validator.swing.SwingValidatorMessageListModel id='errors'/> + <BeanValidator beanClass='org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model' errorTableModel='errors' errorTableModel='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedFieldInSameValidator.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedFieldInSameValidator.jaxx new file mode 100644 index 0000000..1bc581f --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/DuplicatedFieldInSameValidator.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model"> + <field name="text"/> + <field name="text"/> + </BeanValidator> + <JTextField id='text'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldBeanPropertyNotFound.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldBeanPropertyNotFound.jaxx new file mode 100644 index 0000000..56e5291 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldBeanPropertyNotFound.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model"> + <field name="fake"/> + </BeanValidator> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentDuplicated.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentDuplicated.jaxx new file mode 100644 index 0000000..a4b4c2d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentDuplicated.jaxx @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model"> + <field name="text2" component="text"/> + <field name="text" component="text"/> + </BeanValidator> + <JTextField id='text'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentNotFound.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentNotFound.jaxx new file mode 100644 index 0000000..63b9d4a --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentNotFound.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model"> + <field name="text" component="fake"/> + </BeanValidator> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentNotFound2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentNotFound2.jaxx new file mode 100644 index 0000000..56e5291 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldComponentNotFound2.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model"> + <field name="fake"/> + </BeanValidator> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldNoName.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldNoName.jaxx new file mode 100644 index 0000000..b5d014e --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldNoName.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model"> + <field/> + </BeanValidator> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldNoName2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldNoName2.jaxx new file mode 100644 index 0000000..1836d34 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/FieldNoName2.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass="org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model"> + <field component="text"/> + </BeanValidator> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/Model.java b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/Model.java new file mode 100644 index 0000000..e1a9448 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/Model.java @@ -0,0 +1,90 @@ +/* + * #%L + * JAXX :: Maven plugin + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors; + +import java.beans.*; + +public class Model { + + protected String text = "text"; + + protected String text2 = "text2"; + + protected int ratio = 51; + + + PropertyChangeSupport p; + + public Model() { + p = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + p.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + p.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + p.removePropertyChangeListener(propertyName, listener); + } + + + public String getText() { + return text; + } + + public String getText2() { + return text2; + } + + public int getRatio() { + return ratio; + } + + public void setText(String text) { + String oldText = this.text; + this.text = text; + p.firePropertyChange("text", oldText, text); + } + + public void setText2(String text2) { + String oldText2 = this.text2; + this.text2 = text2; + p.firePropertyChange("text2", oldText2, text2); + } + + public void setRatio(int ratio) { + int oldRatio = this.ratio; + this.ratio = ratio; + p.firePropertyChange("ratio",oldRatio, ratio); + } +} \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/NoBean.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/NoBean.jaxx new file mode 100644 index 0000000..4dc5b81 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/NoBean.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + + <BeanValidator id='validator'/> + +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundBean.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundBean.jaxx new file mode 100644 index 0000000..7a091ba --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundBean.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator bean='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorList.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorList.jaxx new file mode 100644 index 0000000..7e0ba95 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorList.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass='org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model' errorList='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorListModel.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorListModel.jaxx new file mode 100644 index 0000000..099f762 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorListModel.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass='org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model' errorListModel='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorTable.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorTable.jaxx new file mode 100644 index 0000000..cc43718 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorTable.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass='org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model' errorTable='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorTableModel.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorTableModel.jaxx new file mode 100644 index 0000000..436b12e --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundErrorTableModel.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator bean='org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model' errorTableModel='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundParentValidator.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundParentValidator.jaxx new file mode 100644 index 0000000..b4069a0 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/errors/UnfoundParentValidator.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application> + <BeanValidator beanClass='org.nuiton.jaxx.plugin.compilerValidatorTest.validator.errors.Model' parentValidator='fake'/> +</Application> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Validation.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Validation.jaxx new file mode 100644 index 0000000..2f51fe1 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/Validation.jaxx @@ -0,0 +1,298 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application title="Validation.jaxx"> + + <!-- models --> + <Model id='model'/> + <Model id='model2'/> + <Identity id='identity'/> + + <!-- errors model --> + <jaxx.runtime.validator.swing.SwingValidatorMessageListModel id='errors' + onContentsChanged='ok.setEnabled(errors.isEmpty())'/> + + <!-- 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.swing.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.swing.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> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/ValidationBeanClass.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/ValidationBeanClass.jaxx new file mode 100644 index 0000000..898fd30 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/compilerValidatorTest/validator/ok/ValidationBeanClass.jaxx @@ -0,0 +1,136 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Application title="Validation.jaxx"> + + <!-- models --> + <Identity id='identity'/> + + <!-- errors model --> + <jaxx.runtime.validator.swing.SwingValidatorMessageListModel id='errors'/> + + <!-- validators --> + <BeanValidator id='validator3' autoField='true' beanClass='org.nuiton.jaxx.plugin.compilerValidatorTest.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> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/dataBindingTest/First.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/dataBindingTest/First.jaxx new file mode 100644 index 0000000..262b800 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/dataBindingTest/First.jaxx @@ -0,0 +1,48 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel> + + <java.io.File id='file' constructorParams='""'/> + <java.io.File id='file2' javaBean='new File("")'/> + + <org.nuiton.jaxx.plugin.DataBinding.Bean id='bean' javaBean='new org.nuiton.jaxx.plugin.DataBinding.BeanImpl()'/> + <org.nuiton.jaxx.plugin.DataBinding.BeanImpl id='beanImpl' javaBean='new org.nuiton.jaxx.plugin.DataBinding.BeanImpl()'/> + + <JLabel id='nobinding1' text='{file.getAbsolutePath()}'/> + <JLabel id='nobinding2' text='{getFile().getAbsolutePath()}'/> + + <JLabel id='binding0' text='{file2.getAbsolutePath()}' javaBean='new JLabel()'/> + <JLabel id='binding1' text='{this.getFile2().getAbsolutePath()}'/> + <JLabel id='binding2' text='{getFile2().getAbsolutePath()}'/> + <JLabel id='binding3' text='{bean.getText()}'/> + <JLabel id='binding4' text='{getBean().getText()}'/> + <JLabel id='binding5' text='{beanImpl.getText()}'/> + <JLabel id='binding6' text='{getBeanImpl().getText()}'/> + <JLabel id='binding7' text='{binding0.getText()}'/> + <JLabel id='binding8' text='{getBinding0().getText()}'/> + <JLabel id='binding9' text='{binding0.getText() + binding1.getText()}'/> + +</JPanel> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/dataBindingTest/simpleBinding.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/dataBindingTest/simpleBinding.xml new file mode 100644 index 0000000..221a642 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/dataBindingTest/simpleBinding.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <force>true</force> + <!--<verbose>true</verbose>--> + <includes> + <value>**/dataBindingTest/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/decoratorTest/BoxedDecorator.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/decoratorTest/BoxedDecorator.jaxx new file mode 100644 index 0000000..8c37a04 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/decoratorTest/BoxedDecorator.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel> + <JButton id='boxedButton' decorator='boxed'/> +</JPanel> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/decoratorTest/Decorator.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/decoratorTest/Decorator.xml new file mode 100644 index 0000000..f1a6312 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/decoratorTest/Decorator.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <addLogger>false</addLogger> + <includes> + <value>**/decoratorTest/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error.xml new file mode 100644 index 0000000..42adb84 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <!--<verbose>true</verbose>--> + <includes> + <value>**/evolution74Test/error/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swingcombo.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swingcombo.jaxx new file mode 100644 index 0000000..c9dd3c0 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swingcombo.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JComboBox id='comboBox'> + <item value='{_("OK")}' selected='true'/> +</JComboBox> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swinglist.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swinglist.jaxx new file mode 100644 index 0000000..a9900ff --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swinglist.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JList> + <item value='OK'/> +</JList> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swingtree.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swingtree.jaxx new file mode 100644 index 0000000..eab7b0b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/error/swingtree.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JTree> + <item value='OK'/> +</JTree> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok.xml new file mode 100644 index 0000000..65cb62d --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <includes> + <value>**/evolution74Test/ok/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxcombo.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxcombo.jaxx new file mode 100644 index 0000000..526f3de --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxcombo.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JAXXComboBox> + <item value='OK'/> +</JAXXComboBox> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxlist.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxlist.jaxx new file mode 100644 index 0000000..76692e8 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxlist.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JAXXList> + <item value='OK'/> +</JAXXList> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxtree.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxtree.jaxx new file mode 100644 index 0000000..fe5d5cc --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/jaxxtree.jaxx @@ -0,0 +1,28 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JAXXTree> + <item value='OK'/> +</JAXXTree> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swingcombo.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swingcombo.jaxx new file mode 100644 index 0000000..1329cfe --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swingcombo.jaxx @@ -0,0 +1,26 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JComboBox/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swinglist.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swinglist.jaxx new file mode 100644 index 0000000..9165c83 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swinglist.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JList/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swingtree.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swingtree.jaxx new file mode 100644 index 0000000..7ef4404 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/evolution74Test/ok/swingtree.jaxx @@ -0,0 +1,26 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JTree/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nText.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nText.xml new file mode 100644 index 0000000..e646f97 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nText.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <i18nable>true</i18nable> + <includes> + <value>**/i18nTest/text/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nTitle.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nTitle.xml new file mode 100644 index 0000000..47afa21 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nTitle.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <i18nable>true</i18nable> + <includes> + <value>**/i18nTest/title/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nToolTipText.xml b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nToolTipText.xml new file mode 100644 index 0000000..068dbdc --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/I18nToolTipText.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.nuiton.jaxx.test</groupId> + <artifactId>test</artifactId> + <version>0</version> + <build> + <plugins> + <plugin> + <groupId>org.nuiton</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <configuration> + <src>${basedir}/target/test-classes</src> + <outJava>${basedir}/target/generated-sources/test-java</outJava> + <!--outResource>${basedir}/target/it-generated-sources/resources</outResource--> + <force>true</force> + <i18nable>true</i18nable> + <includes> + <value>**/i18nTest/tooltiptext/*.jaxx</value> + </includes> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/text/JButton.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/text/JButton.jaxx new file mode 100644 index 0000000..07f6d9b --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/text/JButton.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<javax.swing.JButton text='test.text'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JDialog.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JDialog.jaxx new file mode 100644 index 0000000..5c62eeb --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JDialog.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JDialog title='test.title'/> diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JTabbedPane.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JTabbedPane.jaxx new file mode 100644 index 0000000..05e8150 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JTabbedPane.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + <JTabbedPane> + <tab title='test.title'/> +</JTabbedPane> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JTabbedPane2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JTabbedPane2.jaxx new file mode 100644 index 0000000..c3b5109 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/title/JTabbedPane2.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JTabbedPane> + <tab title='test.title'> + <JLabel text='testLabel'/> + </tab> +</JTabbedPane> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JButton.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JButton.jaxx new file mode 100644 index 0000000..4f7fcf9 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JButton.jaxx @@ -0,0 +1,25 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<javax.swing.JButton toolTipText='test.toolTipText'/> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane.jaxx new file mode 100644 index 0000000..6ccf502 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + <JTabbedPane toolTipText='test.toolTipText'> + <tab title="text"/> +</JTabbedPane> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane2.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane2.jaxx new file mode 100644 index 0000000..417b769 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane2.jaxx @@ -0,0 +1,27 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + <JTabbedPane> + <tab toolTipText='test.toolTipText'/> +</JTabbedPane> \ No newline at end of file diff --git a/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane3.jaxx b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane3.jaxx new file mode 100644 index 0000000..5d8d847 --- /dev/null +++ b/trunk/jaxx-maven-plugin/src/test/resources/org/nuiton/jaxx/plugin/i18nTest/tooltiptext/JTabbedPane3.jaxx @@ -0,0 +1,29 @@ +<!-- + #%L + JAXX :: Maven plugin + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JTabbedPane> + <tab toolTipText='test.toolTipText'> + <JLabel text='yo'/> + </tab> +</JTabbedPane> \ No newline at end of file diff --git a/trunk/jaxx-runtime/LICENSE.txt b/trunk/jaxx-runtime/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/jaxx-runtime/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/jaxx-runtime/README.txt b/trunk/jaxx-runtime/README.txt new file mode 100644 index 0000000..d2e50d3 --- /dev/null +++ b/trunk/jaxx-runtime/README.txt @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install diff --git a/trunk/jaxx-runtime/changelog.txt b/trunk/jaxx-runtime/changelog.txt new file mode 100644 index 0000000..764da92 --- /dev/null +++ b/trunk/jaxx-runtime/changelog.txt @@ -0,0 +1,109 @@ +1.5 + * 20090506 [chemit] - super-pom has no dependencies + +1.3 chemit 20090409 + * 20090404 [chemit] - introduce DataContext class + * 20090331 [chemit] - introduce DecoratorUtils class + * 20090302 [chemit] - add pcs in ApplicationContext + - add method in Util to filter JAXX property changed listeners + +1.2 letellier 2009022? + * 2009021 [chemit] - introduce DefaultApplicationContext iwth annotation system. + +1.1 chemit 20090220 + * 20090124 [chemit] - add methods to retreave icons from UIManager in Util class + * 20090123 [chemit] - add a simple createIcon method in Util classe (to create an icon with no path prefix) + - add a UIManager key "default.icon.path" to be able to change the path where to find icons + * 20090122 [chemit] - refactor poms (sibling dependencies, pluginsManagment,...) + +1.0 chemit 20090111 + * 20090111 [chemit] - integrate new architecture to allow to have runtime code with NO link with compiler :) + +0.8 ??? 200812?? + * 20081228 [chemit] - generify ClassDescriptor + - introduce StylesheetHelper helper class to detach Stylesheet, Rule and Selector classes from + JAXXCompiler and make possible to extract compiler engine from runtime + + * 20081227 [chemit] - add PCS on ValidatorErrorTable to be used by table validation + * 20081218 [chemit] - improve generation of methods + * 20081214 [chemit] - can now in validation, put error with args (all args must be separated by a ##) + - improve event naming : replace the $evXXX by doMEthodName__on__field (except with optimize option) + - add jaww.runtime.swing.Utils.fillComboBox to fill a combobox model from a collection + - add addSourcesToClassPath property to add sources directories in class-path + - improve classloader managment + - keep in DataSource objetCode + - fix bug when processDataBinding on a null objectCode + - always clean demoNode cached values when selected it + - add usefull databinding method in Util + + * 20081213 [chemit] - improve navigation tree demoNode rendering with some caches + - introduce a ChildBuilder to simplify building of child nodes from a collection or array + +0.7 chemit 20081210 + * 20081210 [chemit] - fix bug 1751 + * 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 demoNode + * 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 + 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) diff --git a/trunk/jaxx-runtime/pom.xml b/trunk/jaxx-runtime/pom.xml new file mode 100644 index 0000000..75c3f35 --- /dev/null +++ b/trunk/jaxx-runtime/pom.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> + <!-- + #%L + JAXX :: Runtime + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jaxx</artifactId> + <version>2.5.2</version> + </parent> + + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-runtime</artifactId> + + <dependencies> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <!-- pour utiliser javaHelp --> + <dependency> + <groupId>javax.help</groupId> + <artifactId>javahelp</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <!-- pour utiliser JTreeTable --> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-core</artifactId> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JAXX :: Runtime</name> + <description>JAXX Runtime api</description> + +</project> diff --git a/trunk/jaxx-runtime/src/license/THIRD-PARTY.properties b/trunk/jaxx-runtime/src/license/THIRD-PARTY.properties new file mode 100644 index 0000000..aa1cf78 --- /dev/null +++ b/trunk/jaxx-runtime/src/license/THIRD-PARTY.properties @@ -0,0 +1,20 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - BSD License +# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 +# - Common Public License Version 1.0 +# - GNU General Public License - Version 2 with the class path exception +# - Indiana University Extreme! Lab Software License, vesion 1.1.1 +# - Lesser General Public License (LGPL) +# - Lesser General Public License (LGPL) v 3.0 +# - Lesser General Public License (LPGL) +# - Lesser General Public License (LPGL) v 2.1 +# - MIT License +# - The Apache Software License, Version 2.0 +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Thu Aug 18 07:10:40 CEST 2011 +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/Base64Coder.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/Base64Coder.java new file mode 100644 index 0000000..b55605f --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/Base64Coder.java @@ -0,0 +1,267 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +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 + diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/ComponentDescriptor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/ComponentDescriptor.java new file mode 100644 index 0000000..6cafceb --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/ComponentDescriptor.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +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 diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingListener.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingListener.java new file mode 100644 index 0000000..a29e335 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingListener.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + + +/** + * A <code>PropertyChangeListener</code> which processes a data binding when it receives a + * <code>PropertyChangeEvent</code>. + */ +public class DataBindingListener implements PropertyChangeListener { + private JAXXObject object; + + private String dest; + + /** + * Creates a new <code>DataBindingListener</code> which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param object the object in which the data binding exists + * @param dest the name of the data binding to run + */ + public DataBindingListener(JAXXObject object, String dest) { + this.object = object; + this.dest = dest; + } + + + /** + * Processes the data binding in response to a <code>PropertyChangeEvent</code>. + * + * @param e the event which triggered the binding + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + object.processDataBinding(dest); + + // for now, handle dependency changes by always removing & reapplying + // the binding. We should be more efficient and only do this when it's + // actually necessary + object.removeDataBinding(dest); + object.applyDataBinding(dest); + } +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingUpdateListener.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingUpdateListener.java new file mode 100644 index 0000000..c0fe668 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/DataBindingUpdateListener.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + + +/** + * A <code>PropertyChangeListener</code> which removes and re-applies a data binding + * when it receives a <code>PropertyChangeEvent</code>. + */ +public class DataBindingUpdateListener implements PropertyChangeListener { + private JAXXObject object; + + private String dest; + + /** + * Creates a new <code>DataBindingUpdateListener</code> which will remove and re-apply a + * data binding when it receives a <code>PropertyChangeEvent</code>. + * + * @param object the object in which the data binding exists + * @param dest the name of the data binding to reapply + */ + public DataBindingUpdateListener(JAXXObject object, String dest) { + this.object = object; + this.dest = dest; + } + + + public String getBindingName() { + return dest; + } + + + /** + * Updates the data binding in response to a <code>PropertyChangeEvent</code>. + * + * @param e the event which triggered the binding + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + object.removeDataBinding(dest); + object.applyDataBinding(dest); + } +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXAction.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXAction.java new file mode 100644 index 0000000..63dde24 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXAction.java @@ -0,0 +1,45 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import jaxx.runtime.context.JAXXInitialContext; + +/** + * This is the contract to be realized by any class to be used as Action class for an ui. + * + * @author tchemit <chemit@codelutin.com> + */ +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 JAXXInitialContext} to be injected in the ui via the constructor of the {@link JAXXObject} + */ + JAXXInitialContext init(JAXXContext parentContent, Object... datas); + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXBinding.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXBinding.java new file mode 100644 index 0000000..9ff1cf0 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXBinding.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import java.beans.PropertyChangeListener; + +/** + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public interface JAXXBinding extends PropertyChangeListener { + /** @return the unique id of a binding */ + String getId(); + + /** @return the {@link JAXXObject} which owns the binding */ + JAXXObject getSource(); + + /** + * This state is not used actually, but will be usefull later... + * + * @return {@code true} if binding was registred as a default binding, {@code false} otherwise + */ + boolean isDefaultBinding(); + + /** Apply the binding without processing it (say just install listeners). */ + void applyDataBinding(); + + /** Processes the binding. */ + void processDataBinding(); + + /** Remove the binding. */ + void removeDataBinding(); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXContext.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXContext.java new file mode 100644 index 0000000..4640649 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXContext.java @@ -0,0 +1,132 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +/** + * 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 tchemit <chemit@codelutin.com> + */ +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 <T> type of data to set in context + * @param o the value to push in context + */ + <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 <T> type of data to set in context + * @param o the value to push in context + * @param name the name of the new entry + */ + <T> void setContextValue(T o, String name); + + /** + * Remove from context the value with the given klazz as an unamed entry + * + * @param <T> type of data to remove from context + * @param klazz the klazz entry + */ + <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 <T> type of data to remove from context + * @param klazz the klazz entry + * @param name extra name of the entry + */ + <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 <T> type of data to obtain from context + * @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. + */ + <T> T getContextValue(Class<T> clazz); + + /** + * Seek for a named entry in the context + * + * @param <T> type of data to obtain from 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. + */ + <T> T getContextValue(Class<T> clazz, String name); + +// /** +// * Return parent's container corresponding to the Class clazz +// * +// * @param <O> type of container to obtain from context +// * @param clazz clazz desired +// * @return parent's container +// * @deprecated since 2.0.0 : breaks neutral since Swing +// */ +// @Deprecated +// public <O extends Container> O getParentContainer(Class<O> clazz); +// +// /** +// * Return parent's container corresponding to the Class clazz +// * +// * @param <O> type of container to obtain from context +// * @param top the top container +// * @param clazz desired +// * @return parent's container +// * @deprecated since 2.0.0 : breaks neutral since Swing +// */ +// @Deprecated +// public <O extends Container> O getParentContainer(Object top, Class<O> clazz); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObject.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObject.java new file mode 100644 index 0000000..6b3e0b4 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObject.java @@ -0,0 +1,170 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import java.awt.Container; +import java.beans.PropertyChangeListener; +import java.io.Serializable; +import java.util.Map; + +/** + * The <code>JAXXObject</code> interface is implemented by all classes + * produced by the JAXX compiler. + */ +public interface JAXXObject extends JAXXContext, Serializable { + + /** + * Retrieves an object defined in an XML tag by its ID. + * + * @param id the id of the component to retrieve + * @return the object + */ + Object getObjectById(String id); + + /** + * Pretrieves the dictonary of knwon objects indexed by their ids. + * + * @return the dictonary of objects. + */ + Map<String, Object> get$objectMap(); + + /** @return the {@link JAXXContext} attached to the object */ + JAXXContext getDelegateContext(); + + /** @return all the databinding registred on the jaxx object */ + JAXXBinding[] getDataBindings(); + + /** + * Register a new binding in the jaxx object. + * + * @param binding the binding to add + */ + void registerDataBinding(JAXXBinding binding); + + /** + * Apply the data bind by name and then process it. + * + * @param id the id of the databinding + */ + void applyDataBinding(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 + */ + void processDataBinding(String dest); + + /** + * 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 + * @param force flag to force binding, even if already on run + */ + void processDataBinding(String dest, boolean force); + + /** + * Remove a databinding by name. + * + * @param id the name of databinding to remove + */ + void removeDataBinding(String id); + + /** + * Obtain a binding given his id. + * + * @param bindingId the id of the binding + * @return the binding, or {@code null} if not found. + * @see JAXXBinding + * @since 2.4.2 + */ + JAXXBinding getDataBinding(String bindingId); + + /** + * 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 + */ + void firePropertyChange(String name, Object oldValue, Object newValue); + + /** + * Register a general {@link PropertyChangeListener}. + * + * @param listener the listener to register + */ + void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Register a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to register + */ + void addPropertyChangeListener(String property, PropertyChangeListener listener); + + /** + * Unregister a general {@link PropertyChangeListener}. + * + * @param listener the listener to unregister + */ + void removePropertyChangeListener(PropertyChangeListener listener); + + /** + * Unregister a {@link PropertyChangeListener}. for the given {@code propertyName}. + * + * @param property the property name to listen + * @param listener the listener to unregister + */ + void removePropertyChangeListener(String property, PropertyChangeListener listener); + + /** + * Return parent's container corresponding to the Class clazz + * + * @param <O> type of container to obtain from context + * @param clazz clazz desired + * @return parent's container + */ + <O extends Container> O getParentContainer(Class<O> clazz); + + /** + * Return parent's container corresponding to the Class clazz + * + * @param <O> type of container to obtain from context + * @param top the top container + * @param clazz desired + * @return parent's container + */ + <O extends Container> O getParentContainer(Object top, Class<O> clazz); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java new file mode 100644 index 0000000..c239857 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXObjectDescriptor.java @@ -0,0 +1,64 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import jaxx.runtime.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 diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXUtil.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXUtil.java new file mode 100644 index 0000000..caff5e1 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/JAXXUtil.java @@ -0,0 +1,639 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import jaxx.runtime.context.JAXXContextEntryDef; +import jaxx.runtime.context.JAXXInitialContext; +import org.apache.commons.beanutils.ConstructorUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Component; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeListenerProxy; +import java.beans.PropertyChangeSupport; +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.Collection; +import java.util.Collections; +import java.util.EventListener; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +public class JAXXUtil { + + /** Logger */ + static private final Log log = LogFactory.getLog(JAXXUtil.class); + + public static final String PARENT = "parent"; + + // 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 final PropertyChangeListener[] EMPTY_ARRAY_PROPERTY_CHANGE_LISTENERS = new PropertyChangeListener[0]; + + 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); + } 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); + } 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 <O> JAXXContextEntryDef<O> newContextEntryDef( + Class<O> klass) { + return newContextEntryDef(null, klass); + } + + public static <O> JAXXContextEntryDef<O> newContextEntryDef( + String name, Class<?> klass) { + return new JAXXContextEntryDef<O>(name, (Class<O>) klass); + } + + public static <O> JAXXContextEntryDef<List<O>> newListContextEntryDef() { + return newListContextEntryDef(null); + } + + public static <O> JAXXContextEntryDef<List<O>> newListContextEntryDef( + String name) { + Class<List<O>> castList = castList(); + JAXXContextEntryDef<List<O>> contextEntryDef = + new JAXXContextEntryDef<List<O>>(name, castList); + return contextEntryDef; + } + + public static <K, V> JAXXContextEntryDef<Map<K, V>> newMapContextEntryDef( + String name) { + JAXXContextEntryDef<Map<K, V>> contextEntryDef = + new JAXXContextEntryDef<Map<K, V>>(Map.class, name); + return contextEntryDef; + } + + @SuppressWarnings({"unchecked"}) + protected static <K, V> Class<Map<K, V>> castMap() { + return (Class<Map<K, V>>) Collections.emptyMap().getClass(); + } + + @SuppressWarnings({"unchecked"}) + protected static <O> Class<List<O>> castList() { + return (Class<List<O>>) Collections.emptyList().getClass(); + } + + /** + * Method to initialize the context of a ui. + * + * @param ui the ui + * @param parentContext the context to set in ui + */ + public static void initContext(JAXXObject ui, JAXXContext parentContext) { + + if (parentContext instanceof JAXXInitialContext) { + ((JAXXInitialContext) parentContext).to(ui); + } else { + ui.setContextValue(parentContext); + } + // if parentContext is a JAXXObject then + // add an special parent entry to can go up + if (parentContext instanceof JAXXObject) { + ui.setContextValue(parentContext, PARENT); + } + } + + public static <E extends EventListener> E getEventListener( + Class<E> listenerClass, + final String listenerMethodName, + final Object methodContainer, + 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 (descriptor.listenerClass.equals(listenerClass) && + (listenerMethodName == null ? + descriptor.listenerMethodName == null : + listenerMethodName.equals( + descriptor.listenerMethodName)) && + methodName.equals(descriptor.methodName)) { + return (E) 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()); + } + // tchemit 2010-12-01 : we must the exact method found, some none javaBeans + // api does use different signature for some of them listener + // an exemple is the TableColumnModelListener : http://download.oracle.com/javase/6/docs/api/javax/swing/event/TableColumnMo... + // This fix the bug http://nuiton.org/issues/show/1124 + Class<?>[] parameterTypes; + if (listenerMethodName != null) { + + // search an exact method, so must use the exact found listener method + parameterTypes = listenerMethod.getParameterTypes(); + } else { + + // keep this horrible code which is not safe at all : + // see previous comment + 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() { + + @Override + public Object invoke(Object proxy, + Method method, + Object[] args) { + String methodName = method.getName(); + if (listenerMethodName == null && + listenerMethods.contains(method) || + methodName.equals(listenerMethodName)) { + try { + targetMethod.setAccessible(true); + return targetMethod.invoke( + methodContainer, args); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "could not invoke on container " + + methodContainer, 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 (E) descriptor.eventListener; + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public static <E extends EventListener> E getEventListener( + Class<E> listenerClass, + Object methodContainer, + 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; + } + + /** + * Remove all listeners registred in given {@code pcs}. + * + * @param pcs the pcs to clean + */ + public static void destroy(PropertyChangeSupport pcs) { + PropertyChangeListener[] listeners = pcs.getPropertyChangeListeners(); + for (PropertyChangeListener l : listeners) { + if (log.isInfoEnabled()) { + if (l instanceof PropertyChangeListenerProxy) { + PropertyChangeListenerProxy ll = (PropertyChangeListenerProxy) l; + log.info("remove property change listener " + ll.getPropertyName() + " : " + l); + } else { + log.info("remove property change listener " + l); + } + } + pcs.removePropertyChangeListener(l); + } + } + + /** + * Remove all listeners registred in given {@code component}. + * + * @param component the pcs to clean + */ + public static void destroy(Component component) { + PropertyChangeListener[] listeners = component.getPropertyChangeListeners(); + for (PropertyChangeListener l : listeners) { + if (log.isInfoEnabled()) { + if (l instanceof PropertyChangeListenerProxy) { + PropertyChangeListenerProxy ll = (PropertyChangeListenerProxy) l; + log.info("remove property change listener " + ll.getPropertyName() + " : " + l); + } else { + log.info("remove property change listener " + l); + } + } + component.removePropertyChangeListener(l); + } + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static boolean assignment(boolean value, + String name, + JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + + public static byte assignment(byte value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static short assignment(short value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static int assignment(int value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static long assignment(long value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static float assignment(float value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static double assignment(double value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static char assignment(char value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** @deprecated since 2.4.2, never use, will not be replaced */ + @Deprecated + public static Object assignment(Object value, String name, JAXXObject src) { + src.firePropertyChange(name.trim(), null, "dummy value"); + return value; + } + + /** + * 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 some entries exists in a given context and throw an + * IllegalArgumentException if not. + * <p/> + * + * @param context the context to test + * @param defs the definitions of entries to seek in context + * @throws IllegalArgumentException if the entry is not found in context. + */ + public static void checkJAXXContextEntries(JAXXContext context, + JAXXContextEntryDef<?>... defs) + throws IllegalArgumentException { + + for (JAXXContextEntryDef<?> def : defs) { + Object value = def.getContextValue(context); + + if (value == null) { + throw new IllegalArgumentException( + "the context entry [" + def + "] ] was not found in " + + "context " + context); + } + } + } + + /** + * 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 <T> the type of required data + * @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; + } + + /** + * To reload a binding, the method will invoke + * <ul> + * <li>{@link JAXXBinding#removeDataBinding()}</li> + * <li>{@link JAXXBinding#applyDataBinding()}</li> + * </ul> + * + * @param binding the binding to reload. + * @since 2.4.2 + */ + public static void reloadBinding(JAXXBinding binding) { + binding.removeDataBinding(); + binding.applyDataBinding(); + } + + /** + * Convinient method to reload a given binding by his id on a JAXX ui. + * + * @param src the ui to treate + * @param bindingId the id of binding to reload. + * @since 2.4.2 + */ + public static void reloadBinding(JAXXObject src, String bindingId) { + JAXXBinding dataBinding = src.getDataBinding(bindingId); + if (dataBinding != null) { + reloadBinding(dataBinding); + } else { + if (log.isWarnEnabled()) { + log.warn("Could not found binding[" + bindingId + "] on ui " + src); + } + } + } + + /** + * Convinient method to apply 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 applyDataBinding(JAXXObject src, String... bindings) { + for (String binding : bindings) { + src.applyDataBinding(binding); + } + } + + /** + * Convinient method to apply 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 applyDataBinding(JAXXObject src, + Collection<String> bindings) { + for (String binding : bindings) { + src.applyDataBinding(binding); + } + } + + /** + * 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 remove 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 removeDataBinding(JAXXObject src, String... bindings) { + for (String binding : bindings) { + src.removeDataBinding(binding); + } + } + + /** + * detects all PropertychangedListener added by Jaxx uis (should be a {@link + * DataBindingListener} + * + * @param propertyNames the array of property names to find + * @param listeners the array of listeners to filter + * @return the filtered listeners + */ + public static PropertyChangeListener[] findJaxxPropertyChangeListener( + String[] propertyNames, PropertyChangeListener... listeners) { + if (listeners == null || listeners.length == 0) { + return EMPTY_ARRAY_PROPERTY_CHANGE_LISTENERS; + } + List<String> pNames = Arrays.asList(propertyNames); + + List<PropertyChangeListener> toRemove = + new ArrayList<PropertyChangeListener>(); + + for (PropertyChangeListener listener : listeners) { + String pName = null; + PropertyChangeListenerProxy plistener = null; + if (listener instanceof PropertyChangeListenerProxy) { + plistener = (PropertyChangeListenerProxy) listener; + if (!pNames.contains(plistener.getPropertyName())) { + // not on the good property + continue; + } + listener = (PropertyChangeListener) plistener.getListener(); + pName = plistener.getPropertyName(); + } + if (plistener != null && + pName != null && + listener instanceof DataBindingListener) { + if (log.isDebugEnabled()) { + log.debug("find config listener to remove [" + pName + + "] : " + listener); + } + toRemove.add(plistener); + //toRemove.add(listener); + } + } + return toRemove.toArray(new PropertyChangeListener[toRemove.size()]); + } + + /** + * Overrides the commons method to have generict cast fiex. + * + * @param type the type of objet to instanciate + * @param prototype prototype of the constructor + * @param parms params to pass to constructor + * @param <O> type of object to create + * @return the new object + * @throws Exception if something wrong + * @since 2.1 + */ + @SuppressWarnings({"unchecked"}) + public static <O> O invokeConstructor(Class<O> type, + Class<?>[] prototype, + Object... parms) throws Exception { + O o = (O) ConstructorUtils.invokeConstructor(type, + parms, + prototype + ); + return o; + } + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/SwingUtil.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/SwingUtil.java new file mode 100644 index 0000000..4b577d7 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/SwingUtil.java @@ -0,0 +1,1276 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + +import jaxx.runtime.swing.Item; +import jaxx.runtime.swing.JAXXComboBox; +import jaxx.runtime.swing.editor.BooleanCellEditor; +import jaxx.runtime.swing.renderer.BooleanCellRenderer; +import jaxx.runtime.swing.renderer.EmptyNumberTableCellRenderer; +import jaxx.runtime.swing.renderer.EnumTableCellRenderer; +import jaxx.runtime.swing.renderer.I18nTableCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.JXLayer; +import org.jdesktop.jxlayer.plaf.LayerUI; +import org.jdesktop.swingx.JXTreeTable; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JList; +import javax.swing.JRootPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.text.AbstractDocument; +import javax.swing.text.JTextComponent; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Desktop; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Rectangle; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EventObject; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Properties; + +import static org.nuiton.i18n.I18n._; + +/** + * The runtime swing util class with some nice stuff. + * <p/> + * Note : Replace previous class jaxx.runtime.swing.Utils in previous versions. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.2 + */ +public class SwingUtil extends JAXXUtil { + + /** Logger */ + static private final Log log = LogFactory.getLog(SwingUtil.class); + + public static final String DEFAULT_ICON_PATH = "/icons/"; + + public static final String DEFAULT_ICON_PATH_PROPERTY = "default.icon.path"; + + private static Field numReaders; + + private static Field notifyingListeners; + + public static final String ICON_PREFIX = "icon."; + + public static final String COLOR_PREFIX = "color."; + + public static Dimension newMinDimension() { + return new Dimension(0, 0); + } + + public static Dimension newMaxXDimension() { + return new Dimension(Short.MAX_VALUE, 0); + } + + public static Dimension newMaxYDimension() { + return new Dimension(0, Short.MAX_VALUE); + } + + public static Dimension newMaxXYDimension() { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + 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) > 0) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + 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); + } + } + + /** + * Fill a combo box model with some datas, and select after all the given object + * + * @param combo the combo to fill + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + */ + public static void fillComboBox(JComboBox combo, Collection<?> data, + Object select) { + if (!(combo.getModel() instanceof DefaultComboBoxModel)) { + throw new IllegalArgumentException( + "this method need a DefaultComboBoxModel for " + + "this model but was " + combo.getModel().getClass()); + } + DefaultComboBoxModel model = (DefaultComboBoxModel) combo.getModel(); + // evince the model + model.removeListDataListener(combo); + model.removeAllElements(); + if (data != null) { + for (Object o : data) { + model.addElement(o); + } + } + // attach the model + model.addListDataListener(combo); + model.setSelectedItem(select); + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param list the list to fill + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + */ + public static void fillList(JList list, Collection<?> data, Object select) { + if (!(list.getModel() instanceof DefaultListModel)) { + throw new IllegalArgumentException( + "this method need a DefaultListModel for this model " + + "but was " + list.getModel().getClass()); + } + DefaultListModel model = (DefaultListModel) list.getModel(); + // evince the model +// model.removeListDataListener(combo); + model.removeAllElements(); + if (data != null) { + for (Object o : data) { + model.addElement(o); + } + } + // attach the model +// model.addListDataListener(combo); + list.setSelectedValue(select, true); + } + + /** + * TODO move this to JAXXComboBox. + * <p/> + * Fill a combo box model with some datas, and select after all the given object + * + * @param combo the combo to fill + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + * @param firstNull add a first null element + * @deprecated since 1.7.XXX this code is moved to JAXXComboBox + */ + @Deprecated + public static void fillComboBox(JAXXComboBox combo, + Collection<?> data, + Object select, boolean firstNull) { + List<Item> items = new ArrayList<Item>(); + if (firstNull) { + items.add(new Item("null", " ", null, false)); + } + if (data != null) { + for (Object d : data) { + Item item = new Item(d.toString(), d.toString(), d, + d.equals(select)); + items.add(item); + } + } + combo.setItems(items); + } + + /** + * Return parent's container corresponding to the Class clazz + * + * @param <O> type of container to obtain from context + * @param top the top container + * @param clazz desired + * @return parent's container + */ + @SuppressWarnings({"unchecked"}) + public static <O extends Container> O getParentContainer(Object top, + Class<O> clazz) { + 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; + } + + public static int computeTableColumnWidth(JTable table, + Font font, + int columnIndex, String suffix) { + int width = 0; + if (font == null) { + font = table.getFont(); + } +// if (font == null) { +// TableColumn column = table.getColumnModel().getColumn(columnIndex); +// font = ((JComponent) column.getCellRenderer()).getFont(); +// } + FontMetrics fontMetrics = table.getFontMetrics(font); + for (int i = 0, rowCount = table.getRowCount(); i < rowCount; i++) { + String key = (String) table.getModel().getValueAt(i, 0); + int w = fontMetrics.stringWidth(key + suffix); + if (w > width) { + width = w; + } + } + return width; + } + + public static void fixTableColumnWidth(JTable table, + int columnIndex, + int width) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setMaxWidth(width); + column.setMinWidth(width); + column.setWidth(width); + column.setPreferredWidth(width); + } + + public static void setTableColumnEditor(JTable table, + int columnIndex, + TableCellEditor editor) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setCellEditor(editor); + } + + public static void setTableColumnRenderer(JTable table, + int columnIndex, + TableCellRenderer editor) { + TableColumn column = table.getColumnModel().getColumn(columnIndex); + column.setCellRenderer(editor); + } + + public static void setI18nTableHeaderRenderer(JTable table, + String... libelles) { + I18nTableCellRenderer defaultRenderer = + new I18nTableCellRenderer( + table.getTableHeader().getDefaultRenderer(), libelles); + table.getTableHeader().setDefaultRenderer(defaultRenderer); + } + + public static TableCellRenderer newStringTableCellRenderer( + final DefaultTableCellRenderer renderer, + final int length, + final boolean tooltip) { + + return new DefaultTableCellRenderer() { + + private static final long serialVersionUID = 1l; + + @Override + public Component getTableCellRendererComponent( + JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + + renderer.getTableCellRendererComponent( + table, + value, + isSelected, + hasFocus, + row, + column + ); + String val = renderer.getText(); + String val2 = val; + if (val.length() > length) { + val2 = val.substring(0, length - 3) + "..."; + } + + JComponent comp = (JComponent) + super.getTableCellRendererComponent( + table, + val2, + isSelected, + hasFocus, + row, + column + ); + if (tooltip) { + comp.setToolTipText(val); + } + return comp; + } + }; + } + + /** + * Box a component in a {@link JXLayer}. + * + * @param component the component to box + * @return the {@link JXLayer} boxing the component + */ + public static <V extends JComponent> JXLayer<V> boxComponentWithJxLayer(V component) { + JXLayer<V> layer = getLayer(component); + if (layer != null) { + return layer; + } + layer = new JXLayer<V>(); + layer.setView(component); + return layer; + } + + public static List<JComponent> getLayeredComponents(JAXXObject object) { + List<JComponent> result = new ArrayList<JComponent>(); + for (Entry<String, Object> child : object.get$objectMap().entrySet()) { + if (child.getValue() == null) { + log.warn("find a null object in $objectMap " + child.getKey()); + continue; + } + if (JComponent.class.isAssignableFrom(child.getValue().getClass())) { + JComponent comp = (JComponent) child.getValue(); + if (isLayered(comp)) { + result.add(comp); + } + } + } + return result; + } + + public static <V extends JComponent> JXLayer<V> getLayer(V comp) { + if (!isLayered(comp)) { + return null; + } + return (JXLayer<V>) comp.getParent(); + } + + public static void setLayerUI(JComponent comp, LayerUI<JComponent> ui) { + JXLayer<JComponent> layer = getLayer(comp); + layer.setUI(ui); + } + + public static boolean isLayered(JComponent comp) { + Container parent = comp.getParent(); + return parent != null && parent instanceof JXLayer<?>; + } + + /** + * 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; + } + + /** + * Centrer un component graphique au center d'un autre component. + * <p/> + * <b>Note:</b> si le parent est null, alors on ne fait rien. + * + * @param parent le component parent + * @param component le component à centrer + */ + public static void center(Component parent, Component component) { + if (parent == null) { + return; + } + Rectangle r = parent.getBounds(); + int x = r.x + (r.width - component.getSize().width) / 2; + int y = r.y + (r.height - component.getSize().height) / 2; + component.setLocation(x, y); + } + + /** + * Try to load the Nimbus look and feel. + * <p/> + * + * @throws UnsupportedLookAndFeelException + * if nimbus is not applicable + * @throws ClassNotFoundException + * @throws InstantiationException + * @throws IllegalAccessException + */ + public static void initNimbusLoookAndFeel() throws UnsupportedLookAndFeelException, ClassNotFoundException, InstantiationException, IllegalAccessException { + + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(laf.getName())) { + UIManager.setLookAndFeel(laf.getClassName()); + } + } + } + + /** + * Load the ui.properties file and set in {@link UIManager} colors and + * icons found. + * + * @param defaultUIConfig le path vers le fichier de la config d'ui par + * défaut (doit etre dansle class-path) + * @param extraUIConfig le path vers une surcharge de la config d'ui + * (doit etre dans le class-path) + * @throws IOException if could not load the ui.properties file + */ + public static void loadUIConfig(String defaultUIConfig, + String extraUIConfig) throws IOException { + + Properties p = new Properties(); + log.info("loading default UI config " + defaultUIConfig); + p.load(SwingUtil.class.getResourceAsStream(defaultUIConfig)); + if (log.isDebugEnabled()) { + log.debug(p.toString()); + } + if (extraUIConfig != null) { + InputStream extraStream = + SwingUtil.class.getResourceAsStream(extraUIConfig); + if (extraStream == null) { + log.warn("could not find extraUIConfig : " + extraUIConfig); + } else { + log.info("loading extra UI config " + extraUIConfig); + Properties p2 = new Properties(p); + p2.load(extraStream); + if (log.isDebugEnabled()) { + log.debug(p2.toString()); + } + p.putAll(p2); + } + } + for (Entry<Object, Object> entry : p.entrySet()) { + String key = (String) entry.getKey(); + if (key.startsWith(ICON_PREFIX)) { + ImageIcon icon; + try { + icon = createImageIcon((String) entry.getValue()); + UIManager.put(key.substring(ICON_PREFIX.length()), icon); + } catch (Exception e) { + log.warn("could not load icon " + entry.getValue()); + } + continue; + } + if (key.startsWith(COLOR_PREFIX)) { + String value = (String) entry.getValue(); + String[] rgb = value.split(","); + UIManager.put( + key.substring(COLOR_PREFIX.length()), + new Color( + Integer.valueOf(rgb[0]), + Integer.valueOf(rgb[1]), + Integer.valueOf(rgb[2]) + ) + ); + } + } + } + + /** + * Load the ui.properties file and set in {@link UIManager} colors and + * icons found. + * + * @param incoming the ui resources to load. + * @since 2.1 + */ + public static void loadUIConfig(Properties incoming) { + + for (Entry<Object, Object> entry : incoming.entrySet()) { + String key = (String) entry.getKey(); + if (key.startsWith(ICON_PREFIX)) { + ImageIcon icon; + try { + icon = createImageIcon((String) entry.getValue()); + UIManager.put(key.substring(ICON_PREFIX.length()), icon); + } catch (Exception e) { + log.warn("could not load icon " + entry.getValue()); + } + continue; + } + if (key.startsWith(COLOR_PREFIX)) { + String value = (String) entry.getValue(); + String[] rgb = value.split(","); + UIManager.put( + key.substring(COLOR_PREFIX.length()), + new Color( + Integer.valueOf(rgb[0]), + Integer.valueOf(rgb[1]), + Integer.valueOf(rgb[2]) + ) + ); + } + } + } + + /** + * Iterate the components of a {@link JTabbedPane} in natural order. + * <p/> + * Says using method {@link JTabbedPane#getComponent(int)} + * + * @param tabs the + * @return the iterator + * @since 1.4 + */ + public static TabbedPaneIterator<Component> newTabbedPaneIterator( + JTabbedPane tabs) { + return new TabbedPaneIterator<Component>(false, tabs) { + + @Override + protected Component get(int index, Component comp) { + return comp; + } + }; + } + + /** + * A simple iterator on a {@link JTabbedPane}. + * <p/> + * Implements the method {@link #get(int, Component)} to obtain + * the data required given the component (or index). + * <p/> + * You can also inverse the order by usin the method {@link #reverse()}. + * <p/> + * Note: After the use of the method {@link #reverse()} the iterator returns + * to the first element. + * + * @param <O> the type of return elements. + * @since 1.4 + */ + public static abstract class TabbedPaneIterator<O> implements Iterator<O> { + + final JTabbedPane tabs; + + boolean reverse; + + int index; + + int increment; + + protected abstract O get(int index, Component comp); + + public TabbedPaneIterator(boolean reverse, JTabbedPane tabs) { + this.tabs = tabs; + setReverse(reverse); + } + + public void reset() { + setReverse(reverse); + } + + public int size() { + return tabs.getTabCount(); + } + + public TabbedPaneIterator<O> reverse() { + setReverse(!reverse); + return this; + } + + @Override + public boolean hasNext() { + return reverse ? index > 0 : index < tabs.getTabCount(); + } + + public int getIndex() { + return index; + } + + @Override + public O next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Component next = tabs.getComponentAt(index); + O result = get(index, next); + index += increment; + return result; + } + + @Override + public void remove() { + throw new IllegalStateException("not implemented for " + this); + } + + @Override + public String toString() { + return super.toString() + "< reverse:" + reverse + ", index:" + + index + ", size:" + tabs.getTabCount() + " >"; + } + + protected void setReverse(boolean reverse) { + if (reverse) { + index = tabs.getTabCount() - 1; + increment = -1; + } else { + index = 0; + increment = 1; + } + this.reverse = reverse; + } + } + + public static JLabel newLabel(String text, Object iconKey, int aligment) { + Icon icon = null; + if (iconKey instanceof Icon) { + icon = (Icon) iconKey; + } else if (iconKey instanceof String) { + icon = getUIManagerActionIcon((String) iconKey); + } + JLabel result; + if (icon == null) { + result = new JLabel(text, aligment); + } else { + result = new JLabel(text, icon, aligment); + } + return result; + } + + /** + * Gets the higest visible component in a ancestor hierarchy at + * specific x,y coordinates + * + * @param parent + * @param x + * @param y + * @return the deppest component + */ + public static Component getDeepestObjectAt(Component parent, int x, int y) { + + if (parent instanceof Container) { + Container cont = (Container) parent; + // use a copy of 1.3 Container.findComponentAt + Component child = findComponentAt(cont, + cont.getWidth(), + cont.getHeight(), x, y); + if (child != null && child != cont) { + //log.info("child find : " + child.getName()); + if (child instanceof JRootPane) { + JLayeredPane lp = ((JRootPane) child).getLayeredPane(); + Rectangle b = lp.getBounds(); + child = getDeepestObjectAt(lp, x - b.x, y - b.y); + } + if (child != null) { + return child; + } + } + } + // if the parent is not a Container then it might be a MenuItem. + // But even if it isn't a MenuItem just return the parent because + // that's a close as we can come. + return parent; + } + + public static Component findComponentAt(Container cont, + int width, + int height, + int x, + int y) { + //log.info("container : " + cont.getName()); + synchronized (cont.getTreeLock()) { + + if (!(x >= 0 && x < width && y >= 0 && y < height && + cont.isVisible() && cont.isEnabled())) { + return null; + } + + Component[] component = cont.getComponents(); + int ncomponents = cont.getComponentCount(); + + // Two passes: see comment in sun.awt.SunGraphicsCallback + for (int i = 0; i < ncomponents; i++) { + Component comp = component[i]; + Rectangle rect = null; + + if (comp != null && !comp.isLightweight()) { + if (rect == null || rect.width == 0 || rect.height == 0) { + rect = comp.getBounds(); + } + if (comp instanceof JXLayer<?>) { + JXLayer<?> layer = (JXLayer<?>) comp; + comp = layer.getView(); + } + if (comp instanceof Container) { + comp = findComponentAt( + (Container) comp, + rect.width, + rect.height, + x - rect.x, + y - rect.y + ); + } else { + comp = comp.getComponentAt(x - rect.x, y - rect.y); + } + if (comp != null && comp.isVisible() && comp.isEnabled()) { + return comp; + } + } + } + + for (int i = 0; i < ncomponents; i++) { + Component comp = component[i]; + Rectangle rect = null; + + if (comp != null && comp.isLightweight()) { + if (rect == null || rect.width == 0 || rect.height == 0) { + rect = comp.getBounds(); + } + if (comp instanceof JXLayer<?>) { + JXLayer<?> layer = (JXLayer<?>) comp; + comp = layer.getView(); + } + if (comp instanceof Container) { + comp = findComponentAt( + (Container) comp, + rect.width, + rect.height, + x - rect.x, + y - rect.y + ); + } else { + comp = comp.getComponentAt(x - rect.x, y - rect.y); + } + if (comp != null && comp.isVisible() && comp.isEnabled()) { + return comp; + } + } + } + return cont; + } + } + + public static TableCellRenderer newDeleteCellRenderer( + DefaultTableCellRenderer renderer) { + Icon icon = UIManager.getIcon("Table.removeIcon"); + if (icon == null) { + // try with default icon + icon = createActionIcon("delete"); + } + return new BooleanCellEditor(renderer, icon); + } + + public static TableCellRenderer newBooleanTableCellRenderer( + TableCellRenderer renderer) { + return new BooleanCellRenderer(renderer); + } + + public static TableCellRenderer newBooleanTableCellEditorAndRenderer( + TableCellRenderer renderer) { + return new BooleanCellEditor(renderer); + } + + public static BooleanCellEditor newBooleanTableCellEditor( + TableCellRenderer renderer) { + return new BooleanCellEditor(renderer); + } + + public static EmptyNumberTableCellRenderer newEmptyNumberTableCellRenderer( + TableCellRenderer renderer) { + return new EmptyNumberTableCellRenderer(renderer); + } + + public static <E extends Enum<E>> EnumTableCellRenderer<E> + newEnumTableCellRenderer(TableCellRenderer renderer, Class<E> enumClass) { + return new EnumTableCellRenderer<E>(renderer, enumClass); + } + + /** + * Open a link coming from a {@link HyperlinkEvent}. + * <p/> + * And try to open the link if an url in a browser. + * + * @param he the event to treate + * @since 1.6.0 + */ + public static void openLink(HyperlinkEvent he) { + if (he.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + + if (Desktop.isDesktopSupported()) { + try { + URL u = he.getURL(); + if (u.getProtocol().equalsIgnoreCase("mailto") || + u.getProtocol().equalsIgnoreCase("http") || + u.getProtocol().equalsIgnoreCase("ftp")) { + Desktop.getDesktop().browse(u.toURI()); + } + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Error while opening link", e); + } + } catch (URISyntaxException e) { + if (log.isErrorEnabled()) { + log.error("Error while opening link", e); + } + } + } + } + } + + public static void openLink(String url) { + + try { + if (!Desktop.isDesktopSupported()) { + throw new IllegalStateException( + _("swing.error.desktop.not.supported")); + } + + + Desktop desktop = Desktop.getDesktop(); + + if (!desktop.isSupported(Desktop.Action.BROWSE)) { + + throw new IllegalStateException( + _("swing.error.desktop.browse.not.supported")); + } + + URI uri = new URI(url); + desktop.browse(uri); + } catch (Exception e) { + + if (log.isErrorEnabled()) { + log.error("Error while opening link", e); + } + } + } + + /** + * Expand all childs of a tree. + * + * @param tree the tree to expand + */ + public static void expandTree(final JTree tree) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + int i = 0; + while (i < tree.getRowCount()) { + tree.expandRow(i++); + } + } + }); + } + + /** + * Expand all childs of a tree table. + * <p/> + * FIXME : Voir pour enlever le copier coller + * + * @param treeTable the tree to expand + */ + public static void expandTreeTable(final JXTreeTable treeTable) { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + int i = 0; + while (i < treeTable.getRowCount()) { + treeTable.expandRow(i++); + } + } + }); + } + + /** + * Add a listener of tree selection model to expand a new selected node + * when it is selected. + * + * @param tree the tree to treate + */ + public static void addExpandOnClickListener(final JTree tree) { + + tree.getSelectionModel().addTreeSelectionListener( + new TreeSelectionListener() { + + @Override + public void valueChanged(final TreeSelectionEvent e) { + TreeNode node = (TreeNode) + e.getPath().getLastPathComponent(); + if (node != null && !node.isLeaf()) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + for (TreePath path : e.getPaths()) { + if (e.isAddedPath(path) && + !tree.isExpanded(path)) { + log.info("expand node [" + path + + "]"); + // will expand the node + tree.expandPath(path); + } + } + } + }); + } + } + }); + } + + /** + * Add a listener of tree table selection model to expand a new selected + * node when it is selected. + * <p/> + * FIXME : Voir pour enlever le copier coller + * + * @param treeTable the tree to treate + */ + public static void addExpandOnClickListener(final JXTreeTable treeTable) { + + treeTable.addTreeSelectionListener(new TreeSelectionListener() { + + @Override + public void valueChanged(final TreeSelectionEvent e) { + TreeNode node = (TreeNode) e.getPath().getLastPathComponent(); + if (node != null && !node.isLeaf()) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + for (TreePath path : e.getPaths()) { + if (e.isAddedPath(path) && + !treeTable.isExpanded(path)) { + log.info("expand node [" + path + "]"); + // will expand the node + treeTable.expandPath(path); + } + } + } + }); + } + } + }); + } + + /** + * Set the width of the given component + * + * @param component the component to resize + * @param width the new width to apply + */ + 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(); + } + } + } + + /** + * Set the height of a given component. + * + * @param component the component to resize + * @param height the new height to apply + */ + 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 ImageIcon createIcon(String path) { + URL imgURL = JAXXUtil.class.getResource(path); + if (imgURL != null) { + return new ImageIcon(imgURL); + } else { + throw new IllegalArgumentException("could not find icon " + path); + } + } + + /** + * @param path the location of icons in root directory icons + * @return the icon at {@link #getIconPath()}+path + */ + public static ImageIcon createImageIcon(String path) { + String iconPath = getIconPath(); + return createIcon(iconPath + path); + } + + /** + * @param key the key of the icon to retreave from {@link UIManager} + * @return the icon, or <code>null if no icon found in {@link UIManager} + */ + public static Icon getUIManagerIcon(String key) { + return UIManager.getIcon(key); + } + + /** + * retreave for the {@link UIManager} the icon prefixed by {@code action}. + * + * @param key the key of the action icon to retreave from {@link UIManager} + * @return the icon, or <code>null if no icon found in {@link UIManager} + */ + public static Icon getUIManagerActionIcon(String key) { + return getUIManagerIcon("action." + key); + } + + public static ImageIcon createActionIcon(String name) { + String iconPath = getIconPath(); + return createIcon(iconPath + "action-" + name + ".png"); + } + + public static ImageIcon createI18nIcon(String name) { + String iconPath = getIconPath(); + return createIcon(iconPath + "i18n/" + name + ".png"); + } + + private static String getIconPath() { + String iconPath = UIManager.getString(DEFAULT_ICON_PATH_PROPERTY); + if (iconPath == null) { + iconPath = DEFAULT_ICON_PATH; + } else { + if (!iconPath.endsWith("/")) { + iconPath += "/"; + } + } + return iconPath; + } + + /** + * Add {@link java.awt.event.KeyListener} to focus next editable cell on TAB key + * + * @param table to add TAB {@link java.awt.event.KeyListener} + */ + public static void makeTableTabFocusable(final JTable table) { + table.setCellSelectionEnabled(true); + table.setSurrendersFocusOnKeystroke(true); + table.addKeyListener(new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_TAB) { + + // get table informations + int selectedColumn = table.getSelectedColumn(); + int selectedRow = table.getSelectedRow(); + + if (log.isDebugEnabled()) { + log.debug("Selected was row[" + selectedRow + "] column[" + selectedColumn + "]"); + } + + int columnCount = table.getColumnCount(); + int rowCount = table.getRowCount(); + + // search on current line + for (int toSelectColumn = selectedColumn; toSelectColumn < columnCount; toSelectColumn++) { + + if (editCell(table, selectedRow, toSelectColumn)) { + return; + } + } + + // search on other lines + for (int toSelectRow = selectedRow; toSelectRow < rowCount; toSelectRow++) { + for (int toSelectColumn = 0; toSelectColumn < columnCount; toSelectColumn++) { + + if (editCell(table, toSelectRow, toSelectColumn)) { + return; + } + } + } + } + } + }); + } + + /** + * Used to edit cell + * + * @param table to edit + * @param row of cell to editing + * @param colummn of cell to editing + * @return false if for any reason the cell cannot be edited, + * or if the indices are invalid + */ + public static boolean editCell(JTable table, int row, int colummn) { + + if (table.isCellEditable(row, colummn)) { + + // get table informations + int selectedColumn = table.getSelectedColumn(); + int selectedRow = table.getSelectedRow(); + + // stop edition + TableCellEditor cellEditor = table.getCellEditor(selectedRow, selectedColumn); + cellEditor.stopCellEditing(); + + // select row + table.setColumnSelectionInterval(colummn, colummn); + table.setRowSelectionInterval(row, row); + + // edit cell + boolean result = table.editCellAt(row, colummn, new EventObject(table)); + Component component = table.getEditorComponent(); + component.requestFocus(); + + if (log.isDebugEnabled()) { + log.debug("Select row[" + row + "] column[" + colummn + "] return : " + result); + } + return result; + } + return false; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/binding/DefaultJAXXBinding.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/binding/DefaultJAXXBinding.java new file mode 100644 index 0000000..b34dd98 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/binding/DefaultJAXXBinding.java @@ -0,0 +1,165 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.binding; + +import jaxx.runtime.JAXXBinding; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeEvent; + + +/** + * A <code>PropertyChangeListener</code> which processes a data binding when it receives a + * <code>PropertyChangeEvent</code>. + */ +public abstract class DefaultJAXXBinding implements JAXXBinding { + + /** Logger */ + private static final Log log = LogFactory.getLog(DefaultJAXXBinding.class); + + /** Counter of all bindings hits */ + private static long NB; + + /** Counter of current binding hits */ + private long nb; + + /** Id of the binding */ + private final String id; + + /** The source of the binding. */ + protected final JAXXObject source; + + /** + * flag to know {@code true} : if the binding was init from a generated + * jaxx object, {@code false} otherwise. + */ + protected final boolean defaultBinding; + + /** + * Internal state to reapply the binding after each fires :this is sometimes + * necessary when binding is complex. For example with this binding + * <pre> + * ui.getModel().getProperty() + * </pre> + * We need to listen two things : first listen on {@code ui} the + * modification of {@code model}, then on {@code model} the {@code property}. + * + * @since 2.4.2 + */ + protected final boolean reloadAfterFire; + + /** + * Creates a new Data binding which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param source the {@link JAXXObject} source of the binding + * @param id the name of the data binding to run + * @param defaultBinding flag to knwon if binding is coming from a generated jaxx object ({@code true}). + */ + public DefaultJAXXBinding(JAXXObject source, String id, + boolean defaultBinding) { + this(source, id, defaultBinding, false); + } + + /** + * Creates a new Data binding which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param source the {@link JAXXObject} source of the binding + * @param id the name of the data binding to run + * @param defaultBinding flag to know if binding is coming from a generated jaxx object ({@code true}). + * @param reloadAfterFire flag to know if the binding need to be reload after each fires + */ + public DefaultJAXXBinding(JAXXObject source, String id, + boolean defaultBinding, + boolean reloadAfterFire) { + this.source = source; + this.id = id; + this.defaultBinding = defaultBinding; + this.reloadAfterFire = reloadAfterFire; + } + + @Override + public String getId() { + return id; + } + + @Override + public JAXXObject getSource() { + return source; + } + + @Override + public boolean isDefaultBinding() { + return defaultBinding; + } + + @Override + public String toString() { + return super.toString() + ":" + id; + } + + private static final String LOG_START_PATTERN = ">> (hits:%1$5d, total:%2$5d) on %3$s"; + + private static final String LOG_END_PATTERN = "<< %4$3d (hits:%1$5d, total:%2$5d) on %3$s"; + + /** + * Processes the data binding in response to a <code>PropertyChangeEvent</code>. + * <p/> + * When the binding is wake up, delegate the process to the source object which + * can manage re-entrant code (can not process a re-entrant event). + * + * @param e the event which triggered the binding + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + long count = NB; + if (log.isDebugEnabled()) { + log.debug(String.format(LOG_START_PATTERN, ++nb, ++NB, this)); + } + //TODO-TC-20091202 perharps could we have a nicer way to process it, + // let the source deal with it to avoid re-entrant code + source.processDataBinding(id); + + //TODO-20091201 Must test on a lot of cases before next release 2.0.0-beta-2 + //TC-20091201 : I really don't see the point + // I comment the code, and still working fine ? Any trick + // for now, handle dependency changes by always removing & reapplying + // the binding. We should be more efficient and only do this when it's + // actually necessary + if (reloadAfterFire) { + JAXXUtil.reloadBinding(this); + } +// source.removeDataBinding(id); +// source.applyDataBinding(id); + if (log.isDebugEnabled()) { + log.debug(String.format(LOG_END_PATTERN, ++nb, ++NB, this, NB - count)); + } + } + +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/binding/SimpleJAXXObjectBinding.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/binding/SimpleJAXXObjectBinding.java new file mode 100644 index 0000000..bb02689 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/binding/SimpleJAXXObjectBinding.java @@ -0,0 +1,84 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.binding; + +import jaxx.runtime.JAXXObject; + +/** + * Created: 5 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @version $Revision$ + * <p/> + * Mise a jour: $Date$ par : + * $Author$ + */ +public abstract class SimpleJAXXObjectBinding extends DefaultJAXXBinding { + + protected final String[] propertyNames; + + /** + * Creates a new Data binding which will run the given data binding + * when it receives a <code>PropertyChangeEvent</code>. + * + * @param source the {@link JAXXObject} source of the binding + * @param id the name of the data binding to run + * @param defaultBinding flag to knwon if binding is coming from a generated jaxx object ({@code true}). + * @param propertyNames the name of properties to listen on source + */ + public SimpleJAXXObjectBinding(JAXXObject source, String id, boolean defaultBinding, String... propertyNames) { + super(source, id, defaultBinding); + if (propertyNames == null || propertyNames.length == 0) { + throw new IllegalArgumentException("must at least have one propertyName "); + } + this.propertyNames = propertyNames; + } + + public boolean canApply() { + return true; + } + + public String[] getPropertyNames() { + return propertyNames; + } + + @Override + public void applyDataBinding() { + if (canApply()) { + for (String s : propertyNames) { + source.addPropertyChangeListener(s, this); + } + } + } + + @Override + public void removeDataBinding() { + if (canApply()) { + for (String s : propertyNames) { + source.removePropertyChangeListener(s, this); + } + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DataContext.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DataContext.java new file mode 100644 index 0000000..2fc38e9 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DataContext.java @@ -0,0 +1,452 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.regex.Pattern; + +/** + * Un contexte de données qui permet l'utilisation des bindings sur les + * entrées du contexte. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public abstract class DataContext { + + /** Logger */ + static private Log log = LogFactory.getLog(DataContext.class); + + public static final DataContextEntry<?>[] EMPTY_DATA_CONTEXT_ENTRY_ARRAY = + new DataContextEntry<?>[0]; + + /** le context qui contient les données */ + protected final DefaultJAXXContext delegate; + + /** la definition de l'entree actuallement selectionnee */ + protected DataContextEntry<?> currentEntry; + + /** to manage properties modifications */ + protected final PropertyChangeSupport pcs; + + protected DataContextEntry<?>[] entries; + + protected final String[] DEFAULT_JAXX_PCS; + + public abstract String getContextPath(Object... e); + + public DataContext(String[] DEFAULT_JAXX_PCS, + DataContextEntry<?>[] entries) { + this.DEFAULT_JAXX_PCS = DEFAULT_JAXX_PCS; + this.entries = entries; + delegate = new DefaultJAXXContext() { + + @Override + protected void setParentContext(JAXXContext parentContext) { + throw new IllegalStateException( + "can not use this method for this type of context"); + } + + @Override + protected JAXXContext getParentContext() { + return null; + } + + @Override + public <T> void removeContextValue(Class<T> klazz, String name) { + if (log.isTraceEnabled()) { + log.trace(klazz + " - " + name); + } + super.removeContextValue(klazz, name); + } + + @Override + public <T> void setContextValue(T o, String name) { + if (log.isTraceEnabled()) { + log.trace(name + " - " + o.getClass()); + } + super.setContextValue(o, name); + } + }; + pcs = new PropertyChangeSupport(this); + } + + public DefaultJAXXContext getDelegate() { + return delegate; + } + + public Iterable<? extends DataContextEntry<?>> iterateOnAll() { + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries); + } + }; + } + + public Iterable<? extends DataContextEntry<?>> iterateToLevel( + final int level) { + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries, level); + } + }; + } + + public Iterable<? extends DataContextEntry<?>> reverseIterateOnAll() { + + return new Iterable<DataContextEntry<?>>() { + + @Override + public Iterator<DataContextEntry<?>> iterator() { + return new DataContextEntryIterator(entries, true); + } + }; + } + + public DataContextEntry<?> getCurrentEntry() { + return currentEntry; + } + + public DataContextEntry<?> getEntry(String path) { + for (DataContextEntry<?> scope : reverseIterateOnAll()) { + if (scope.acceptPath(path)) { + return scope; + } + } + return null; + } + + public DataContextEntry<?> getEntry(Class<?> type) { + for (DataContextEntry<?> scope : iterateOnAll()) { + if (scope.acceptType(type)) { + return scope; + } + } + return null; + } + + public <T> T getContextValue(DataContextEntry<T> entry, String key) { + String contextKey = getKey(entry, key); + T result = delegate.getContextValue(entry.getKlass(), contextKey); + return result; + } + + public void setContextValue(DataContextEntry<?> entry, + Object value, + String key) { + String contextKey = getKey(entry, key); + delegate.setContextValue(value, contextKey); + } + + /** + * @param entry + * @param klass + * @param key + */ + public void removeContextValue(DataContextEntry<?> entry, + Class<?> klass, + String key) { + String contextKey = getKey(entry, key); + delegate.removeContextValue(klass, key); + } + + public void removeContextValue(DataContextEntry<?> entry, + String key) { + String contextKey = getKey(entry, key); + delegate.removeContextValue(entry.getKlass(), contextKey); + } + + @SuppressWarnings("unchecked") + public void updateSelectedData(String path, + Object data, + UpdateDataContext updator) { + + if (log.isDebugEnabled()) { + log.debug("-----------------------------------------------------" + + "-----------"); + } + if (currentEntry != null) { + + if (log.isDebugEnabled()) { + log.debug("remove from old entry " + currentEntry); + } + for (DataContextEntry<?> s : currentEntry) { + if (log.isDebugEnabled()) { + log.debug("remove entry " + s); + } + updator.onRemovingData(this, s); + } + } + + currentEntry = getEntry(path); + + if (log.isDebugEnabled()) { + log.debug("new entry " + currentEntry + " for path " + path); + } + + if (currentEntry != null) { + + for (DataContextEntry<?> s : + iterateToLevel(currentEntry.getLevel())) { + + if (log.isDebugEnabled()) { + log.debug("add entry " + s); + } + updator.onAddingData(this, s, path); + } + } + } + + 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 synchronized boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners( + String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + public void removeJaxxPropertyChangeListener() { + PropertyChangeListener[] toRemove = + JAXXUtil.findJaxxPropertyChangeListener( + DEFAULT_JAXX_PCS, getPropertyChangeListeners()); + if (toRemove == null || toRemove.length == 0) { + return; + } + if (log.isDebugEnabled()) { + log.debug("before remove : " + getPropertyChangeListeners().length); + log.debug("toRemove : " + toRemove.length); + } + for (PropertyChangeListener listener : toRemove) { + removePropertyChangeListener(listener); + } + if (log.isDebugEnabled()) { + log.debug("after remove : " + getPropertyChangeListeners().length); + } + } + + protected void firePropertyChange(String name, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(name, oldValue, newValue); + } + + protected String getKey(DataContextEntry<?> entry, String key) { + String result = null; + if (key != null) { + result = entry.hashCode() + "#" + key; + } + return result; + } + + public void close() throws Exception { + clear(); + + // suppression des ecouteurs + + for (PropertyChangeListener l : getPropertyChangeListeners()) { + removePropertyChangeListener(l); + } + } + + public void clear() { + delegate.clear(); + } + + public static abstract class DataContextEntry<E> implements Iterable<DataContextEntry<?>> { + + private final int level; + + private final DataContextEntry<?> previous; + + private final DataContextEntry<?>[] parents; + + private Class<E> klass; + + public DataContextEntry(Class<E> klass, DataContextEntry<?> previous) { + this.previous = previous; + level = previous.level + 1; + this.klass = klass; + parents = new DataContextEntry<?>[level]; + int i = level; + while (i > 0) { + parents[--i] = previous; + previous = previous.previous; + } + } + + public DataContextEntry(Class<E> klass) { + level = 0; + this.klass = klass; + previous = null; + parents = EMPTY_DATA_CONTEXT_ENTRY_ARRAY; + } + + public Class<E> getKlass() { + return klass; + } + + public int getLevel() { + return level; + } + + public DataContextEntry<?>[] getParents() { + return parents; + } + + public abstract Pattern getPattern(); + + public abstract String getContextPath(Object... args); + + public boolean acceptPath(String path) { + return getPattern().matcher(path).matches(); + } + + public boolean acceptType(Class<?> type) { + return klass.isAssignableFrom(type); + } + + @Override + public Iterator<DataContextEntry<?>> iterator() { + int length = parents.length; + DataContextEntry<?>[] t = new DataContextEntry<?>[length + 1]; + System.arraycopy(parents, 0, t, 0, length); + t[length] = this; + return new DataContextEntryIterator(t, true); + } + + @Override + public String toString() { + return super.toString() + "<type: " + klass.getSimpleName() + ">"; + } + } + + public interface UpdateDataContext<D extends DataContext> { + + void onRemovingData(D context, DataContextEntry<D> entry); + + void onAddingData(D context, DataContextEntry<D> entry, String path); + } + + public static class DataContextEntryIterator implements Iterator<DataContextEntry<?>> { + + protected final DataContextEntry<?>[] datas; + + protected final boolean reverse; + + protected final int level; + + protected int index; + + public DataContextEntryIterator(DataContextEntry<?>[] datas) { + this(datas, false, -1); + } + + public DataContextEntryIterator(DataContextEntry<?>[] datas, + int level) { + this(datas, false, level); + } + + public DataContextEntryIterator(DataContextEntry<?>[] datas, + boolean reverse) { + this(datas, reverse, -1); + } + + DataContextEntryIterator(DataContextEntry<?>[] datas, + boolean reverse, + int level) { + this.datas = datas; + this.reverse = reverse; + if (reverse) { + index = datas.length; + } else { + index = -1; + } + this.level = level; + } + + @Override + public boolean hasNext() { + if (reverse) { + return index > 0; + } else { + return index + 1 < datas.length && + (level == -1 || datas[index + 1].getLevel() <= level); + } + } + + @Override + public DataContextEntry<?> next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + if (reverse) { + index--; + } else { + index++; + } + return datas[index]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("Not supported yet."); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultApplicationContext.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultApplicationContext.java new file mode 100644 index 0000000..99bce2e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultApplicationContext.java @@ -0,0 +1,476 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.JAXXContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +/** + * The default context to be used for an application. + * <p/> + * This extends the {@link DefaultJAXXContext} and add a possibility to + * auto-instanciate some classes asked via {@link #getContextValue(Class)} and + * {@link #getContextValue(Class, String)} methods. + * <p/> + * To registred a such class, just annotate your class with {@link AutoLoad}. + * + * @author tchemit <chemit@codelutin.com> + * @see DefaultJAXXContext + * @since 1.2 + */ +public class DefaultApplicationContext extends DefaultJAXXContext { + + /** + * A class annotated @AutoLoad is used by context to auto instanciate + * the class when required. + * <p/> + * Note : A such class always have a public default constructor. + * + * @author tchemit <chemit@codelutin.com> + * @version 1.0, 21/02/09 + * @since 1.2 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface AutoLoad { + //TODO use this to add a method to init + + String initMethod() default ""; + } + + /** + * A class annotated @MethodAccess is used by context to obtain the + * value of an entry via a declared method. + * <p/> + * Note : A such class must have a method called {@link #methodName()} with + * a single String parameter. + * + * @author tchemit <chemit@codelutin.com> + * @version 1.0, 21/02/09 + * @since 1.2 + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface MethodAccess { + + /** + * Define a forward to a target class. When the target class will be + * asked with method {@link JAXXContext#getContextValue(Class, String)} + * it will be delegating to this class. + * + * @return the forwarded class + */ + Class<?> target() default Object.class; + + /** @return the name of the method to access data */ + String methodName(); + } + + /** Map of forwarded classes (key) to classes (values). */ + protected Map<Class<?>, Class<?>> forwards; + + /** + * Map of entries to watch associated with the property to fires if a + * modification was found. + */ + protected Map<JAXXContextEntryDef<?>, String> entryListened; + + public DefaultApplicationContext() { + forwards = new HashMap<Class<?>, Class<?>>(); + pcs = new PropertyChangeSupport(this); + } + + /** Logger */ + static private final Log log = + LogFactory.getLog(DefaultApplicationContext.class); + + /** to manage properties modifications */ + protected PropertyChangeSupport pcs; + + @SuppressWarnings({"unchecked"}) + @Override + public <T> T getContextValue(Class<T> clazz, String name) { + Object value; + MethodAccess access; + + Class<?> realClass; + + if (forwards.containsKey(clazz)) { + // this is a forward class + realClass = forwards.get(clazz); + // always call the forwarder with no name + value = getContextValue(realClass, null); + if (log.isDebugEnabled()) { + log.debug("detect forward from " + clazz + " to " + realClass + + " (" + value + ")"); + } + + } else { + realClass = clazz; + value = super.getContextValue(realClass, name); + } + + //TC-20091007 TODO Make possible use of named autoload entries + //(add a parameter on AutoLoad annotation) + if (value == null) { + AutoLoad anno = clazz.getAnnotation(AutoLoad.class); + + if (anno == null) { + // no annotation, so do nothing + return null; + } + + if (name != null) { + throw new IllegalArgumentException( + "an " + AutoLoad.class.getName() + " can not have " + + "a named context but was call with this one : " + name); + } + value = newInstance(clazz); + if (!anno.initMethod().trim().isEmpty()) { + // apply method on class + newAccess(clazz, value, anno.initMethod().trim()); + } + if (log.isDebugEnabled()) { + log.debug("new instance " + clazz + " : " + value); + } + // save new instance + setContextValue(value, null); + } + + access = realClass.getAnnotation(MethodAccess.class); + + if (access != null) { + if (name == null) { + if (!Object.class.equals(access.target())) { + // register forward + Class<?> targetClass = access.target(); + if (!forwards.containsKey(targetClass)) { + // register forward + forwards.put(targetClass, clazz); + if (log.isDebugEnabled()) { + log.debug("register forward from " + targetClass + + " to " + clazz); + } + } + } + } else { + // specialized access + value = newAccess(realClass, value, access.methodName(), name); + } + } + return (T) value; + } + + @Override + public <T> void removeContextValue(Class<T> klass, String name) { + Entry<Class<?>, Class<?>> entry; + if (name == null && forwards.containsValue(klass)) { + // remove forward + Iterator<Entry<Class<?>, Class<?>>> itr = + forwards.entrySet().iterator(); + while (itr.hasNext()) { + entry = itr.next(); + if (entry.getValue().equals(klass)) { + itr.remove(); + if (log.isDebugEnabled()) { + log.debug("removed forward from " + entry.getKey() + + " to " + klass); + } + break; + } + } + } + //FIXME should update forwards state + JAXXContextEntryDef<?> entryToDel = getEntry(klass, name); + Object t = remove0(klass, name); + if (log.isDebugEnabled()) { + log.debug("removed object = " + t); + } + if (t != null && entryToDel != null) { + // a value was removed + // notify listeners + fireEntryChanged(entryToDel, t, null); + } +// super.removeContextValue(klass, name); + } + + @Override + public <T> void setContextValue(T o, String name) { +// super.setContextValue(o, name); + if (name == null && 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); + if (log.isDebugEnabled()) { + log.debug("[" + name + "] set value for entry " + entry); + } + // firezs + fireEntryChanged(entry.getKlass(), name, oldValue, o); + } + + /** + * To add a listen modification of the given entry in the context. + * + * @param entry the entry to listen + * @param name the property name to fire if necessary + * @param listener the listener to notify if entry has changed + * @since 2.0.1 + */ + public void addPropertyChangeListener(JAXXContextEntryDef<?> entry, + String name, + PropertyChangeListener listener) { + if (entryListened == null) { + entryListened = new HashMap<JAXXContextEntryDef<?>, String>(); + } + entryListened.put(entry, name); + if (log.isDebugEnabled()) { + log.debug("[" + name + "] for " + entry); + } + pcs.addPropertyChangeListener(name, listener); + } + + /** + * To remove a listen modification of the given entry in the context. + * + * @param entry the entry to listen + * @param name the property name to fire if necessary + * @param listener the listener to notify if entry has changed + * @since 2.0.1 + */ + public void removePropertyChangeListener(JAXXContextEntryDef<?> entry, + String name, + PropertyChangeListener listener) { + if (entryListened == null) { + entryListened = new HashMap<JAXXContextEntryDef<?>, String>(); + } + entryListened.remove(entry); + pcs.removePropertyChangeListener(name, listener); + } + + 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 synchronized boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners( + String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + protected void fireEntryChanged(Class<?> klass, + String name, + Object oldValue, + Object newValue) { + // a value was removed + if (entryListened != null) { + // look if the entry was listened + + if (log.isTraceEnabled()) { + log.trace("data size : " + data.size()); + for (Entry<JAXXContextEntryDef<?>, Object> e : data.entrySet()) { + log.trace(e.getKey()); + } + } + JAXXContextEntryDef<?> entry2 = getEntry(klass, name); + if (log.isDebugEnabled()) { + log.debug("[" + name + "] : try to find a changer for " + entry2); + } + if (entry2 != null) { + // entry find directly on this context + String propertyName = entryListened.get(entry2); + if (log.isTraceEnabled()) { + log.trace("registred property name = " + propertyName); + } + if (propertyName != null) { + if (log.isDebugEnabled()) { + log.debug("will notify modification on " + entry2); + } + // fires the removed + firePropertyChange(propertyName, oldValue, newValue); + } + } + } + } + + protected void fireEntryChanged(JAXXContextEntryDef<?> entryDef, + Object oldValue, + Object newValue) { + // a value was removed + if (entryListened != null) { + // look if the entry was listened + + if (log.isTraceEnabled()) { + log.trace("data size : " + data.size()); + for (Entry<JAXXContextEntryDef<?>, Object> e : data.entrySet()) { + log.trace(e.getKey()); + } + } +// JAXXContextEntryDef<?> entry2 = getEntry(klass, name); +// if (log.isDebugEnabled()) { +// log.debug("[" + name + "] : try to find a changer for " + entry2); +// } + if (entryDef != null) { + // entry find directly on this context + String propertyName = entryListened.get(entryDef); + if (log.isTraceEnabled()) { + log.trace("registred property name = " + propertyName); + } + if (propertyName != null) { + if (log.isDebugEnabled()) { + log.debug("will notify modification on " + entryDef); + } + // fires the removed + firePropertyChange(propertyName, oldValue, newValue); + } + } + } + } + + protected Object newInstance(Class<?> clazz) throws + IllegalArgumentException { + + Object value; + + Constructor<?> constructor; + try { + constructor = clazz.getConstructor(); + // auto instanciate the class + if (constructor == null) { + throw new IllegalArgumentException( + clazz + " has no public constructor"); + } + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException(ex); + } catch (SecurityException ex) { + throw new IllegalArgumentException(ex); + } + try { + value = constructor.newInstance(); + + } catch (InstantiationException ex) { + throw new IllegalArgumentException(ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException(ex); + } catch (InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + return value; + } + + protected Object newAccess( + Class<?> clazz, + Object parent, + String methodName, + String name) throws IllegalArgumentException { + Object value; + try { + Method m = clazz.getMethod(methodName, String.class); + value = m.invoke(parent, name); + return value; + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException(ex); + } catch (SecurityException ex) { + throw new IllegalArgumentException(ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException(ex); + } catch (InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + } + + protected Object newAccess( + Class<?> clazz, + Object parent, + String methodName) throws IllegalArgumentException { + Object value; + try { + Method m = clazz.getMethod(methodName); + value = m.invoke(parent); + return value; + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException(ex); + } catch (SecurityException ex) { + throw new IllegalArgumentException(ex); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException(ex); + } catch (InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + } + + protected void firePropertyChange(String name, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(name, oldValue, newValue); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultJAXXContext.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultJAXXContext.java new file mode 100644 index 0000000..b96a6e0 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/DefaultJAXXContext.java @@ -0,0 +1,232 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +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 tchemit <chemit@codelutin.com> + */ +public class DefaultJAXXContext implements JAXXContext { + + /** entry of the parent context */ + protected static final JAXXContextEntryDef<JAXXContext> + PARENT_CONTEXT_ENTRY = JAXXUtil.newContextEntryDef(JAXXContext.class); + + /** Logger */ + static private final Log log = LogFactory.getLog(DefaultJAXXContext.class); + + /** 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>(); + } + + @Override + public <T> void setContextValue(T o) { + setContextValue(o, null); + } + + @Override + public <T> void setContextValue(T o, String name) { + if (name == null && 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); + } + + @Override + public <T> T getContextValue(Class<T> clazz) { + return getContextValue(clazz, null); + } + + @SuppressWarnings({"unchecked"}) + @Override + public <T> T getContextValue(Class<T> clazz, String name) { + if (parentContext != null && + parentContext.getClass().equals(clazz) || + 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.equals(clazz)) { + // no seek in the parent context, since we are already looking + // for it + return null; + } + + JAXXContext parent = getParentContext(); + if (parent == null) { + // no parent context, so no value find + return null; + } + // seek in parent context + return parent.getContextValue(clazz, name); + } + + @Override + public <T> void removeContextValue(Class<T> klazz) { + removeContextValue(klazz, null); + } + + @Override + public <T> void removeContextValue(Class<T> klazz, String name) { + remove0(klazz, name); + } + + /** + * Obtain all the keys of data for a given type. + * + * @param klass the type of searched keys + * @return the array of all names of keys for the given type of data + * @since 1.3 + */ + public String[] getKeys(Class<?> klass) { + List<String> keys = new ArrayList<String>(); + for (JAXXContextEntryDef<?> key : data.keySet()) { + if (key.getKlass().equals(klass)) { + keys.add(key.getName()); + } + } + return keys.toArray(new String[keys.size()]); + + } + + public void clear() { + data.clear(); + } + + protected JAXXContextEntryDef<?> getKey(String name, Class<?> klass) { + //FIXME-TC20100322 : must change this to have a store, we instanciate + // a new object each time we wants to deal with the context... + return JAXXUtil.newContextEntryDef(name, klass); + } + + @SuppressWarnings({"unchecked"}) + protected <T> T remove0(Class<T> klass, String name) { + if (PARENT_CONTEXT_ENTRY.accept(klass, name)) { + JAXXContext old = getParentContext(); + setParentContext(null); + return (T) old; + } + JAXXContextEntryDef<?> entry = getEntry(klass, name); +// JAXXContextEntryDef<?> entry = null; +// for (JAXXContextEntryDef<?> entryDef : data.keySet()) { +// if (entryDef.accept(klass, name)) { +// entry = entryDef; +// break; +// } +// } + if (entry != null) { + return (T) data.remove(entry); + } + + if (JAXXContext.class.equals(klass)) { + return null; + } + + // try on parent + JAXXContext parent = getParentContext(); + + if (parent == null) { + // no parent, stop now, can not found entry + return null; + } + + if (parent instanceof DefaultJAXXContext) { + // try now on the parent + return ((DefaultJAXXContext) parent).remove0(klass, name); + } + + // can not find the entry anywhere, so says that nothing was removed + return null; + } + + protected JAXXContextEntryDef<?> getEntry(Class<?> klass, String name) { + JAXXContextEntryDef<?> entry = null; + for (JAXXContextEntryDef<?> entryDef : data.keySet()) { + if (entryDef.accept(klass, name)) { + entry = entryDef; + break; + } + } + return entry; + } + + 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; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXContextEntryDef.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXContextEntryDef.java new file mode 100644 index 0000000..d31f2e1 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXContextEntryDef.java @@ -0,0 +1,141 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.JAXXContext; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * To qualify an entry in a {@link JAXXContext}. + * <p/> + * Use the factory methods <code>newContextEntryDef</code> and + * <code>newListContextEntryDef</code< to obtain new instances. + * + * @param <O> type of the entry associated to the definition + * @author tchemit <chemit@codelutin.com> + */ +public class JAXXContextEntryDef<O> implements 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 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 + ">"; + } + + public JAXXContextEntryDef(Class<O> klass) { + this(null, klass); + } + + /** + * Special constructor for map, otherwise it is not possible to cast to O + * + * @param mapClass map class + * @param name name of content + * @since 2.0.2 + */ + @SuppressWarnings({"unchecked"}) + public JAXXContextEntryDef(Class<Map> mapClass, String name) { + this(name, (Class<O>) mapClass); + } + + @SuppressWarnings("unchecked") + public JAXXContextEntryDef(String name, Class<O> klass) { + if (klass == null) { + throw new IllegalArgumentException("class can not be null"); + } + this.name = name; + if (List.class.isAssignableFrom(klass)) { + klass = (Class<O>) List.class; + } + this.klass = klass; + } + + @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 (Object.class.equals(klass) && !Object.class.equals(this.klass)) { + // 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 !(Object.class.equals(klass) && + !Object.class.equals(this.klass)) && + this.klass.isAssignableFrom(klass) && + (this.name == null && name == null || + (this.name != null && name != null && this.name.equals(name)) + ); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXInitialContext.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXInitialContext.java new file mode 100644 index 0000000..dedfc0e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/context/JAXXInitialContext.java @@ -0,0 +1,121 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; + +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((String) 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; + } + + /** + * Register a named (or not) value in the context. + * + * @param <O> type of data to add + * @param def definition of entry + * @param value the value to registred + * @return the instance of the context + */ + public <O> JAXXInitialContext add(JAXXContextEntryDef<O> def, O value) { + super.setContextValue(value, def.getName()); + 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 UnsupportedOperationException(); + } + + @Override + public void setContextValue(Object o, String name) { + throw new UnsupportedOperationException(); + } + + @Override + public <T> void removeContextValue(Class<T> klazz) { + throw new UnsupportedOperationException(); + } + + @Override + public <T> void removeContextValue(Class<T> klazz, String name) { + throw new UnsupportedOperationException(); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/DataBinding.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/DataBinding.java new file mode 100644 index 0000000..1d0d82f --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/DataBinding.java @@ -0,0 +1,52 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.css; + +/** + * Represents a data binding bound to an attribute at runtime. Used by {@link Pseudoclasses} to keep + * track of which data bindings are in effect. + */ +public class DataBinding { + + private String id; + + public DataBinding(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + @Override + public boolean equals(Object o) { + return o instanceof DataBinding && ((DataBinding) o).getId().equals(getId()); + } + + @Override + public int hashCode() { + return id.hashCode(); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Pseudoclasses.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Pseudoclasses.java new file mode 100644 index 0000000..cd3dd4e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Pseudoclasses.java @@ -0,0 +1,205 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.css; + +import jaxx.runtime.JAXXObject; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +public class Pseudoclasses { + + public static final String NO_PSEUDOCLASS = "no pseudoclass"; + + private static Map<Object, Map<String, List<PropertyValue>>> properties = new WeakHashMap<Object, Map<String, List<PropertyValue>>>(); + + private static class PropertyValue implements Comparable<PropertyValue> { + + private Object value; + + private int id; + + public PropertyValue(Object value, int id) { + this.value = value; + this.id = id; + } + + public Object getValue() { + return value; + } + + public int getId() { + return id; + } + + @Override + public int compareTo(PropertyValue o) { + return getId() - o.getId(); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof PropertyValue)) { + return false; + } + PropertyValue that = (PropertyValue) o; + if (that.getId() != getId()) { + return false; + } + if (that.getValue() == null) { + return getValue() == null; + } + return that.getValue().equals(getValue()); + } + + @Override + public int hashCode() { + return (value != null ? value.hashCode() : 0) ^ id; + } + + @Override + public String toString() { + return "PropertyValue[" + value + ", " + id + "]"; + } + } + + private static List<PropertyValue> getPropertyList(Object object, String property) { + Map<String, List<PropertyValue>> propertyMap = properties.get(object); + if (propertyMap == null) { + propertyMap = new HashMap<String, List<PropertyValue>>(); + properties.put(object, propertyMap); + } + + List<PropertyValue> propertyList = propertyMap.get(property); + if (propertyList == null) { + propertyList = new ArrayList<PropertyValue>(); + propertyMap.put(property, propertyList); + } + + return propertyList; + } + + public static boolean isPropertyApplied(Object object, String property, int id) { + for (PropertyValue aPropertyList : getPropertyList(object, property)) { + if (aPropertyList.getId() == id) { + return true; + } + } + return false; + } + + public static void propertyApplied(Object object, String property, Object value, int id) { + List<PropertyValue> propertyList = getPropertyList(object, property); + propertyList.add(new PropertyValue(value, id)); + Collections.sort(propertyList); + } + + public static void propertyRemoved(Object object, String property, Object value, int id) { + List<PropertyValue> propertyList = getPropertyList(object, property); + propertyList.remove(new PropertyValue(value, id)); + } + + public static Object getCurrentValue(Object object, String property) { + List<PropertyValue> propertyList = getPropertyList(object, property); + if (propertyList.size() > 0) { + return propertyList.get(propertyList.size() - 1).getValue(); + } + return NO_PSEUDOCLASS; + } + + public static Object applyProperty(JAXXObject parent, Object object, String property, Object newValue, Object currentValue, int id) { + if (!isPropertyApplied(object, property, id)) { + Object value = getCurrentValue(object, property); + if (value == NO_PSEUDOCLASS) { + propertyApplied(object, property, wrap(currentValue), -1); + } + propertyApplied(object, property, wrap(newValue), id); + value = getCurrentValue(object, property); + if (value instanceof DataBinding) { + parent.applyDataBinding(((DataBinding) value).getId()); + } + return value; + } else { + return currentValue; + } + } + + public static Object removeProperty(JAXXObject parent, Object object, String property, Object oldValue, Object currentValue, int id) { + if (isPropertyApplied(object, property, id)) { + Object value = getCurrentValue(object, property); + if (value == NO_PSEUDOCLASS) { + throw new IllegalStateException("found NO_PSEUDOCLASS value for a property which does not have a default value"); + } + if (value instanceof DataBinding) { + parent.removeDataBinding(((DataBinding) value).getId()); + } + propertyRemoved(object, property, wrap(oldValue), id); + value = getCurrentValue(object, property); + return value; + } else { + return currentValue; + } + } + + public static Object wrap(boolean value) { + return value; + } + + public static Object wrap(byte value) { + return value; + } + + public static Object wrap(short value) { + return value; + } + + public static Object wrap(int value) { + return value; + } + + public static Object wrap(long value) { + return value; + } + + public static Object wrap(float value) { + return value; + } + + public static Object wrap(double value) { + return value; + } + + public static Object wrap(char value) { + return value; + } + + public static Object wrap(Object value) { + return value; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Rule.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Rule.java new file mode 100644 index 0000000..7b77981 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Rule.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.css; + +import java.util.Map; + +public class Rule implements java.io.Serializable, Comparable<Rule> { + + 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; + java.util.Arrays.sort(selectors); + this.properties = properties; + } + + public Rule(Selector[] selectors, String[] keys, String[] values) { + this.selectors = selectors; + java.util.Arrays.sort(selectors); + this.properties = new java.util.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 Selector[] getSelectors() { + return selectors; + } + + public Map<String, String> getProperties() { + return properties; + } + + @Override + public int compareTo(Rule o) { + return selectors[0].compareTo(o.selectors[0]); // they are already sorted so we only need to compare the highest-ranked from each one + } + + @Override + public String toString() { + return "Rule[" + java.util.Arrays.asList(selectors) + ", " + properties + "]"; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Selector.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Selector.java new file mode 100644 index 0000000..a2c648e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Selector.java @@ -0,0 +1,122 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.css; + +public class Selector implements java.io.Serializable, Comparable<Selector> { + + public static final int NEVER_APPLIES = 0; + + public static final int PSEUDOCLASS_APPLIES_INHERIT_ONLY = 1; + + public static final int PSEUDOCLASS_APPLIES = 2; + + public static final int ALWAYS_APPLIES_INHERIT_ONLY = 3; + + public static final int ALWAYS_APPLIES = 4; + + private String javaClassName; + + private String styleClass; + + private String pseudoClass; + + private String id; + + private boolean inline; + + private static final long serialVersionUID = 1L; + + public Selector(String javaClassName, String styleClass, String pseudoClass, String id) { + this(javaClassName, styleClass, pseudoClass, id, false); + } + + public Selector(String javaClassName, String styleClass, String pseudoClass, String id, boolean inline) { + this.javaClassName = javaClassName; + this.styleClass = styleClass; + this.pseudoClass = pseudoClass; + this.id = id; + this.inline = inline; + } + + public String getJavaClassName() { + return javaClassName; + } + + public String getStyleClass() { + return styleClass; + } + + public String getPseudoClass() { + return pseudoClass; + } + + public String getId() { + return id; + } + + public boolean isInline() { + return inline; + } + + @Override + public int compareTo(Selector selector) { + if (inline && !selector.inline) { + return 1; + } + if (!inline && selector.inline) { + return -1; + } + if (pseudoClass != null && selector.pseudoClass == null) { + return 1; + } + if (pseudoClass == null && selector.pseudoClass != null) { + return -1; + } + if (id != null && selector.id == null) { + return 1; + } + if (id == null && selector.id != null) { + return -1; + } + if (styleClass != null && selector.styleClass == null) { + return 1; + } + if (styleClass == null && selector.styleClass != null) { + return -1; + } + if (javaClassName != null && selector.javaClassName == null) { + return 1; + } + if (javaClassName == null && selector.javaClassName != null) { + return -1; + } + return 0; + } + + @Override + public String toString() { + return "Selector[" + javaClassName + ", " + styleClass + ", " + pseudoClass + ", " + id + "]"; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Stylesheet.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Stylesheet.java new file mode 100644 index 0000000..7d65ba4 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/css/Stylesheet.java @@ -0,0 +1,66 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.css; + +public class Stylesheet implements java.io.Serializable { + + private Rule[] rules; + + private static final long serialVersionUID = 1L; + + public Stylesheet() { + rules = new Rule[0]; + } + + public Stylesheet(Rule[] rules) { + this.rules = rules; + java.util.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; + java.util.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); + java.util.Arrays.sort(rules); + } + + @Override + public String toString() { + return "Stylesheet" + java.util.Arrays.asList(rules); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Application.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Application.java new file mode 100644 index 0000000..5ae0a05 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Application.java @@ -0,0 +1,75 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import java.awt.GraphicsConfiguration; + +public class Application extends JFrame { + + private static final long serialVersionUID = 1L; + // Special: jaxxc will automatically add a main() method to any components which + // extend <Application> + + public Application() { + } + + public Application(GraphicsConfiguration gc) { + super(gc); + } + + public Application(String title) { + super(title); + } + + public Application(String title, GraphicsConfiguration gc) { + super(title, gc); + } + + public void setLookAndFeel(String lookAndFeel) { + if (lookAndFeel.equals("system")) { + lookAndFeel = UIManager.getSystemLookAndFeelClassName(); + } else if (lookAndFeel.equals("cross_platform")) { + lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName(); + } + try { + UIManager.setLookAndFeel(lookAndFeel); + if (isDisplayable()) { + SwingUtilities.updateComponentTreeUI(this); + } + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (UnsupportedLookAndFeelException e) { + throw new RuntimeException(e); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java new file mode 100644 index 0000000..07dde26 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java @@ -0,0 +1,345 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import org.jdesktop.jxlayer.JXLayer; +import org.jdesktop.jxlayer.plaf.AbstractLayerUI; + +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.util.Arrays; +import java.util.List; + +/** + * A JXLayer ui implementation that permits to block a component but still + * allow an action when clicking on the right-top icon painted on the layer. + * <p/> + * You can change the blocking and accepting icon. + * <p/> + * To hook an click on the layer's icon, you can : + * <p/> + * <ul><li>pass an Action via method {@link #setAcceptAction(Action)}</li> + * <li>override the method {@link #acceptEvent(MouseEvent, JXLayer)}</li> + * </ul> + * + * @author tchemit <chemit@codelutin.com> + * @since 1.2 + */ +public class BlockingLayerUI extends AbstractLayerUI<JComponent> { + + public static final String CAN_CLICK_PROPERTY = "canClick"; + + public static final String ACCEPT_ICON_PROPERTY = "acceptIcon"; + + public static final String BLOCK_ICON_PROPERTY = "blockIcon"; + + public static final String BLOCK_PROPERTY = "block"; +// private static final long serialVersionUID = 1L; + + /** Action to be treated when click on icon */ + protected Action acceptAction; + + /** Icon when you can not click */ + protected BufferedImage blockIcon; + + /** Icon when you can click */ + protected BufferedImage acceptIcon; + + /** Optinal color to put fill background when blocking */ + protected Color blockingColor; + + /** Internal state to known when we can accept click */ + protected boolean canClick; + + /** + * A flag to enable or disable the use of the icon. + * <p/> + * If set to false, no icon will be displayed and no action + * will be possible. + * <p/> + * By default, this is active. + */ + protected boolean useIcon = true; + + /** Internal state when should block event and paint layer */ + protected boolean block; + + /** Extra components names to accept even in block mode */ + protected List<String> acceptedComponentNames; + + public void setAcceptedComponentNames(String... acceptedComponentNames) { + this.acceptedComponentNames = Arrays.asList(acceptedComponentNames); + setDirty(true); + } + + public void setAcceptAction(Action acceptAction) { + this.acceptAction = acceptAction; + } + + public void setAcceptIcon(ImageIcon acceptIcon) { + this.acceptIcon = prepareIcon(acceptIcon); + firePropertyChange(ACCEPT_ICON_PROPERTY, null, acceptIcon); + setDirty(true); + } + + public void setBlockIcon(ImageIcon blockIcon) { + this.blockIcon = prepareIcon(blockIcon); + firePropertyChange(BLOCK_ICON_PROPERTY, null, blockIcon); + setDirty(true); + } + + public void setCanClick(boolean canClick) { + boolean oldvalue = this.canClick; + this.canClick = canClick; + firePropertyChange(CAN_CLICK_PROPERTY, oldvalue, canClick); + if (oldvalue != canClick) { + setDirty(true); + } + } + + public void setBlock(boolean block) { + boolean oldvalue = this.block; + this.block = block; + firePropertyChange(BLOCK_PROPERTY, oldvalue, block); + if (oldvalue != block) { + setDirty(true); + } + } + + @Override + public void setDirty(boolean isDirty) { + super.setDirty(isDirty); + } + + public void setBlockIcon(BufferedImage blockIcon) { + this.blockIcon = blockIcon; + } + + public void setBlockingColor(Color blockingColor) { + this.blockingColor = blockingColor; + } + + public BufferedImage getBlockIcon() { + return blockIcon; + } + + protected BufferedImage getAcceptIcon() { + return acceptIcon; + } + + public boolean isCanClick() { + return canClick; + } + + public void setUseIcon(boolean useIcon) { + boolean oldvalue = this.useIcon; + this.useIcon = useIcon; + if (oldvalue != useIcon) { + setDirty(true); + } + } + + @Override + public BlockingLayerUI clone() { + BlockingLayerUI clone = new BlockingLayerUI(); + clone.acceptAction = acceptAction; + clone.acceptIcon = acceptIcon; + clone.blockIcon = blockIcon; + clone.useIcon = useIcon; + clone.block = block; + clone.blockingColor = blockingColor; + clone.setCanClick(false); + return clone; + } + + @Override + protected void processKeyEvent(KeyEvent e, JXLayer<? extends JComponent> l) { + if (useIcon) { + e.consume(); + return; + } + + if (block) { + Object source = e.getSource(); + if (!(source instanceof JComponent)) { + e.consume(); + return; + } + JComponent comp = (JComponent) source; + String compName = comp.getName(); + if (acceptedComponentNames == null || + !acceptedComponentNames.contains(compName)) { + e.consume(); + } + } + } + + @Override + protected void processMouseMotionEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (useIcon) { + updateCanClickState(l, e); + e.consume(); + } + + if (block) { + Object source = e.getSource(); + if (!(source instanceof JComponent)) { + e.consume(); + return; + } + JComponent comp = (JComponent) source; + String compName = comp.getName(); + if (acceptedComponentNames == null || + !acceptedComponentNames.contains(compName)) { + e.consume(); + } + } + } + + @Override + protected void processMouseEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (useIcon) { + switch (e.getID()) { + case MouseEvent.MOUSE_ENTERED: + updateCanClickState(l, e); + break; + case MouseEvent.MOUSE_EXITED: + setCanClick(false); + break; + case MouseEvent.MOUSE_CLICKED: + if (canClick) { + acceptEvent(e, l); + } + break; + } + } + if (useIcon) { + + e.consume(); + return; + } + + if (block) { + Object source = e.getSource(); + if (!(source instanceof JComponent)) { + e.consume(); + return; + } + JComponent comp = (JComponent) source; + String compName = comp.getName(); + if (acceptedComponentNames == null || + !acceptedComponentNames.contains(compName)) { + e.consume(); + return; + } + switch (e.getID()) { + case MouseEvent.MOUSE_ENTERED: + break; + case MouseEvent.MOUSE_EXITED: + break; + case MouseEvent.MOUSE_CLICKED: + acceptEvent(e, l); + break; + } + } + + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + if (block && blockingColor != null) { + // to be in sync with the view if the layer has a border + /*Insets layerInsets = l.getInsets(); + g2.translate(layerInsets.left, layerInsets.top); + + JComponent view = l.getView(); + // To prevent painting on view's border + Insets insets = view.getInsets(); + g2.clip(new Rectangle(insets.left, insets.top, + view.getWidth() - insets.left - insets.right, + view.getHeight() - insets.top - insets.bottom)); + */ + + g2.setColor(blockingColor); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f)); + g2.fillRect(0, 0, l.getWidth(), l.getHeight()); + } + if (useIcon && getCurrentIcon() != null) { + g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null); + } + } + + protected void acceptEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (acceptAction != null) { + acceptAction.putValue("layer", l); + Component source = l.getView(); + acceptAction.actionPerformed(new ActionEvent(source, 0, "accept")); + } + } + + protected BufferedImage getCurrentIcon() { + return canClick ? acceptIcon : blockIcon; + } + + protected BufferedImage prepareIcon(ImageIcon image) { + BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.drawImage(image.getImage(), 0, 0, null); + g2.dispose(); + return icon; + } + + protected void updateCanClickState(JXLayer<? extends JComponent> l, MouseEvent e) { + // udpate toolTipText + Point layerLocation = l.getView().getLocation(); + Point mousePoint = e.getPoint(); + BufferedImage currentIcon = getCurrentIcon(); + if (currentIcon == null) { + setCanClick(false); + return; + } + int minX = (int) layerLocation.getX() + l.getWidth() - currentIcon.getWidth(); + int maxX = (int) layerLocation.getX() + l.getWidth(); + int minY = 0; + int maxY = currentIcon.getHeight(); + boolean accept = minX <= mousePoint.getX() && mousePoint.getX() <= maxX; + accept &= minY <= mousePoint.getLocation().getY() && mousePoint.getLocation().getY() <= maxY; + setCanClick(accept); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java new file mode 100644 index 0000000..befa8ba --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java @@ -0,0 +1,238 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import org.jdesktop.jxlayer.JXLayer; +import org.jdesktop.jxlayer.plaf.AbstractLayerUI; + +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; + +/** + * A JXLayer ui implementation that permits to block a component but still + * allow an action when clicking everywhere on the layer. + * <p/> + * Moreover, an icon can be added on the right-top icon painted and changed + * when the mouse is over the layer. + * <p/> + * You can change the blocking and accepting icon. + * <p/> + * To hook an click on the layer's icon, you can : + * <p/> + * <ul><li>pass an Action via method {@link #setAcceptAction(Action)}</li> + * <li>override the method {@link #acceptEvent(MouseEvent, JXLayer)}</li> + * </ul> + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public class BlockingLayerUI2 extends AbstractLayerUI<JComponent> { + + public static final String CAN_CLICK_PROPERTY = "canClick"; + + public static final String ACCEPT_ICON_PROPERTY = "acceptIcon"; + + public static final String BLOCK_ICON_PROPERTY = "blockIcon"; + + /** Action to be treated when click on icon */ + protected Action acceptAction; + + /** Icon when you can not click */ + protected BufferedImage blockIcon; + + /** Icon when you can click */ + protected BufferedImage acceptIcon; + + /** Optinal color to put fill background when blocking */ + protected Color blockingColor; + + /** Internal state to known when we can accept click */ + protected boolean canClick; + + public void setAcceptAction(Action acceptAction) { + this.acceptAction = acceptAction; + } + + public void setAcceptIcon(ImageIcon acceptIcon) { + this.acceptIcon = prepareIcon(acceptIcon); + firePropertyChange(ACCEPT_ICON_PROPERTY, null, acceptIcon); + setDirty(true); + } + + public void setBlockIcon(ImageIcon blockIcon) { + this.blockIcon = prepareIcon(blockIcon); + firePropertyChange(BLOCK_ICON_PROPERTY, null, blockIcon); + setDirty(true); + } + + public void setCanClick(boolean canClick) { + boolean oldvalue = this.canClick; + this.canClick = canClick; + firePropertyChange(CAN_CLICK_PROPERTY, oldvalue, canClick); + if (oldvalue != canClick) { + setDirty(true); + } + } + + @Override + public void setDirty(boolean isDirty) { + super.setDirty(isDirty); + } + + public void setBlockingColor(Color blockingColor) { + this.blockingColor = blockingColor; + } + + public void setBlockIcon(BufferedImage blockIcon) { + this.blockIcon = blockIcon; + } + + public BufferedImage getBlockIcon() { + return blockIcon; + } + + protected BufferedImage getAcceptIcon() { + return acceptIcon; + } + + public boolean isCanClick() { + return canClick; + } + + @Override + public BlockingLayerUI2 clone() { + BlockingLayerUI2 clone = new BlockingLayerUI2(); + clone.acceptAction = acceptAction; + clone.acceptIcon = acceptIcon; + clone.blockIcon = blockIcon; + clone.blockingColor = blockingColor; + clone.setCanClick(false); + return clone; + } + + @Override + protected void processKeyEvent(KeyEvent e, JXLayer<? extends JComponent> l) { + e.consume(); + } + + @Override + protected void processMouseMotionEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + e.consume(); + } + + @Override + protected void processMouseEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + switch (e.getID()) { + case MouseEvent.MOUSE_ENTERED: + setCanClick(true); + break; + case MouseEvent.MOUSE_EXITED: + setCanClick(false); + break; + case MouseEvent.MOUSE_CLICKED: + if (canClick) { + acceptEvent(e, l); + } + break; + } + e.consume(); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + if (blockingColor != null) { + // to be in sync with the view if the layer has a border + /*Insets layerInsets = l.getInsets(); + g2.translate(layerInsets.left, layerInsets.top); + + JComponent view = l.getView(); + // To prevent painting on view's border + Insets insets = view.getInsets(); + g2.clip(new Rectangle(insets.left, insets.top, + view.getWidth() - insets.left - insets.right, + view.getHeight() - insets.top - insets.bottom)); + */ + + g2.setColor(blockingColor); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f)); + g2.fillRect(0, 0, l.getWidth(), l.getHeight()); + } + if (getCurrentIcon() != null) { + g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null); + } + } + + protected void acceptEvent(MouseEvent e, JXLayer<? extends JComponent> l) { + if (acceptAction != null) { + acceptAction.putValue("layer", l); + Component source = l.getView(); + acceptAction.actionPerformed(new ActionEvent(source, 0, "accept")); + } + } + + protected BufferedImage getCurrentIcon() { + return canClick ? acceptIcon : blockIcon; + } + + protected BufferedImage prepareIcon(ImageIcon image) { + BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.drawImage(image.getImage(), 0, 0, null); + g2.dispose(); + return icon; + } + + protected void updateCanClickState(JXLayer<JComponent> l, MouseEvent e) { + // udpate toolTipText + Point layerLocation = l.getView().getLocation(); + Point mousePoint = e.getPoint(); + BufferedImage currentIcon = getCurrentIcon(); + if (currentIcon == null) { + setCanClick(false); + return; + } + int minX = (int) layerLocation.getX() + l.getWidth() - currentIcon.getWidth(); + int maxX = (int) layerLocation.getX() + l.getWidth(); + int minY = 0; + int maxY = currentIcon.getHeight(); + boolean accept = minX <= mousePoint.getX() && mousePoint.getX() <= maxX; + accept &= minY <= mousePoint.getLocation().getY() && mousePoint.getLocation().getY() <= maxY; + setCanClick(accept); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2.java new file mode 100644 index 0000000..f537564 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2.java @@ -0,0 +1,253 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +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.awt.Dimension; +import java.awt.Insets; +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +/** + * An override of the awt {@link 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(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(Container)}. + * + * @author tchemit <chemit@codelutin.com> + * @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>(); + + /** + * A flag to compute dimension only on visible component. + * <p/> + * This is usefull when we only care of the visible component. + */ + protected boolean useOnlyVisibleComponentDimension; + + @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} si l'identifiant est deja present dans le + * layout, {@code false} otherwise. + */ + 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) { + checkContainer(container); + for (Component component : container.getComponents()) { + if (component.isVisible()) { + return component; + } + } + // no component actually visible + return null; + } + + public Component getComponent(Container container, String constraints) { + checkContainer(container); + checkConstraints(constraints); + int index = contexts.indexOf(constraints); + return container.getComponents()[index]; + } + + /** + * Determines the preferred size of the container argument using + * this card layout. + * + * @param parent the parent container in which to do the layout + * @return the preferred dimensions to lay out the subcomponents + * of the specified container + * @see Container#getPreferredSize + * @see CardLayout#minimumLayoutSize + */ + @Override + public Dimension preferredLayoutSize(Container parent) { + Dimension dimension = null; + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(parent); + if (comp != null) { + dimension = comp.getPreferredSize(); + } + } + if (dimension == null) { + dimension = super.preferredLayoutSize(parent); + } + return dimension; + } + + /** + * Calculates the minimum size for the specified panel. + * + * @param parent the parent container in which to do the layout + * @return the minimum dimensions required to lay out the + * subcomponents of the specified container + * @see Container#doLayout + * @see CardLayout#preferredLayoutSize + */ + @Override + public Dimension minimumLayoutSize(Container parent) { + Dimension dimension = null; + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(parent); + if (comp != null) { + dimension = comp.getMinimumSize(); + } + } + if (dimension == null) { + dimension = super.minimumLayoutSize(parent); + } + return dimension; + } + + /** + * Returns the maximum dimensions for this layout given the components + * in the specified target container. + * + * @param target the component which needs to be laid out + * @see Container + * @see #minimumLayoutSize + * @see #preferredLayoutSize + */ + @Override + public Dimension maximumLayoutSize(Container target) { + Dimension dimension = null; + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(target); + if (comp != null) { + dimension = comp.getMaximumSize(); + } + } + if (dimension == null) { + dimension = super.maximumLayoutSize(target); + } + return dimension; + } + + /** + * Lays out the specified container using this card layout. + * <p/> + * Each component in the <code>parent</code> container is reshaped + * to be the size of the container, minus space for surrounding + * insets, horizontal gaps, and vertical gaps. + * + * @param parent the parent container in which to do the layout + * @see Container#doLayout + */ + @Override + public void layoutContainer(Container parent) { + if (useOnlyVisibleComponentDimension) { + Component comp = getVisibleComponent(parent); + if (comp != null) { + //dimension = comp.getMinimumSize(); + Insets insets = parent.getInsets(); + comp.setBounds(getHgap() + insets.left, getVgap() + insets.top, + parent.getWidth() - (getHgap() * 2 + insets.left + insets.right), + parent.getHeight() - (getVgap() * 2 + insets.top + insets.bottom)); + } else { + super.layoutContainer(parent); + } + } else { + super.layoutContainer(parent); + } + } + + public boolean isUseOnlyVisibleComponentDimension() { + return useOnlyVisibleComponentDimension; + } + + public void setUseOnlyVisibleComponentDimension(boolean useOnlyVisibleComponentDimension) { + this.useOnlyVisibleComponentDimension = useOnlyVisibleComponentDimension; + } + + /** + * remove from cardlayout and linked container all his components. + * + * @param parent the parent container linked with the layout + */ + public void reset(Container parent) { + checkContainer(parent); + for (Component component : parent.getComponents()) { + removeLayoutComponent(component); + parent.remove(component); + } + contexts.clear(); + + } + + protected void checkContainer(Container container) { + if (!equals(container.getLayout())) { + throw new IllegalArgumentException("the container is not managed by the current layout"); + } + } + + protected void checkConstraints(String constraints) { + if (!contains(constraints)) { + throw new IllegalArgumentException("the constraints '" + constraints + "' is not supported by this layout : " + contexts); + } + } + + public Serializable[] getContexts() { + return contexts.toArray(new Serializable[contexts.size()]); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java new file mode 100644 index 0000000..6c4303a --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java @@ -0,0 +1,131 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import jaxx.runtime.JAXXObject; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Container; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * Une extension de {@link CardLayout2} pour pouvoir automatiquement afficher un + * contenu à partir de la propriété {@link #selected}. + * <p/> + * Ainsi, en changeant cette propriété via la méthode {@link #setSelected(String)}, + * le contenu sera changé automatiquement, ce qui permet une utilisation direct + * dans jaxx sans à avoir à écrire d'écouteur. + * + * @author tchemit <chemit@codelutin.com> + * @see CardLayout2 + * @since 1.3 + */ +public class CardLayout2Ext extends CardLayout2 { + + /** log */ + static private Log log = LogFactory.getLog(CardLayout2.class); + + private static final long serialVersionUID = 1L; + + public static final String SELECTED_PROPERTY_NAME = "selected"; + + /** pour propager les changements dans le modèle vers l'ui */ + protected PropertyChangeSupport pcs; + + /** le contenu sélectionné */ + protected String selected; + + private String containerName; + + private JAXXObject ui; + + private Container container; + + public CardLayout2Ext(JAXXObject ui, String containerName) { + pcs = new PropertyChangeSupport(this); + this.ui = ui; + this.containerName = containerName; + } + + public String getSelected() { + return selected; + } + + public String getPreviousSelected() { + int index = contexts.indexOf(selected); + if (index < 1) { + return null; + } + return contexts.get(index - 1) + ""; + } + + public String getNextSelected() { + int index = contexts.indexOf(selected); + if (index >= contexts.size()) { + return null; + } + return contexts.get(index + 1) + ""; + } + + public void setSelected(String selected) { + String oldSelected = this.selected; + this.selected = selected; + show(getContainer(), selected); + pcs.firePropertyChange(SELECTED_PROPERTY_NAME, oldSelected, selected); + } + + public Container getContainer() { + if (container == null) { + container = (Container) ui.getObjectById(containerName); + } + return container; + } + + 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 void removePropertyChangeListeners() { + for (PropertyChangeListener l : pcs.getPropertyChangeListeners()) { + pcs.removePropertyChangeListener(l); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/GBC.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/GBC.java new file mode 100644 index 0000000..4bc3230 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/GBC.java @@ -0,0 +1,132 @@ +/* %%Ignore-License +GBC - A convenience class to tame the GridBagLayout + +Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com) + +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.swing; + +import java.awt.GridBagConstraints; +import java.awt.Insets; + +/** + * This class simplifies the use of the GridBagConstraints + * class. + */ +public class GBC extends GridBagConstraints { + private static final long serialVersionUID = -3626882543530638704L; + + /** + * Constructs a GBC with a given gridx and gridy position and + * all other grid bag constraint values set to the default. + * + * @param gridx the gridx position + * @param gridy the gridy position + */ + public GBC(int gridx, int gridy) { + this.gridx = gridx; + this.gridy = gridy; + } + + /** + * Constructs a GBC with given gridx, gridy, gridwidth, gridheight + * and all other grid bag constraint values set to the default. + * + * @param gridx the gridx position + * @param gridy the gridy position + * @param gridwidth the cell span in x-direction + * @param gridheight the cell span in y-direction + */ + public GBC(int gridx, int gridy, int gridwidth, int gridheight) { + this.gridx = gridx; + this.gridy = gridy; + this.gridwidth = gridwidth; + this.gridheight = gridheight; + } + + /** + * Sets the anchor. + * + * @param anchor the anchor value + * @return this object for further modification + */ + public GBC setAnchor(int anchor) { + this.anchor = anchor; + return this; + } + + /** + * Sets the fill direction. + * + * @param fill the fill direction + * @return this object for further modification + */ + public GBC setFill(int fill) { + this.fill = fill; + return this; + } + + /** + * Sets the cell weights. + * + * @param weightx the cell weight in x-direction + * @param weighty the cell weight in y-direction + * @return this object for further modification + */ + public GBC setWeight(double weightx, double weighty) { + this.weightx = weightx; + this.weighty = weighty; + return this; + } + + /** + * Sets the insets of this cell. + * + * @param distance the spacing to use in all directions + * @return this object for further modification + */ + public GBC setInsets(int distance) { + this.insets = new Insets(distance, distance, distance, distance); + return this; + } + + /** + * Sets the insets of this cell. + * + * @param top the spacing to use on top + * @param left the spacing to use to the left + * @param bottom the spacing to use on the bottom + * @param right the spacing to use to the right + * @return this object for further modification + */ + public GBC setInsets(int top, int left, int bottom, int right) { + this.insets = new Insets(top, left, bottom, right); + return this; + } + + /** + * Sets the internal padding + * + * @param ipadx the internal padding in x-direction + * @param ipady the internal padding in y-direction + * @return this object for further modification + */ + public GBC setIpad(int ipadx, int ipady) { + this.ipadx = ipadx; + this.ipady = ipady; + return this; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBox.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBox.java new file mode 100644 index 0000000..20e1794 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBox.java @@ -0,0 +1,119 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JPanel; +import java.awt.Insets; + +/** + * Panel which uses an {@link HBoxLayout} by default. + * + * @author Ethan Nicholas + */ +public class HBox extends JPanel { + + private static final long serialVersionUID = 1L; + + public static final String SPACING_PROPERTY = "spacing"; + + public static final String MARGIN_PROPERTY = "margin"; + + public static final String HORIZONTAL_ALIGNMENT_PROPERTY = "horizontalAlignment"; + + public static final String VERTICAL_ALIGNMENT_PROPERTY = "verticalAlignment"; + + private Insets margin; + + public HBox() { + super(new HBoxLayout()); + } + + /** + * Returns the spacing between components, in pixels. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @return spacing between components + */ + public int getSpacing() { + return ((HBoxLayout) getLayout()).getSpacing(); + } + + /** + * Sets the spacing between components. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @param spacing new spacing value + */ + public void setSpacing(int spacing) { + int oldValue = getSpacing(); + ((HBoxLayout) getLayout()).setSpacing(spacing); + firePropertyChange(SPACING_PROPERTY, oldValue, spacing); + revalidate(); + } + + public int getHorizontalAlignment() { + return ((HBoxLayout) getLayout()).getHorizontalAlignment(); + } + + public void setHorizontalAlignment(int horizontalAlignment) { + int oldValue = getHorizontalAlignment(); + ((HBoxLayout) getLayout()).setHorizontalAlignment(horizontalAlignment); + firePropertyChange(HORIZONTAL_ALIGNMENT_PROPERTY, oldValue, horizontalAlignment); + revalidate(); + } + + public int getVerticalAlignment() { + return ((HBoxLayout) getLayout()).getVerticalAlignment(); + } + + public void setVerticalAlignment(int verticalAlignment) { + int oldValue = getVerticalAlignment(); + ((HBoxLayout) getLayout()).setVerticalAlignment(verticalAlignment); + firePropertyChange(VERTICAL_ALIGNMENT_PROPERTY, oldValue, verticalAlignment); + revalidate(); + } + + public Insets getMargin() { + return margin; + } + + public void setMargin(Insets margin) { + Insets oldValue = this.margin; + this.margin = (Insets) margin.clone(); + firePropertyChange(MARGIN_PROPERTY, oldValue, margin); + } + + @Override + public Insets getInsets() { + Insets result = super.getInsets(); + if (margin != null) { + result.top += margin.top; + result.left += margin.left; + result.right += margin.right; + result.bottom += margin.bottom; + } + return result; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxBeanInfo.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxBeanInfo.java new file mode 100644 index 0000000..8a884d0 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxBeanInfo.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; + +public class HBoxBeanInfo extends SimpleBeanInfo { + + @Override + public BeanInfo[] getAdditionalBeanInfo() { + try { + return new BeanInfo[]{Introspector.getBeanInfo(JPanel.class)}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } + + @Override + public PropertyDescriptor[] getPropertyDescriptors() { + try { + PropertyDescriptor spacing = new PropertyDescriptor("spacing", HBox.class); + spacing.setBound(true); + + PropertyDescriptor margin = new PropertyDescriptor("margin", HBox.class); + margin.setBound(true); + + PropertyDescriptor horizontalAlignment = new PropertyDescriptor("horizontalAlignment", HBox.class); + horizontalAlignment.setBound(true); + horizontalAlignment.setValue("enumerationValues", new Object[]{ + "left", SwingConstants.LEFT, "SwingConstants.LEFT", + "center", SwingConstants.CENTER, "SwingConstants.CENTER", + "right", SwingConstants.RIGHT, "SwingConstants.RIGHT" + }); + + PropertyDescriptor verticalAlignment = new PropertyDescriptor("verticalAlignment", HBox.class); + verticalAlignment.setBound(true); + verticalAlignment.setValue("enumerationValues", new Object[]{ + "top", SwingConstants.TOP, "SwingConstants.TOP", + "middle", SwingConstants.CENTER, "SwingConstants.CENTER", + "bottom", SwingConstants.BOTTOM, "SwingConstants.BOTTOM" + }); + + return new PropertyDescriptor[]{spacing, margin, horizontalAlignment, verticalAlignment}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxLayout.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxLayout.java new file mode 100644 index 0000000..3904625 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/HBoxLayout.java @@ -0,0 +1,149 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.SwingConstants; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; + +/** + * Horizontal box layout. The layout rules followed by this class are quite different than the core BoxLayout class, + * and in general represent a more useful algorithm. + * + * @author Ethan Nicholas + */ +public class HBoxLayout implements LayoutManager { + + private int spacing = 6; + + private int horizontalAlignment = SwingConstants.LEFT; + + private int verticalAlignment = SwingConstants.TOP; + + public int getSpacing() { + return spacing; + } + + public void setSpacing(int spacing) { + this.spacing = spacing; + } + + public int getHorizontalAlignment() { + return horizontalAlignment; + } + + public void setHorizontalAlignment(int horizontalAlignment) { + this.horizontalAlignment = horizontalAlignment; + } + + public int getVerticalAlignment() { + return verticalAlignment; + } + + public void setVerticalAlignment(int verticalAlignment) { + this.verticalAlignment = verticalAlignment; + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + + @Override + public void layoutContainer(Container parent) { + Insets insets = parent.getInsets(); + int parentHeight = parent.getSize().height - insets.top - insets.bottom; + int count = parent.getComponentCount(); + Dimension preferredSize = parent.getPreferredSize(); + int x; + switch (horizontalAlignment) { + case SwingConstants.LEFT: + x = insets.left; + break; + case SwingConstants.CENTER: + x = insets.left + (parent.getWidth() - preferredSize.width) / 2; + break; + case SwingConstants.RIGHT: + x = insets.left + (parent.getWidth() - preferredSize.width); + break; + default: + throw new IllegalArgumentException("invalid horizontal alignment: " + horizontalAlignment); + } + + for (int i = 0; i < count; i++) { + Component component = parent.getComponent(i); + Dimension childPreferredSize = component.getPreferredSize(); + int height = Math.min(childPreferredSize.height, parentHeight); + int y; + switch (verticalAlignment) { + case SwingConstants.TOP: + y = insets.top; + break; + case SwingConstants.CENTER: + y = insets.top + (parentHeight - childPreferredSize.height) / 2; + break; + case SwingConstants.BOTTOM: + y = insets.top + (parentHeight - childPreferredSize.height); + break; + default: + throw new IllegalArgumentException("invalid vertical alignment: " + verticalAlignment); + } + component.setBounds(x, y, childPreferredSize.width, height); + x += childPreferredSize.width + spacing; + } + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + int width = (parent.getComponentCount() - 1) * spacing; + int height = 0; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension minimumSize = parent.getComponent(i).getMinimumSize(); + width += minimumSize.width; + height = Math.max(height, minimumSize.height); + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + int width = (parent.getComponentCount() - 1) * spacing; + int height = 0; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension preferredSize = parent.getComponent(i).getPreferredSize(); + width += preferredSize.width; + height = Math.max(height, preferredSize.height); + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public void removeLayoutComponent(Component comp) { + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Item.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Item.java new file mode 100644 index 0000000..62a7623 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Item.java @@ -0,0 +1,253 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.event.SwingPropertyChangeSupport; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.List; + +// This needs to be split into two classes, Item and TreeItem + +/** + * An item in a component such as <code>JComboBox</code> or <code>JTree</code>. The <code>Item</code> + * class corresponds to the <code><item></code> tag in JAXX source files. + */ +public class Item { + + public static final String LABEL_PROPERTY = "label"; + + public static final String VALUE_PROPERTY = "value"; + + public static final String SELECTED_PROPERTY = "selected"; + + private String id; + + private String label; + + private Object value; + + private boolean selected; + + private List<Item> children; + + private Item parent; + + private PropertyChangeSupport propertyChangeSupport; + + /** + * Creates a new Item. This should only be called from compiled JAXX files. + * + * @param id the item's ID + * @param label the string that should be used to represent the item visually + * @param value the item's actual value + * @param selected <code>true</code> if the item should be selected by default + */ + public Item(String id, String label, Object value, boolean selected) { + this.id = id; + this.label = label; + this.value = value; + this.selected = selected; + } + + /** + * Returns this item's ID. + * + * @return the JAXX ID attribute + */ + public String getId() { + return id; + } + + /** + * Returns the string that should be used to represent the item at display time. If <code>null</code>, + * <code>String.valueOf(getValue())</code> will be used instead. + * + * @return this item's display string + * @see #setLabel + */ + public String getLabel() { + return label; + } + + /** + * Sets the item's display string. If <code>null, String.valueOf(getValue())</code> will be used instead. + * + * @param label the new display string + * @see #getLabel + */ + public void setLabel(String label) { + String oldLabel = this.label; + this.label = label; + firePropertyChange(LABEL_PROPERTY, oldLabel, label); + } + + /** + * Returns the item's actual value as it appears in the component's model. The <code>Item</code> itself is not + * visible from the model, only the value. + * + * @return the item's value + * @see #setValue + */ + public Object getValue() { + return value; + } + + /** + * Sets the item's value as it appears in the component's model. The <code>Item</code> itself is not + * visible from the model, only the value. + * + * @param value the new value + * @see #getValue + */ + public void setValue(Object value) { + Object oldValue = this.value; + this.value = value; + firePropertyChange(VALUE_PROPERTY, oldValue, value); + } + + /** + * Returns <code>true</code> if this item is currently selected. This is a bound property. + * + * @return <code>true</code> if item is selected + * @see #setSelected + */ + public boolean isSelected() { + return selected; + } + + /** + * Sets the item's selection state. This is a bound property. + * + * @param selected the new selection state + * @see #isSelected + */ + public void setSelected(boolean selected) { + boolean oldSelected = this.selected; + this.selected = selected; + firePropertyChange(SELECTED_PROPERTY, oldSelected, selected); + } + + /** + * Adds a new child node (Items can be nested in trees). + * + * @param item the new child item + */ + public void addChild(Item item) { + if (children == null) { + children = new ArrayList<Item>(); + } + children.add(item); + item.parent = this; + } + + /** + * Remove child node a new child node + * + * @param item to remove + */ + public void removeChild(Item item) { + if (children != null) { + children.remove(item); + } + } + + /** + * Remove all childs nodes + * + * @param items list of items to remove + */ + public void removeChilds(List<Item> items) { + if (children != null) { + children.removeAll(items); + } + } + + /** + * Returns a list of this item's children. + * + * @return a list of all nested child nodes + */ + public List<Item> getChildren() { + if (children == null) { + children = new ArrayList<Item>(); + } + return children; + } + + /** + * Returns the <code>Item</code> containing this <code>Item</code>, or <code>null</code> for a top-level + * <code>Item</code>. + * + * @return the item parent (or null) + */ + public Item getParent() { + return parent; + } + + /** + * Set the parent of this item + * + * @param parent the item parent (or null) + */ + public void setParent(Item parent) { + this.parent = parent; + } + + private PropertyChangeSupport getPropertyChangeSupport() { + if (propertyChangeSupport == null) { + propertyChangeSupport = new SwingPropertyChangeSupport(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); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (propertyChangeSupport != null) { + getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue); + } + } + + @Override + public String toString() { + return getClass().getName() + "[" + value + "]"; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java new file mode 100644 index 0000000..3e03e87 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXButtonGroup.java @@ -0,0 +1,253 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +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() { + + @Override + 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 buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); + if (buttonValue != getSelectedValue()) { + setSelectedValue(buttonValue); + } + } + } + } + + 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 AbstractButton getSelectedButton() { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + if (button.isSelected()) { + return button; + } + } + return null; + } + + public AbstractButton getButton(Object value) { + Enumeration<AbstractButton> e = getElements(); + while (e.hasMoreElements()) { + AbstractButton button = e.nextElement(); + Object buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); + if (value.equals(buttonValue)) { + return button; + } + } + return null; + } + + 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 buttonValue = button.getClientProperty(VALUE_CLIENT_PROPERTY); + if (value.equals(buttonValue)) { + 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); + } + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXComboBox.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXComboBox.java new file mode 100644 index 0000000..e8ab961 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXComboBox.java @@ -0,0 +1,315 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.AbstractListModel; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.ListModel; +import java.awt.Component; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class JAXXComboBox extends JComboBox { + + private static final long serialVersionUID = 1L; + + public class JAXXComboBoxModel extends AbstractListModel implements ComboBoxModel { + + private List<Item> items; + + private Object selectedItem; + + private static final long serialVersionUID = -8940733376638766414L; + + public JAXXComboBoxModel(List<Item> items) { + this.items = items; + + PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent e) { + if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { + Item item = (Item) e.getSource(); + int itemIndex = JAXXComboBoxModel.this.items.indexOf(item); + // TODO: fix cut-and-pasting badness + int[] oldSelection = new int[]{getSelectedIndex()}; + int[] newSelection; + int index = -1; + for (int i = 0; i < oldSelection.length; i++) { + if (oldSelection[i] == itemIndex) { + index = i; + break; + } + } + if (item.isSelected()) { + if (index != -1) // it was already selected + { + return; + } + newSelection = new int[oldSelection.length + 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, oldSelection.length); + newSelection[newSelection.length - 1] = itemIndex; + } else { + if (index == -1) // it already wasn't selected + { + return; + } + newSelection = new int[oldSelection.length - 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, index); + System.arraycopy(oldSelection, index + 1, newSelection, index, oldSelection.length - 1 - index); + } + if (newSelection.length > 0) { + setSelectedIndex(newSelection[0]); + } + } else { + // TODO: more cut-and-pasting badness + for (int i = 0; i < getSize(); i++) { + if (getElementAt(i) == ((Item) e.getSource()).getValue()) { + fireContentsChanged(JAXXComboBoxModel.this, i, i); + if (getSelectedIndex() == i) { + fireItemStateChanged(new ItemEvent(JAXXComboBox.this, ItemEvent.ITEM_STATE_CHANGED, getElementAt(i), ItemEvent.DESELECTED)); + } + return; + } + } + } + } + }; + for (Item item : items) { + item.addPropertyChangeListener(listener); + } + } + + public List<Item> getItems() { + return items; + } + + @Override + public Object getElementAt(int i) { + return items.get(i).getValue(); + } + + @Override + public int getSize() { + return items.size(); + } + + @Override + public Object getSelectedItem() { + return selectedItem; + } + + @Override + public void setSelectedItem(Object selectedItem) { + if (this.selectedItem != null && !this.selectedItem.equals(selectedItem) || + this.selectedItem == null && selectedItem != null) { + this.selectedItem = selectedItem; + fireContentsChanged(this, -1, -1); + } + } + } + + public JAXXComboBox() { + setRenderer(new DefaultListCellRenderer() { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + ListModel model = list.getModel(); + if (model instanceof JAXXComboBoxModel) { + List/*<Item>*/ items = ((JAXXComboBoxModel) model).items; + Item item = null; + if (index == -1) { + for (Object item1 : items) { + Item testItem = (Item) item1; + if (testItem.getValue() == value) { + item = testItem; + break; + } + } + } else { + item = (Item) items.get(index); + } + + if (item != null) { + String label = item.getLabel(); + if (label != null) { + value = label; + } + } + } + return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + }); + + addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + ListModel model = getModel(); + if (model instanceof JAXXComboBoxModel) { + List<Item> items = ((JAXXComboBoxModel) model).items; + for (int i = items.size() - 1; i >= 0; i--) { + boolean selected = getSelectedIndex() == i; + Item item = items.get(i); + if (selected != item.isSelected()) { + item.setSelected(selected); + } + } + } + } + }); + } + + /** + * Fill a combo box model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param select the object to select in combo after reflling his model + * @param methodName method to invoke to display data's name + */ + public void fillComboBox(Collection<?> data, Object select, String methodName) { + // prepare method to use + Method m; + try { + m = select.getClass().getMethod(methodName); + m.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("could not find method " + methodName + " on " + select.getClass()); + } + + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = o.equals(select); + try { + items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); + } catch (IllegalAccessException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } + } + setItems(items); + } + + // this way we can keep it marked protected and still allow code in this file to call it + + @Override + protected void fireItemStateChanged(ItemEvent e) { + super.fireItemStateChanged(e); + } + + public void setItems(List<Item> items) { + setModel(new JAXXComboBoxModel(items)); + List<Integer> selectedIndexList = new ArrayList<Integer>(); + for (int i = 0; i < items.size(); i++) { + if (items.get(i).isSelected()) { + selectedIndexList.add(i); + } + } + int[] selectedIndices = new int[selectedIndexList.size()]; + for (int i = 0; i < selectedIndexList.size(); i++) { + selectedIndices[i] = selectedIndexList.get(i); + } + if (selectedIndices.length > 0) { + setSelectedIndex(selectedIndices[0]); + } + } + + public List<Item> getItems() { + if (getModel() instanceof JAXXComboBoxModel) { + return ((JAXXComboBoxModel) getModel()).getItems(); + } + return null; + } + + public void setSelectedItem(Item item) { + //TC-20092004 Anomalie #73 fix npe when want to call with a null + // value + super.setSelectedItem(item == null ? null : item.getValue()); + } + + public Item getSelectedJaxxItem() { + Object selected = super.getSelectedItem(); + return findItem(selected); + } + + public Item findItem(Object value) { + List<Item> items = getItems(); + if (items != null) { + for (Item i : items) { + if (i.getValue().equals(value)) { + return i; + } + } + } + return null; + } + + public void addItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.add(item); + setItems(items); + } + } + + public void addAllItems(Collection<Item> itemsToAdd) { + List<Item> items = getItems(); + if (items != null) { + items.addAll(itemsToAdd); + setItems(items); + } + } + + public void removeItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.remove(item); + setItems(items); + } + } + + public void removeAllItems(Collection<Item> itemsToRemove) { + List<Item> items = getItems(); + if (items != null) { + items.removeAll(itemsToRemove); + setItems(items); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXList.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXList.java new file mode 100644 index 0000000..4162abc --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXList.java @@ -0,0 +1,417 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.AbstractListModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class JAXXList extends JList { + + private static final long serialVersionUID = 1L; + + public class JAXXListModel extends AbstractListModel { + + private List<Item> items; + + private static final long serialVersionUID = -1598924187490122036L; + + public JAXXListModel(List<Item> items) { + this.items = items; + + PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent e) { + if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { + Item item = (Item) e.getSource(); + int itemIndex = JAXXListModel.this.items.indexOf(item); + int[] oldSelection = getSelectedIndices(); + int[] newSelection; + int index = -1; + for (int i = 0; i < oldSelection.length; i++) { + if (oldSelection[i] == itemIndex) { + index = i; + break; + } + } + if (item.isSelected()) { + if (index != -1) // it was already selected + { + return; + } + newSelection = new int[oldSelection.length + 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, oldSelection.length); + newSelection[newSelection.length - 1] = itemIndex; + } else { + if (index == -1) // it already wasn't selected + { + return; + } + newSelection = new int[oldSelection.length - 1]; + System.arraycopy(oldSelection, 0, newSelection, 0, index); + System.arraycopy(oldSelection, index + 1, newSelection, index, oldSelection.length - 1 - index); + } + setSelectedIndices(newSelection); + } else { + for (int i = 0; i < getSize(); i++) { + if (getElementAt(i) == ((Item) e.getSource()).getValue()) { + fireContentsChanged(JAXXListModel.this, i, i); + if (isSelectedIndex(i)) { + fireSelectionValueChanged(i, i, false); + } + return; + } + } + } + } + }; + for (Item item : items) { + item.addPropertyChangeListener(listener); + } + } + + public List<Item> getItems() { + return items; + } + + @Override + public Object getElementAt(int i) { + return items.get(i).getValue(); + } + + @Override + public int getSize() { + return items.size(); + } + } + + public JAXXList() { + setCellRenderer(new DefaultListCellRenderer() { + + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + ListModel model = list.getModel(); + if (model instanceof JAXXListModel) { + Item item = ((JAXXListModel) model).items.get(index); + String label = item.getLabel(); + if (label != null) { + value = label; + } + } + return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + }); + + addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + ListModel model = getModel(); + if (model instanceof JAXXListModel) { + List<Item> items = ((JAXXListModel) model).items; + for (int i = items.size() - 1; i >= 0; i--) { + boolean selected = isSelectedIndex(i); + Item item = items.get(i); + if (selected != item.isSelected()) { + item.setSelected(selected); + } + } + } + } + }); + } + + // this way we can keep it marked protected and still allow code in this file to call it + + @Override + protected void fireSelectionValueChanged(int firstIndex, int lastIndex, boolean isAdjusting) { + super.fireSelectionValueChanged(firstIndex, lastIndex, isAdjusting); + } + + public void setItems(List<Item> items) { + setModel(new JAXXListModel(items)); + List<Integer> selectedIndexList = new ArrayList<Integer>(); + for (int i = 0; i < items.size(); i++) { + if (items.get(i).isSelected()) { + selectedIndexList.add(i); + } + } + int[] selectedIndices = new int[selectedIndexList.size()]; + for (int i = 0; i < selectedIndexList.size(); i++) { + selectedIndices[i] = selectedIndexList.get(i); + } + setSelectedIndices(selectedIndices); + } + + public List<Item> getItems() { + if (getModel() instanceof JAXXListModel) { + return ((JAXXListModel) getModel()).getItems(); + } + return null; + } + + public void setSelectedValue(Object value) { + super.setSelectedValue(value, true); + } + + /** + * Set the selected Objects + * + * @param values Objects must be selected in the list + */ + public void setSelectedValues(Object[] values) { + if (values != null) { + List<Integer> selectedIndices = new ArrayList<Integer>(); + ListModel model = getModel(); + for (int i = 0; i < model.getSize(); i++) { + Object o = model.getElementAt(i); + for (Object value : values) { + if (o.equals(value)) { + selectedIndices.add(i); + break; + } + } + } + int[] ints = new int[selectedIndices.size()]; + for (int i = 0; i < ints.length; i++) { + ints[i] = selectedIndices.get(i).intValue(); + } + setSelectedIndices(ints); + } else { + // No selection if values is null + setSelectedIndex(-1); + } + } + + public void setSelectedItem(Item item) { + super.setSelectedValue(item.getValue(), true); + } + + public void setSelectedItems(List<Item> itemsToSelect) { + if (itemsToSelect != null) { + List<Item> items = getItems(); + int[] indices = new int[itemsToSelect.size()]; + int i = 0; + for (Item item : itemsToSelect) { + indices[i] = items.indexOf(item); + i++; + } + super.setSelectedIndices(indices); + } + } + + public Item getSelectedItem() { + Object selected = super.getSelectedValue(); + return findItem(selected); + } + + public List<Item> getSelectedItems() { + Object[] selected = super.getSelectedValues(); + java.util.List<Item> itemsSelected = new ArrayList<Item>(); + for (Object s : selected) { + itemsSelected.add(findItem(s)); + } + return itemsSelected; + } + + public Item findItem(Object value) { + List<Item> items = getItems(); + if (items != null) { + for (Item i : items) { + if (i.getValue().equals(value)) { + return i; + } + } + } + return null; + } + + public void addItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.add(item); + setItems(items); + } + } + + public void addAllItems(Collection<Item> itemsToAdd) { + List<Item> items = getItems(); + if (items != null) { + items.addAll(itemsToAdd); + setItems(items); + } + } + + public void removeItem(Item item) { + List<Item> items = getItems(); + if (items != null) { + items.remove(item); + setItems(items); + } + } + + public void removeAllItems(Collection<Item> itemsToRemove) { + List<Item> items = getItems(); + if (items != null) { + items.removeAll(itemsToRemove); + setItems(items); + } + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param selects the objects to select in list after reflling his model + */ + public void fillList(Collection<?> data, Collection<?> selects) { + if (selects == null) { + selects = java.util.Collections.EMPTY_LIST; + } + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = false; + for (Object select : selects) { + if (selected = o.equals(select)) { + break; + } + } + items.add(new Item(o.toString(), o.toString(), o, selected)); + } + setItems(items); + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param select object to select in list after reflling his model + */ + public void fillList(Collection<?> data, Object select) { + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = o.equals(select); + items.add(new Item(o.toString(), o.toString(), o, selected)); + } + setItems(items); + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param select object to select in list after reflling his model + * @param methodName method to invoke to display data's name + */ + public void fillList(Collection<?> data, Object select, String methodName) { + // prepare method to use + Method m = null; + + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = o.equals(select); + if (m == null) { + try { + m = o.getClass().getMethod(methodName); + m.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass()); + } + } + try { + items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); + } catch (SecurityException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } + } + setItems(items); + } + + /** + * Fill a list model with some datas, and select after all the given object + * + * @param data data ot inject in combo + * @param selects the objects to select in list after reflling his model + * @param methodName method to invoke to display data's name + */ + public void fillList(Collection<?> data, Collection<?> selects, String methodName) { + // prepare method to use + Method m = null; + + List<Item> items = new ArrayList<Item>(); + for (Object o : data) { + boolean selected = selects.contains(o); + if (m == null) { + try { + m = o.getClass().getMethod(methodName); + m.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("could not find method " + methodName + " on " + o.getClass()); + } + } + try { + items.add(new Item(o.toString(), (String) m.invoke(o), o, selected)); + } catch (SecurityException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + // shoudl never happen ? + throw new RuntimeException(e); + } + } + setItems(items); + } + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTab.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTab.java new file mode 100644 index 0000000..7999572 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTab.java @@ -0,0 +1,31 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +/** @author tchemit <chemit@codelutin.com> */ +public class JAXXTab extends Table { + + private static final long serialVersionUID = 1L; +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXToggleButton.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXToggleButton.java new file mode 100644 index 0000000..dad7b32 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXToggleButton.java @@ -0,0 +1,125 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JToggleButton; + +public class JAXXToggleButton extends JToggleButton { + + private static final long serialVersionUID = 1L; + + protected String glueText; + + protected String normalText; + + protected String glueTooltipText; + + protected String normalTooltipText; + + protected int normalMnemonic; + + protected int glueMnemonic; + + protected boolean _init; + + public String getGlueText() { + return glueText; + } + + public String getNormalText() { + return normalText; + } + + public String getGlueTooltipText() { + return glueTooltipText; + } + + public String getNormalTooltipText() { + return normalTooltipText; + } + + public void setGlueText(String glueText) { + this.glueText = glueText; + + } + + public void setNormalText(String normalText) { + this.normalText = normalText; + + } + + public void setGlueTooltipText(String glueTooltipText) { + this.glueTooltipText = glueTooltipText; + } + + public int getNormalMnemonic() { + return normalMnemonic; + } + + public void setNormalMnemonic(int normalMnemonic) { + this.normalMnemonic = normalMnemonic; + } + + public int getGlueMnemonic() { + return glueMnemonic; + } + + public void setGlueMnemonic(int glueMnemonic) { + this.glueMnemonic = glueMnemonic; + } + + public void setNormalTooltipText(String normalTooltipText) { + this.normalTooltipText = normalTooltipText; + if (!_init) { + init(); + _init = true; + } + } + + @Override + public void setSelected(boolean b) { + super.setSelected(b); + if (isSelected()) { + setText(getGlueText()); + setToolTipText(getGlueTooltipText()); + setMnemonic(getGlueMnemonic()); + } else { + setText(getNormalText()); + setToolTipText(getNormalTooltipText()); + setMnemonic(getNormalMnemonic()); + } + revalidate(); + } + + public void init() { + setSelected(false); + } + + /* end raw body code */ + public JAXXToggleButton() { + super(); + _init = false; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTree.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTree.java new file mode 100644 index 0000000..e04dd49 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/JAXXTree.java @@ -0,0 +1,281 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JTree; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +public class JAXXTree extends JTree { + + private static final long serialVersionUID = 1L; + + private static final String SYNTHETIC = "<synthetic root node>"; + + public class JAXXTreeModel implements TreeModel { + + private Item root; + + private List<TreeModelListener> listeners = new ArrayList<TreeModelListener>(); + + public JAXXTreeModel(List<Item> items) { + if (items.size() == 1) { + root = items.get(0); + } else { + root = new Item(null, null, SYNTHETIC, false); + for (Item item : items) { + root.addChild(item); + } + } + + PropertyChangeListener listener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent e) { + if (e.getPropertyName().equals(Item.SELECTED_PROPERTY)) { + Item item = (Item) e.getSource(); + if (item.isSelected()) { + addSelectionPath(getTreePath(item)); + } else { + removeSelectionPath(getTreePath(item)); + } + } else { + Item item = (Item) e.getSource(); + boolean root = item.getParent() == null; + TreePath path = !root ? getTreePath(item.getParent()) : null; + fireTreeNodesChanged(new TreeModelEvent(JAXXTreeModel.this, path, + !root ? new int[]{item.getParent().getChildren().indexOf(item)} : null, + new Object[]{item.getValue()})); + } + } + }; + addPropertyChangeListener(root, listener); + } + + private void addPropertyChangeListener(Item item, PropertyChangeListener listener) { + item.addPropertyChangeListener(listener); + List<Item> children = item.getChildren(); + for (Item aChildren : children) { + addPropertyChangeListener(aChildren, listener); + } + } + + @Override + public void addTreeModelListener(TreeModelListener listener) { + listeners.add(listener); + } + + + /* This is an inefficient implementation, but hand-coded tree structures are unlikely to contain + enough nodes for that to really matter. This could be sped up with caching. */ + public Item findItem(Object value) { + return findItem(root, value); + } + + private Item findItem(Item node, Object value) { + if (node.getValue() == value) { + return node; + } else { + List<Item> children = node.getChildren(); + for (Item aChildren : children) { + Item result = findItem(aChildren, value); + if (result != null) { + return result; + } + } + return null; + } + } + + private TreePath getTreePath(Item node) { + List<Object> path = new ArrayList<Object>(); + while (node != null) { + path.add(0, node.getValue()); + node = node.getParent(); + } + return new TreePath(path.toArray()); + } + + @Override + public Object getChild(Object parent, int index) { + Item node = findItem(parent); + return node.getChildren().get(index).getValue(); + } + + @Override + public int getChildCount(Object parent) { + Item node = findItem(parent); + if (node == null) { + return 0; + } + return node.getChildren().size(); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + Item node = findItem(parent); + List<Item> children = node.getChildren(); + for (int i = 0, j = children.size(); i < j; i++) { + if (children.get(i).getValue() == child) { + return i; + } + } + return -1; + } + + @Override + public Object getRoot() { + return root.getValue(); + } + + public Item getRootItem() { + return root; + } + + @Override + public boolean isLeaf(Object node) { + Item item = findItem(node); + return item != null && item.getChildren().size() == 0; + } + + @Override + public void removeTreeModelListener(TreeModelListener listener) { + listeners.remove(listener); + } + + public void fireTreeNodesChanged(TreeModelEvent e) { + for (TreeModelListener listener : listeners) { + listener.treeNodesChanged(e); + } + } + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + } + } + + public JAXXTree(TreeModel model) { + super(model); + } + + public JAXXTree() { + setCellRenderer(new DefaultTreeCellRenderer() { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { + TreeModel model = tree.getModel(); + if (model instanceof JAXXTreeModel) { + Item item = ((JAXXTreeModel) model).findItem(value); + if (item != null) { + String label = item.getLabel(); + if (label != null) { + value = label; + } + } + } + return super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + } + }); + + addTreeSelectionListener(new TreeSelectionListener() { + + @Override + public void valueChanged(TreeSelectionEvent e) { + TreeModel model = getModel(); + if (model instanceof JAXXTreeModel) { + scan((JAXXTreeModel) model, ((JAXXTreeModel) model).root); + } + } + + private void scan(JAXXTreeModel model, Item item) { + TreePath path = model.getTreePath(item); + if (item.isSelected() != isPathSelected(path)) { + item.setSelected(!item.isSelected()); + } + List<Item> children = item.getChildren(); + for (Item aChildren : children) { + scan(model, aChildren); + } + } + }); + } + + public void setItem(Item items) { + List<Item> newItems = new ArrayList<Item>(); + newItems.add(items); + setItems(newItems); + } + + public void setItems(List<Item> items) { + // Create model + JAXXTreeModel model = new JAXXTreeModel(items); + if (model.getRoot() != null) { + setRootVisible(model.getRoot() != SYNTHETIC); + } + // Atach model + setModel(model); + + // Appli selected items + if (items != null) { + List<TreePath> treePathSelected = new ArrayList<TreePath>(); + for (Item i : items) { + if (i.isSelected()) { + treePathSelected.add(model.getTreePath(i)); + } + } + setSelectionPaths(convertToTreePathArray(treePathSelected.toArray())); + } + } + + public Object getSelectionValue() { + TreePath selectionPath = getSelectionPath(); + return selectionPath != null ? selectionPath.getLastPathComponent() : null; + } + + public Item getRootItem() { + if (getModel() instanceof JAXXTreeModel) { + return ((JAXXTreeModel) getModel()).getRootItem(); + } + return null; + } + + protected TreePath[] convertToTreePathArray(Object[] datas) { + TreePath[] params = new TreePath[datas.length]; + System.arraycopy(datas, 0, params, 0, datas.length); + return params; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/OneClicListSelectionModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/OneClicListSelectionModel.java new file mode 100644 index 0000000..6522986 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/OneClicListSelectionModel.java @@ -0,0 +1,208 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionListener; +import java.util.Arrays; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class OneClicListSelectionModel implements ListSelectionModel { + + /** Logger */ + static private Log log = LogFactory.getLog(OneClicListSelectionModel.class); + + protected ListSelectionModel delegate; + + protected final ListModel model; + + private boolean[] _states; + + public OneClicListSelectionModel(ListSelectionModel delegate, ListModel model) { + this.delegate = delegate; + this.model = model; + delegate.clearSelection(); + } + + protected boolean[] getStates(int selectedIndex) { + int max = model.getSize(); + if (_states == null || _states.length != max) { + _states = new boolean[max]; + } else { + Arrays.fill(_states, false); + } + for (int i = 0; i < max; i++) { + _states[i] = i != selectedIndex && delegate.isSelectedIndex(i); + } + return _states; + } + + @Override + public void setSelectionInterval(int index0, int index1) { + if (index0 != index1) { + // not a single selection (come from a click) + // use default behaviour + delegate.setSelectionInterval(index0, index1); + return; + } + delegate.setValueIsAdjusting(true); + + try { + int max = model.getSize(); + + if (log.isDebugEnabled()) { + log.debug("single [index:" + index0 + "] [selected:" + isSelectedIndex(index0) + "] [size:" + max + "] [anchor:" + delegate.getAnchorSelectionIndex() + "] [lead:" + delegate.getLeadSelectionIndex() + "]"); + } + + if (!isSelectedIndex(index0)) { + // select it + delegate.addSelectionInterval(index0, index1); + return; + } + if (max == index0) { + // last selected index, so can directly remove it + delegate.removeIndexInterval(index0, index0); + return; + } + + // must recompute the selection removing only the index0 item + boolean[] state = getStates(index0); + + if (log.isDebugEnabled()) { + log.debug("state : " + Arrays.toString(state)); + } + delegate.clearSelection(); + for (int i = 0; i < max; i++) { + if (state[i]) { + delegate.addSelectionInterval(i, i); + } + } + } finally { + delegate.setValueIsAdjusting(false); + } + } + + @Override + public void addSelectionInterval(int index0, int index1) { + delegate.addSelectionInterval(index0, index1); + } + + @Override + public void removeSelectionInterval(int index0, int index1) { + delegate.removeSelectionInterval(index0, index1); + } + + @Override + public int getMinSelectionIndex() { + return delegate.getMinSelectionIndex(); + } + + @Override + public int getMaxSelectionIndex() { + return delegate.getMaxSelectionIndex(); + } + + @Override + public boolean isSelectedIndex(int index) { + return delegate.isSelectedIndex(index); + } + + @Override + public int getAnchorSelectionIndex() { + return delegate.getAnchorSelectionIndex(); + } + + @Override + public void setAnchorSelectionIndex(int index) { + delegate.setAnchorSelectionIndex(index); + } + + @Override + public int getLeadSelectionIndex() { + return delegate.getLeadSelectionIndex(); + } + + @Override + public void setLeadSelectionIndex(int index) { + delegate.setLeadSelectionIndex(index); + } + + @Override + public void clearSelection() { + delegate.clearSelection(); + } + + @Override + public boolean isSelectionEmpty() { + return delegate.isSelectionEmpty(); + } + + @Override + public void insertIndexInterval(int index, int length, boolean before) { + delegate.insertIndexInterval(index, length, before); + } + + @Override + public void removeIndexInterval(int index0, int index1) { + delegate.removeIndexInterval(index0, index1); + } + + @Override + public void setValueIsAdjusting(boolean valueIsAdjusting) { + delegate.setValueIsAdjusting(valueIsAdjusting); + } + + @Override + public boolean getValueIsAdjusting() { + return delegate.getValueIsAdjusting(); + } + + @Override + public void setSelectionMode(int selectionMode) { + delegate.setSelectionMode(selectionMode); + } + + @Override + public int getSelectionMode() { + return delegate.getSelectionMode(); + } + + @Override + public void addListSelectionListener(ListSelectionListener x) { + delegate.addListSelectionListener(x); + } + + @Override + public void removeListSelectionListener(ListSelectionListener x) { + delegate.removeListSelectionListener(x); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Spacer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Spacer.java new file mode 100644 index 0000000..112a55a --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Spacer.java @@ -0,0 +1,32 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JComponent; + +public class Spacer extends JComponent { + + private static final long serialVersionUID = 1L; +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfo.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfo.java new file mode 100644 index 0000000..0ae1575 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfo.java @@ -0,0 +1,234 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.event.SwingPropertyChangeSupport; +import java.awt.Color; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class TabInfo { + + public static String BACKGROUND_PROPERTY = "background"; + + public static String TAB_COMPONENT_PROPERTY = "tabComponent"; + + public static String TAB_COMPONENT_STR_PROPERTY = "tabComponentStr"; + + public static String DISABLED_ICON_PROPERTY = "disabledIcon"; + + public static String DISPLAYED_MNEMONIC_INDEX_PROPERTY = "displayedMnemonicIndex"; + + public static String ENABLED_PROPERTY = "enabled"; + + public static String FOREGROUND_PROPERTY = "foreground"; + + public static String ICON_PROPERTY = "icon"; + + public static String MNEMONIC_PROPERTY = "mnemonic"; + + public static String TITLE_PROPERTY = "title"; + + public static String TOOL_TIP_TEXT_PROPERTY = "toolTipText"; + + private String id; + + private Color background; + + private Icon disabledIcon; + + private int displayedMnemonicIndex = -1; + + private boolean enabled = true; + + private Color foreground; + + private Icon icon; + + private int mnemonic = -1; + + private String title; + + private String toolTipText; + + private JComponent tabComponent; + + private String tabComponentStr; + + private PropertyChangeSupport propertyChangeSupport; + + public TabInfo() { + } + + public TabInfo(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public Color getBackground() { + return background; + } + + public void setBackground(Color background) { + Color oldValue = this.background; + this.background = background; + firePropertyChange(BACKGROUND_PROPERTY, oldValue, background); + } + + public Icon getDisabledIcon() { + return disabledIcon; + } + + public void setDisabledIcon(Icon disabledIcon) { + Icon oldValue = this.disabledIcon; + this.disabledIcon = disabledIcon; + firePropertyChange(DISABLED_ICON_PROPERTY, oldValue, disabledIcon); + } + + public int getDisplayedMnemonicIndex() { + return displayedMnemonicIndex; + } + + public void setDisplayedMnemonicIndex(int displayedMnemonicIndex) { + int oldValue = this.displayedMnemonicIndex; + this.displayedMnemonicIndex = displayedMnemonicIndex; + firePropertyChange(DISPLAYED_MNEMONIC_INDEX_PROPERTY, oldValue, displayedMnemonicIndex); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + boolean oldValue = this.enabled; + this.enabled = enabled; + firePropertyChange(ENABLED_PROPERTY, oldValue, enabled); + } + + public Color getForeground() { + return foreground; + } + + public void setForeground(Color foreground) { + Color oldValue = this.foreground; + this.foreground = foreground; + firePropertyChange(FOREGROUND_PROPERTY, oldValue, foreground); + } + + public Icon getIcon() { + return icon; + } + + public void setIcon(Icon icon) { + Icon oldValue = this.icon; + this.icon = icon; + firePropertyChange(ICON_PROPERTY, oldValue, icon); + } + + public int getMnemonic() { + return mnemonic; + } + + public void setMnemonic(int mnemonic) { + int oldValue = this.mnemonic; + this.mnemonic = mnemonic; + firePropertyChange(MNEMONIC_PROPERTY, oldValue, mnemonic); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + String oldValue = this.title; + this.title = title; + firePropertyChange(TITLE_PROPERTY, oldValue, title); + } + + public String getToolTipText() { + return toolTipText; + } + + public void setToolTipText(String toolTipText) { + String oldValue = this.toolTipText; + this.toolTipText = toolTipText; + firePropertyChange(TOOL_TIP_TEXT_PROPERTY, oldValue, toolTipText); + } + + public JComponent getTabComponent() { + return tabComponent; + } + + public void setTabComponent(JComponent tabComponent) { + JComponent oldValue = this.tabComponent; + this.tabComponent = tabComponent; + firePropertyChange(TAB_COMPONENT_PROPERTY, oldValue, tabComponent); + } + + + public String getTabComponentStr() { + return tabComponentStr; + } + + public void setTabComponentStr(String tabComponentStr) { + String oldValue = this.tabComponentStr; + this.tabComponentStr = tabComponentStr; + firePropertyChange(TAB_COMPONENT_STR_PROPERTY, oldValue, tabComponent); + } + + private PropertyChangeSupport getPropertyChangeSupport() { + if (propertyChangeSupport == null) { + propertyChangeSupport = new SwingPropertyChangeSupport(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); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (propertyChangeSupport != null) { + getPropertyChangeSupport().firePropertyChange(propertyName, oldValue, newValue); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfoPropertyChangeListener.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfoPropertyChangeListener.java new file mode 100644 index 0000000..9e8eee9 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/TabInfoPropertyChangeListener.java @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.Icon; +import javax.swing.JTabbedPane; +import java.awt.Color; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class TabInfoPropertyChangeListener implements PropertyChangeListener { + + private JTabbedPane tabs; + + private int tabIndex; + + public TabInfoPropertyChangeListener(JTabbedPane tabs, int tabIndex) { + this.tabs = tabs; + this.tabIndex = tabIndex; + } + + @Override + public void propertyChange(PropertyChangeEvent e) { + String name = e.getPropertyName(); + if (name.equals(TabInfo.TITLE_PROPERTY)) { + tabs.setTitleAt(tabIndex, (String) e.getNewValue()); + } else if (name.equals(TabInfo.TOOL_TIP_TEXT_PROPERTY)) { + tabs.setToolTipTextAt(tabIndex, (String) e.getNewValue()); + } else if (name.equals(TabInfo.FOREGROUND_PROPERTY)) { + tabs.setForegroundAt(tabIndex, (Color) e.getNewValue()); + } else if (name.equals(TabInfo.BACKGROUND_PROPERTY)) { + tabs.setBackgroundAt(tabIndex, (Color) e.getNewValue()); + } else if (name.equals(TabInfo.MNEMONIC_PROPERTY)) { + tabs.setMnemonicAt(tabIndex, (Integer) e.getNewValue()); + } else if (name.equals(TabInfo.DISPLAYED_MNEMONIC_INDEX_PROPERTY)) { + tabs.setDisplayedMnemonicIndexAt(tabIndex, (Integer) e.getNewValue()); + } else if (name.equals(TabInfo.ICON_PROPERTY)) { + tabs.setIconAt(tabIndex, (Icon) e.getNewValue()); + } else if (name.equals(TabInfo.DISABLED_ICON_PROPERTY)) { + tabs.setDisabledIconAt(tabIndex, (Icon) e.getNewValue()); + } else if (name.equals(TabInfo.TAB_COMPONENT_PROPERTY)) { + tabs.setTabComponentAt(tabIndex, (Component) e.getNewValue()); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Table.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Table.java new file mode 100644 index 0000000..581310e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/Table.java @@ -0,0 +1,82 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JPanel; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.LayoutManager; + +/** + * Panel which uses a {@link GridBagLayout} by default. + * + * @author Ethan Nicholas + */ +public class Table extends JPanel { + + private static final long serialVersionUID = 1L; + + public static final Insets DEFAULT_INSETS = new Insets(3, 3, 3, 3); + + private GridBagConstraints tableConstraints = new GridBagConstraints(); + + private GridBagConstraints rowConstraints; + + private GridBagConstraints cellConstraints; + + public Table() { + super.setLayout(new GridBagLayout()); + + tableConstraints.insets = DEFAULT_INSETS; + } + + @Override + public void setLayout(LayoutManager layout) { + // do nothing + } + + public GridBagConstraints getTableConstraints() { + return tableConstraints; + } + + public GridBagConstraints getRowConstraints() { + return rowConstraints; + } + + public GridBagConstraints getCellConstraints() { + return cellConstraints; + } + + public void newRow() { + tableConstraints.gridy++; + rowConstraints = (GridBagConstraints) tableConstraints.clone(); + } + + public void newCell() { + rowConstraints.gridx++; + cellConstraints = (GridBagConstraints) rowConstraints.clone(); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBox.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBox.java new file mode 100644 index 0000000..74f4009 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBox.java @@ -0,0 +1,119 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JPanel; +import java.awt.Insets; + +/** + * Panel which uses a {@link VBoxLayout} by default. + * + * @author Ethan Nicholas + */ +public class VBox extends JPanel { + + private static final long serialVersionUID = 1L; + + public static final String SPACING_PROPERTY = "spacing"; + + public static final String MARGIN_PROPERTY = "margin"; + + public static final String HORIZONTAL_ALIGNMENT_PROPERTY = "horizontalAlignment"; + + public static final String VERTICAL_ALIGNMENT_PROPERTY = "verticalAlignment"; + + private Insets margin; + + public VBox() { + super(new VBoxLayout()); + } + + /** + * Returns the spacing between components, in pixels. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @return spacing between components + */ + public int getSpacing() { + return ((VBoxLayout) getLayout()).getSpacing(); + } + + /** + * Sets the spacing between components. Spacing is applied between components only, + * not to the top or bottom of the container. + * + * @param spacing new spacing value + */ + public void setSpacing(int spacing) { + int oldValue = getSpacing(); + ((VBoxLayout) getLayout()).setSpacing(spacing); + firePropertyChange(SPACING_PROPERTY, oldValue, spacing); + revalidate(); + } + + public int getHorizontalAlignment() { + return ((VBoxLayout) getLayout()).getHorizontalAlignment(); + } + + public void setHorizontalAlignment(int horizontalAlignment) { + int oldValue = getHorizontalAlignment(); + ((VBoxLayout) getLayout()).setHorizontalAlignment(horizontalAlignment); + firePropertyChange(HORIZONTAL_ALIGNMENT_PROPERTY, oldValue, horizontalAlignment); + revalidate(); + } + + public int getVerticalAlignment() { + return ((VBoxLayout) getLayout()).getVerticalAlignment(); + } + + public void setVerticalAlignment(int verticalAlignment) { + int oldValue = getVerticalAlignment(); + ((VBoxLayout) getLayout()).setVerticalAlignment(verticalAlignment); + firePropertyChange(VERTICAL_ALIGNMENT_PROPERTY, oldValue, verticalAlignment); + revalidate(); + } + + public Insets getMargin() { + return margin; + } + + public void setMargin(Insets margin) { + Insets oldValue = this.margin; + this.margin = (Insets) margin.clone(); + firePropertyChange(MARGIN_PROPERTY, oldValue, margin); + } + + @Override + public Insets getInsets() { + Insets result = super.getInsets(); + if (margin != null) { + result.top += margin.top; + result.left += margin.left; + result.right += margin.right; + result.bottom += margin.bottom; + } + return result; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxBeanInfo.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxBeanInfo.java new file mode 100644 index 0000000..1bfcdfe --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxBeanInfo.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; + +public class VBoxBeanInfo extends SimpleBeanInfo { + + @Override + public BeanInfo[] getAdditionalBeanInfo() { + try { + return new BeanInfo[]{Introspector.getBeanInfo(JPanel.class)}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } + + @Override + public PropertyDescriptor[] getPropertyDescriptors() { + try { + PropertyDescriptor spacing = new PropertyDescriptor("spacing", VBox.class); + spacing.setBound(true); + + PropertyDescriptor margin = new PropertyDescriptor("margin", VBox.class); + margin.setBound(true); + + PropertyDescriptor horizontalAlignment = new PropertyDescriptor("horizontalAlignment", VBox.class); + horizontalAlignment.setBound(true); + horizontalAlignment.setValue("enumerationValues", new Object[]{ + "left", SwingConstants.LEFT, "SwingConstants.LEFT", + "center", SwingConstants.CENTER, "SwingConstants.CENTER", + "right", SwingConstants.RIGHT, "SwingConstants.RIGHT" + }); + + PropertyDescriptor verticalAlignment = new PropertyDescriptor("verticalAlignment", VBox.class); + verticalAlignment.setBound(true); + verticalAlignment.setValue("enumerationValues", new Object[]{ + "top", SwingConstants.TOP, "SwingConstants.TOP", + "middle", SwingConstants.CENTER, "SwingConstants.CENTER", + "bottom", SwingConstants.BOTTOM, "SwingConstants.BOTTOM" + }); + + return new PropertyDescriptor[]{spacing, margin, horizontalAlignment, verticalAlignment}; + } catch (IntrospectionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxLayout.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxLayout.java new file mode 100644 index 0000000..1680af8 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/VBoxLayout.java @@ -0,0 +1,149 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.SwingConstants; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; + +/** + * Vertical box layout. The layout rules followed by this class are quite different than the core BoxLayout class, + * and in general represent a more useful algorithm. + * + * @author Ethan Nicholas + */ +public class VBoxLayout implements LayoutManager { + + private int spacing = 6; + + private int horizontalAlignment = SwingConstants.LEFT; + + private int verticalAlignment = SwingConstants.TOP; + + public int getSpacing() { + return spacing; + } + + public void setSpacing(int spacing) { + this.spacing = spacing; + } + + public int getHorizontalAlignment() { + return horizontalAlignment; + } + + public void setHorizontalAlignment(int horizontalAlignment) { + this.horizontalAlignment = horizontalAlignment; + } + + public int getVerticalAlignment() { + return verticalAlignment; + } + + public void setVerticalAlignment(int verticalAlignment) { + this.verticalAlignment = verticalAlignment; + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + + @Override + public void layoutContainer(Container parent) { + Insets insets = parent.getInsets(); + int parentWidth = parent.getSize().width - insets.left - insets.right; + int count = parent.getComponentCount(); + Dimension preferredSize = parent.getPreferredSize(); + int y; + switch (verticalAlignment) { + case SwingConstants.TOP: + y = insets.top; + break; + case SwingConstants.CENTER: + y = insets.top + (parent.getHeight() - preferredSize.height) / 2; + break; + case SwingConstants.BOTTOM: + y = insets.top + (parent.getHeight() - preferredSize.height); + break; + default: + throw new IllegalArgumentException("invalid vertical alignment: " + verticalAlignment); + } + + for (int i = 0; i < count; i++) { + Component component = parent.getComponent(i); + Dimension childPreferredSize = component.getPreferredSize(); + int width = Math.min(childPreferredSize.width, parentWidth); + int x; + switch (horizontalAlignment) { + case SwingConstants.LEFT: + x = insets.left; + break; + case SwingConstants.CENTER: + x = insets.left + (parentWidth - childPreferredSize.width) / 2; + break; + case SwingConstants.RIGHT: + x = insets.left + (parentWidth - childPreferredSize.width); + break; + default: + throw new IllegalArgumentException("invalid horizontal alignment: " + horizontalAlignment); + } + component.setBounds(x, y, width, childPreferredSize.height); + y += childPreferredSize.height + spacing; + } + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + int width = 0; + int height = (parent.getComponentCount() - 1) * spacing; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension minimumSize = parent.getComponent(i).getMinimumSize(); + width = Math.max(width, minimumSize.width); + height += minimumSize.height; + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + int width = 0; + int height = (parent.getComponentCount() - 1) * spacing; + for (int i = parent.getComponentCount() - 1; i >= 0; i--) { + Dimension preferredSize = parent.getComponent(i).getPreferredSize(); + width = Math.max(width, preferredSize.width); + height += preferredSize.height; + } + Insets insets = parent.getInsets(); + return new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom); + } + + @Override + public void removeLayoutComponent(Component comp) { + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionExecutor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionExecutor.java new file mode 100644 index 0000000..e1b457e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionExecutor.java @@ -0,0 +1,279 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.application; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ReflectUtil; + +import javax.swing.SwingWorker; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +/** + * Executor of {@link ActionWorker}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public abstract class ActionExecutor { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ActionExecutor.class); + + /** current tasks */ + protected final Set<ActionWorker<?, ?>> tasks = + new HashSet<ActionWorker<?, ?>>(); + + /** the listener of running action */ + protected final PropertyChangeListener workerListener; + + /** + * Hook when a action is about to start. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionStart(ActionWorker<?, ?> source); + + /** + * Hook when a action has failed. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionFail(ActionWorker<?, ?> source); + + /** + * Hook when a action has been canceled. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionCancel(ActionWorker<?, ?> source); + + /** + * Hook when a action has end with no failure or cancel. + * + * @param source the action worker containing the action to perform + */ + public abstract void onActionEnd(ActionWorker<?, ?> source); + + /** + * Hook atfer action is consumed. + * + * @param source the action worker containing the action to perform + */ + public abstract void onAfterAction(ActionWorker<?, ?> source); + + public ActionExecutor() { + workerListener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("action " + evt.getSource() + " property " + + evt.getPropertyName() + " changed <" + + evt.getOldValue() + " - " + evt.getNewValue() + + '>'); + } + + if ("state".equals(evt.getPropertyName())) { + ActionWorker<?, ?> source = (ActionWorker<?, ?>) evt.getSource(); + SwingWorker.StateValue state = + (SwingWorker.StateValue) evt.getNewValue(); + + if (state == SwingWorker.StateValue.STARTED) { + // starting new action + + onActionStart(source); + return; + } + + if (state == SwingWorker.StateValue.DONE) { + // on rend la main au thread pour qu'il attende une + // prochaine operation + + ActionWorker.ActionStatus status = source.getStatus(); + if (log.isDebugEnabled()) { + log.debug("Action [" + source.getActionLabel() + + "] status = " + status); + } + try { + switch (status) { + + case OK: + onActionEnd(source); + break; + case CANCEL: + onActionCancel(source); + break; + case FAIL: + onActionFail(source); + break; + } + } finally { + tasks.remove(source); + onAfterAction(source); + } + } + } + } + }; + } + + /** + * Add an new action to perform. + * + * @param actionLabel the name of the action to perform + * @param action the action to perform + * @return the worker that will launch the action + */ + public ActionWorker<?, ?> addAction(String actionLabel, Runnable action) { + + ActionWorker<?, ?> worker; + if (action instanceof ActionWorker) { + + worker = (ActionWorker<?, ?>) action; + } else { + + worker = new ActionWorker(actionLabel, action); + } + worker.addPropertyChangeListener(workerListener); + tasks.add(worker); + worker.execute(); + return worker; + } + + /** + * Ask the thread to stop. + * <p/> + * It will finish all incoming files (but will not accept more tasks). + * <p/> + * <b>Note:</b> The method does not return until all tasks are not + * consumed. + * + * @throws InterruptedException if something wrong while waiting end of + * executor + */ + public void terminatesAndWaits() throws InterruptedException { + + if (log.isDebugEnabled()) { + log.debug("Executor " + this + " is terminating..."); + } + + // ask executor to terminate + for (ActionWorker<?, ?> task : tasks) { + task.cancel(true); + } + + if (log.isDebugEnabled()) { + log.debug("Executor " + this + " is terminated at " + new Date()); + } + } + + public int getNbActions() { + return getTasks().size(); + } + + public Set<ActionWorker<?, ?>> getTasks() { + return tasks; + } + + /** + * Creates a runnable instance (via a Proxy) to a method given by his name + * ({@code methodName}) to invoke on {@code methodcontainer} with given + * {@code arguments}. + * <p/> + * This is a great feature to create runnable code with a real context. + * + * @param methodContainer the container of the method to invoke + * @param methodName the name of the method to invoke + * @param arguments parameters to pass to method to invke. + * @return the proxy instance + */ + public Runnable createRunnable(final Object methodContainer, + String methodName, + final Object... arguments) { + + // find method + + Class<?> klass = methodContainer.getClass(); + final Method targetMethod = ReflectUtil.getDeclaredMethod(klass, + methodName, + true, + arguments + ); + targetMethod.setAccessible(true); + Runnable result; + + // create runnable proxy + + result = (Runnable) Proxy.newProxyInstance( + getClass().getClassLoader(), + new Class<?>[]{Runnable.class}, + new InvocationHandler() { + + @Override + public Object invoke(Object proxy, + Method method, + Object[] args) { + String methodName = method.getName(); + + if ("run".equals(methodName)) { + try { + if (log.isDebugEnabled()) { + log.debug("will invoke run method"); + } + return targetMethod.invoke(methodContainer, arguments); + } catch (IllegalAccessException e) { + throw new RuntimeException( + "could not invoke on container " + + methodContainer, e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + if (methodName.equals("toString")) { + return toString(); + } + if (methodName.equals("equals")) { + return equals(args[0]); + } + if (methodName.equals("hashCode")) { + return hashCode(); + } + return null; + } + } + ); + return result; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionWorker.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionWorker.java new file mode 100644 index 0000000..f09a2de --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ActionWorker.java @@ -0,0 +1,178 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.application; + +import com.google.common.base.Preconditions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; + +import javax.swing.SwingWorker; +import java.util.concurrent.Callable; + +/** + * Action worker to execute a incoming action. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public class ActionWorker<R, P> extends SwingWorker<R, P> { + + /** Logger */ + private static final Log log = LogFactory.getLog(ActionWorker.class); + + protected final String actionLabel; + + protected Callable<R> target; + + protected ActionStatus status; + + protected Exception error; + + protected long startTime; + + protected long endTime; + + public ActionWorker(String actionLabel) { + this.actionLabel = actionLabel; + } + + public ActionWorker(String actionLabel, Runnable target) { + this.target = new RunnableBridge<R>(target); + this.actionLabel = actionLabel; + } + + public Callable<R> getTarget() { + return target; + } + + public void setTarget(Runnable target) { + setTarget(new RunnableBridge<R>(target)); + } + + /** + * Set the target to execute. + * + * @param target the target to execute + * @since 2.5.1 + */ + public void setTarget(Callable<R> target) { + this.target = target; + } + + @Override + protected R doInBackground() throws Exception { + Preconditions.checkNotNull(target != null, "Targe field can not be null here."); + startTime = System.nanoTime(); + if (log.isDebugEnabled()) { + log.debug("Action [" + getActionLabel() + "] is starting..."); + } + R result = null; + try { + + result = getTarget().call(); + } catch (Exception e) { + error = e; + } finally { + if (log.isDebugEnabled()) { + log.debug("Action [" + getActionLabel() + "] is ending..."); + } + } + return result; + } + + public boolean isFailed() { + return (isDone() || isCancelled()) && error != null; + } + + public Exception getError() { + return error; + } + + public ActionStatus getStatus() { + return status; + } + + public String getActionLabel() { + return actionLabel; + } + + @Override + protected void done() { + super.done(); + endTime = System.nanoTime(); + if (error != null) { + status = ActionStatus.FAIL; + } else if (isCancelled()) { + status = ActionStatus.CANCEL; + } else { + status = ActionStatus.OK; + } + if (log.isDebugEnabled()) { + log.debug("Action [" + getActionLabel() + "] ends with status : " + status + " in " + getTime()); + } + } + + public String getTime() { + return StringUtil.convertTime(endTime - startTime); + } + + public long getStartTime() { + return startTime; + } + + public long getEndTime() { + return endTime; + } + + /** State of a running action */ + public enum ActionStatus { + OK, + CANCEL, + FAIL + } + + /** + * Transform a {@link Runnable} into a {@link Callable}. + * + * @param <R> type of return (used to maintain generic checks in this class). + * @since 2.5.1 + */ + private static class RunnableBridge<R> implements Callable<R> { + + private final Runnable target; + + public RunnableBridge(Runnable target) { + this.target = target; + } + + @Override + public R call() throws Exception { + target.run(); + return null; + } + } + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ApplicationRunner.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ApplicationRunner.java new file mode 100644 index 0000000..fce66bf --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/application/ApplicationRunner.java @@ -0,0 +1,250 @@ +/* + * #%L + * JAXX :: Runtime + * * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.application; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Simple application runner which authorize to reload an application. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public abstract class ApplicationRunner { + + /** Logger */ + private static Log log = LogFactory.getLog(ApplicationRunner.class); + + private static final Object lock = new Object(); + + private static ApplicationRunner runner; + + public static ApplicationRunner getRunner() { + if (runner == null) { + throw new IllegalStateException("No runner initialized"); + } + return runner; + } + + public static void lock() throws InterruptedException { + synchronized (lock) { + // on arrete le thread principal + // pour rendre la main a la methode main + lock.wait(); + } + } + + public static void unlock() { + synchronized (lock) { + // on arrete le thread principal + // pour rendre la main a la methode main + lock.notifyAll(); + } + } + + /** arguments given to runner at launch time */ + protected final String[] args; + + /** flag to reload the runner when closing it */ + protected boolean reload; + + /** the runner to start application */ + protected final Runnable runnable; + + protected long startingTime; + + protected Exception error; + + /** + * To execute some code only once. + * <p/> + * This code will not be re-execute when reloading the runner. + */ + protected abstract void initOnce(); + + /** + * Hook to init runner. + * + * @throws Exception if any problem + */ + protected abstract void onInit() throws Exception; + + /** + * Hook to start runner. + * + * @throws Exception if any problem + */ + protected abstract void onStart() throws Exception; + + /** + * Hook to close runner. + * + * @param reload if reload was asked + * @throws Exception if any problme + */ + protected abstract void onClose(boolean reload) throws Exception; + + /** + * Hook to shutdown launcher + * + * @throws Exception if any problem + */ + protected abstract void onShutdown() throws Exception; + + /** + * Hook to shutdown launcher when an exception occurs on clsoing. + * + * @param ex the error catched while closing launcher + */ + protected abstract void onShutdown(Exception ex); + + /** + * Hook when an error occurs in runner. + * + * @param e the error catched + */ + protected abstract void onError(Exception e); + + protected ApplicationRunner(String... args) { + runner = this; + this.args = args; + + initOnce(); + + runnable = new Runnable() { + @Override + public void run() { + startingTime = System.nanoTime(); + try { + + onInit(); + + onStart(); + + } catch (Exception e) { + error = e; + onError(e); + unlock(); + } + } + }; + + Thread shutdownHook = new Thread(new Runnable() { + + @Override + public void run() { + try { + + //onClose(false); + onShutdown(); + + } catch (Exception e) { + error = e; + onShutdown(e); + } + } + }, "ShutDown " + getClass().getSimpleName()); + + Runtime.getRuntime().addShutdownHook(shutdownHook); + } + + public boolean isReload() { + return reload; + } + + public void setReload(boolean reload) { + this.reload = reload; + } + + protected Thread mainThread; + + public final void launch() { + + // au demarrage le reload est toujours desactive + reload = false; + + // preparation du thread de l'application principale + // que l'on démarre + mainThread = new Thread(runnable, getClass().getSimpleName()); + mainThread.start(); + + try { + + // on attend que l'application se termine ou demande un redémarrage + lock(); + + // on va libérer le runner + log.info("Application [" + mainThread + "] is closing..."); + + } catch (InterruptedException e) { + if (log.isErrorEnabled()) { + log.error(mainThread + " was interrupted for reason " + e.getMessage(), e); + } + } finally { + + close(); + + } + } + + public final void close() { + boolean doReload = isReload(); + + try { + + // fermeture du runner + onClose(doReload); + + if (doReload) { + + // redemarrage du runner + + if (log.isInfoEnabled()) { + log.info("Will reload application"); + } + + System.runFinalization(); + + launch(); + } + + } catch (Exception e) { + onError(e); + } finally { + if (!doReload) { + if (log.isDebugEnabled()) { + log.debug("Will shutdown application ..."); + } + + unlock(); + + // force to shutdown + Runtime.getRuntime().exit(0); + } + } + } + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/BooleanCellEditor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/BooleanCellEditor.java new file mode 100644 index 0000000..4768385 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/BooleanCellEditor.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id: BooleanCellRenderer.java 2334 2012-06-15 10:02:35Z sletellier $ + * $HeadURL: http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime... $ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor; + +import java.awt.Component; +import javax.swing.AbstractCellEditor; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import org.jdesktop.swingx.JXTable; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class BooleanCellEditor extends AbstractCellEditor implements TableCellRenderer, TableCellEditor { + + private static final long serialVersionUID = 1L; + + protected TableCellRenderer rendererDelegate; + protected TableCellEditor editorDelegate; + + protected Icon icon; + + public BooleanCellEditor(TableCellRenderer delegate) { + this(delegate, null); + } + + public BooleanCellEditor(TableCellRenderer delegate, Icon icon) { + this.rendererDelegate = delegate; + this.editorDelegate = new JXTable.BooleanEditor(); + this.icon = icon; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JComponent rendered = (JComponent) rendererDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (rendered instanceof JCheckBox) { + JCheckBox checkBox = (JCheckBox)rendered; + checkBox.setHorizontalAlignment(JLabel.CENTER); + checkBox.setVerticalTextPosition(JLabel.TOP); + checkBox.setBorderPainted(true); + checkBox.setIcon(icon); + } + return rendered; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + return editorDelegate.getTableCellEditorComponent(table, value, isSelected, row, column); + } + + @Override + public Object getCellEditorValue() { + return editorDelegate.getCellEditorValue(); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ClassCellEditor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ClassCellEditor.java new file mode 100644 index 0000000..e4da130 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/ClassCellEditor.java @@ -0,0 +1,126 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor; + +import org.apache.commons.beanutils.Converter; +import org.nuiton.util.converter.ConverterUtil; + +import javax.swing.DefaultCellEditor; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.event.CellEditorListener; +import javax.swing.table.TableCellEditor; +import java.awt.Component; +import java.util.EventObject; + +/** + * A class cell editor (fork from comandline project). + * + * @author tchemit <chemit@codelutin.com> + */ +public class ClassCellEditor implements TableCellEditor { + + protected TableCellEditor delegate; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + + String valStr = (value + "").trim(); + if (valStr.equals("null")) { + valStr = ""; + } else if (valStr.startsWith("class ")) { + valStr = valStr.substring(6); + } + Component comp; + comp = getDelegate().getTableCellEditorComponent(table, valStr, isSelected, row, column); + return comp; + } + + @Override + public Object getCellEditorValue() { + Object o = !hasDelegate() ? null : delegate.getCellEditorValue(); + if (o == null) { + return null; + } + Converter converter = ConverterUtil.getConverter(Class.class); + + try { + if (converter != null) { + return converter.convert(Class.class, o); + } + o = Class.forName(o + ""); + } catch (Exception e) { + o = null; + } + return o; + } + + @Override + public boolean isCellEditable(EventObject anEvent) { + return !hasDelegate() || delegate.isCellEditable(anEvent); + } + + @Override + public boolean shouldSelectCell(EventObject anEvent) { + return hasDelegate() && delegate.shouldSelectCell(anEvent); + } + + @Override + public boolean stopCellEditing() { + return !hasDelegate() || delegate.stopCellEditing(); + } + + @Override + public void cancelCellEditing() { + if (hasDelegate()) { + delegate.cancelCellEditing(); + } + } + + @Override + public void addCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.addCellEditorListener(l); + } + } + + @Override + public void removeCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.removeCellEditorListener(l); + } + } + + protected TableCellEditor getDelegate() { + if (delegate == null) { + delegate = new DefaultCellEditor(new JTextField()); + } + return delegate; + } + + protected boolean hasDelegate() { + return delegate != null; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/EnumEditor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/EnumEditor.java new file mode 100644 index 0000000..ab352e4 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/EnumEditor.java @@ -0,0 +1,143 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* + * *##% + * JAXX Runtime + * Copyright (C) 2008 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* */ +package jaxx.runtime.swing.editor; + +import org.nuiton.util.ReflectUtil; + +import javax.swing.JComboBox; +import java.util.EnumSet; +import java.util.Iterator; + +/** + * Une éditeur d'enum. + * + * @param <E> le type d'enumeration a editer. + * @author tchemit <chemit@codelutin.com> + * @since 1.6.0 + */ +public class EnumEditor<E extends Enum<E>> extends JComboBox { + + private static final long serialVersionUID = 2L; + + /** Type of enumeration */ + protected Class<E> type; + + /** + * Creates a {@link EnumEditor} for the given enumeration {@code type}, with + * all values of enumeration. + * + * @param type type of enumeration + * @param <E> generci type of enumeration + * @return the instanciated editor + */ + public static <E extends Enum<E>> EnumEditor<E> newEditor(Class<E> type) { + return new EnumEditor<E>(type); + } + + + /** + * Creates a {@link EnumEditor} for the given enumeration {@code type}, with + * all values of enumeration which {@code ordinal} is strictly lower than + * the given {@code maxOrdinal}. + * + * @param type type of enumeration + * @param maxOrdinal the upper (strict) bound of ordinal values allowed + * @param <E> generic type of enumeration + * @return the instanciated editor + */ + public static <E extends Enum<E>> EnumEditor<E> newEditor(Class<E> type, + int maxOrdinal) { + return new EnumEditor<E>(type, maxOrdinal); + } + + /** + * Creates a {@link EnumEditor} for the given enumeration {@code type}, with + * all given {@code universe} values of enumeration. + * + * @param universe enumerations to put in editor + * @param <E> generci type of enumeration + * @return the instanciated editor + */ + public static <E extends Enum<E>> EnumEditor<E> newEditor(E... universe) { + return new EnumEditor<E>(universe); + } + + public EnumEditor(Class<E> type) { + super(buildModel(type)); + } + + public EnumEditor(Class<E> type, int maxOrdinal) { + super(buildModel(type, maxOrdinal)); + } + + public EnumEditor(E... universe) { + super(universe); + } + + @Override + public E getSelectedItem() { + return (E) super.getSelectedItem(); + } + + protected static <E extends Enum<E>> Object[] buildModel(Class<E> type) { + Class<E> enumClass = ReflectUtil.getEnumClass(type); + EnumSet<E> result = EnumSet.allOf(enumClass); + return result.toArray(new Object[result.size()]); + } + + + protected static <E extends Enum<E>> Object[] buildModel(Class<E> type, + int maxOrdinal) { + Class<E> enumClass = ReflectUtil.getEnumClass(type); + EnumSet<E> result = EnumSet.allOf(enumClass); + Iterator<E> itr = result.iterator(); + while (itr.hasNext()) { + E e = itr.next(); + if (e.ordinal() > maxOrdinal) { + itr.remove(); + } + } + return result.toArray(new Object[result.size()]); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/LocaleEditor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/LocaleEditor.java new file mode 100644 index 0000000..1089b0d --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/LocaleEditor.java @@ -0,0 +1,74 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor; + +import org.nuiton.i18n.I18n; +import org.nuiton.i18n.I18nStore; + +import javax.swing.JComboBox; +import java.util.Locale; + +/** + * A {@link Locale} editor. + * <p/> + * use the static method to have an instance of editor + * {@link #newEditor(Locale...)} + * <p/> + * If no locale is given to this method, it will go and seek via + * {@link I18nStore#getLocales()} all loaded locales in i18n system + * + * @author tchemit <chemit@codelutin.com> + * @since 1.6.0 + */ +public class LocaleEditor extends JComboBox { + + /** serialVersionUID */ + private static final long serialVersionUID = -6777873426011538807L; + + protected Locale[] type; + + public static LocaleEditor newEditor(Locale... type) { + return new LocaleEditor(type); + } + + public LocaleEditor(Locale... type) { + super(buildModel(type)); + } + + @Override + public Locale getSelectedItem() { + return (Locale) super.getSelectedItem(); + } + + protected static Locale[] buildModel(Locale... type) { + if (type.length > 0) { + return type; + } + // get availables locales registred in I18n system + type = I18n.getStore().getLocales(); + return type; + } + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/MyDefaultCellEditor.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/MyDefaultCellEditor.java new file mode 100644 index 0000000..8a35d45 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/editor/MyDefaultCellEditor.java @@ -0,0 +1,127 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor; + +import javax.swing.DefaultCellEditor; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.TableCellEditor; +import java.awt.Component; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class MyDefaultCellEditor extends DefaultCellEditor { + + private static final long serialVersionUID = 1L; + + public static TableCellEditor newTextEditor() { + return new MyDefaultCellEditor(new JTextField()); + } + + public static TableCellEditor newBooleanEditor() { + return new MyDefaultCellEditor(new JCheckBox()); + } + + public static TableCellEditor newListEditor() { + return newListEditor(new JComboBox()); + } + + public static TableCellEditor newListEditor(JComboBox editor) { + return new MyDefaultCellEditor(editor); + } + + public static TableCellEditor newEnumEditor(EnumEditor<?> editor) { + return new MyDefaultCellEditor(editor) { + + private static final long serialVersionUID = 1L; + + @Override + public Object getCellEditorValue() { + Object value = super.getCellEditorValue(); + if (value != null) { + value = ((Enum) value).ordinal(); + } else { + value = -1; + } + return value; + } + }; + } + + public static TableCellEditor newBooleanEditor(Icon icon) { + return new MyDefaultCellEditor(new JCheckBox(icon)); + } + + public static TableCellEditor newBooleanEditor(Icon icon, boolean requireSelect) { + TableCellEditor cellEditor = newBooleanEditor(icon); + ((MyDefaultCellEditor) cellEditor).setRequireSelect(requireSelect); + return cellEditor; + } + + public static TableCellEditor newBooleanEditor(boolean requireSelect) { + TableCellEditor cellEditor = newBooleanEditor(); + ((MyDefaultCellEditor) cellEditor).setRequireSelect(requireSelect); + return cellEditor; + } + + protected boolean requireSelect = true; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (!isSelected && requireSelect) { + // force to have select the cell before editing, a way to not modify edition for nothing... + return null; + } + return super.getTableCellEditorComponent(table, value, isSelected, row, column); + } + + public boolean isRequireSelect() { + return requireSelect; + } + + public void setRequireSelect(boolean requireSelect) { + this.requireSelect = requireSelect; + } + + protected MyDefaultCellEditor(JTextField textField) { + super(textField); + setClickCountToStart(1); + } + + protected MyDefaultCellEditor(JCheckBox checkBox) { + super(checkBox); + setClickCountToStart(1); + } + + protected MyDefaultCellEditor(JComboBox comboBox) { + super(comboBox); + setClickCountToStart(1); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpBroker.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpBroker.java new file mode 100644 index 0000000..85ea440 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpBroker.java @@ -0,0 +1,590 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.help; + +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.help.CSH; +import javax.help.HelpBroker; +import javax.help.HelpSet; +import javax.swing.AbstractButton; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import java.applet.Applet; +import java.awt.AWTEvent; +import java.awt.ActiveEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.MenuComponent; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Map; +import java.util.Vector; + +/** + * La classe pour encapsuler l'aide de l'application. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.4 + */ +public class JAXXHelpBroker { + + public static final String JAXX_CONTEXT_ENTRY = "jaxxcontext"; + + /** Logger */ + static private Log log = LogFactory.getLog(JAXXHelpBroker.class); + + /** name of helpset */ + protected final String helpsetName; + + /** default id to use if none given */ + protected final String defaultID; + + /** help key */ + protected final String helpKey; + + /** helpset to use */ + protected HelpSet helpset; + + /** help broker */ + protected HelpBroker helpBroker; + + /** current locale used */ + protected Locale locale; + + /** cache of cursors modified when in context-sensitive mode */ + protected Hashtable<Component, Cursor> cursors; + + /** cursor to use in context-sensitive mode */ + protected Cursor onItemCursor; + + /** cache of component which cursor have been modified */ + protected final Map<Component, String> cache; + + /** help ui handler */ + protected JAXXHelpUIHandler handler; + + public JAXXHelpBroker(String helpsetName, String helpKey, String defaultID, JAXXHelpUIHandler handler) { + this(null, helpsetName, helpKey, defaultID, handler); + } + + public JAXXHelpBroker(Locale locale, String helpsetName, String helpKey, String defaultID, JAXXHelpUIHandler handler) { + if (helpsetName == null) { + throw new NullPointerException("parameter helpsetName can not be null!"); + } + if (handler == null) { + throw new NullPointerException("handler can not be null"); + } + this.locale = locale; + this.helpsetName = helpsetName; + this.helpKey = helpKey; + this.defaultID = defaultID; + this.handler = handler; + this.cache = new HashMap<Component, String>(); + } + + public void prepareUI(JAXXObject c) { + if (c == null) { + throw new NullPointerException("parameter c can not be null!"); + } + + // l'ui doit avoir un boutton showHelp + AbstractButton help = getShowHelpButton(c); + + if (help == null) { + // no showHelp button + return; + } + + // attach context to button + if (log.isDebugEnabled()) { + log.debug("attach context to showhelp button " + c); + } + help.putClientProperty(JAXX_CONTEXT_ENTRY, c); + + // add tracking action + ActionListener listener = getShowHelpAction(); + if (log.isDebugEnabled()) { + log.debug("adding tracking action " + listener); + } + help.addActionListener(listener); + + if (log.isDebugEnabled()) { + log.debug("done for " + c); + } + + + getHelpBroker().enableHelpKey(((Component) c), getDefaultID(), getHelpset()); + } + + public void showHelp(JAXXContext context, String helpId) { + getHandler().showHelp(context, this, helpId); + } + + public JAXXHelpUIHandler getHandler() { + return handler; + } + + public HelpBroker getHelpBroker() { + if (helpBroker == null) { + helpBroker = getHelpset().createHelpBroker(); + } + return helpBroker; + } + + public String getHelpKey() { + return helpKey; + } + + public HelpSet getHelpset() { + if (helpset == null) { + try { + ClassLoader cl = getClass().getClassLoader(); + URL url = HelpSet.findHelpSet(cl, helpsetName, locale); + helpset = new HelpSet(cl, url); + } catch (Exception ee) { + throw new IllegalStateException("could not find help set " + helpsetName + " for reason " + ee.getMessage(), ee); + } + } + return helpset; + } + + public String getHelpsetName() { + return helpsetName; + } + + public String getDefaultID() { + return defaultID; + } + + public void setLocale(Locale locale) { + this.locale = locale; + // need to reload helpset and helpbroker + helpset = null; + helpBroker = null; + getHelpset(); + getHelpBroker(); + } + + public void showHelpSet() { + if (log.isDebugEnabled()) { + log.debug(this); + } + new CSH.DisplayHelpFromSource(getHelpBroker()); + } + + public void installUI(Component comp, String helpId) { + CSH.setHelpIDString(comp, helpId); + if (log.isDebugEnabled()) { + log.debug(helpId + " : " + comp.getName()); + } + cache.put(comp, helpId); + } + + public class ShowHelpForTrackedComponentAction implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + AbstractButton source = (AbstractButton) e.getSource(); + + JAXXContext context = (JAXXContext) source.getClientProperty(JAXX_CONTEXT_ENTRY); + + // prepare cursor + onItemCursor = (Cursor) UIManager.get("HelpOnItemCursor"); + Vector<?> topComponents = null; + cursors = null; + + if (onItemCursor != null) { + cursors = new Hashtable<Component, Cursor>(); + topComponents = getTopContainers(source); + Enumeration<?> enums = topComponents.elements(); + while (enums.hasMoreElements()) { + setAndStoreCursors((Container) enums.nextElement(), onItemCursor); + } + } + + // get the tracked component + Component comp = null; + try { + MouseEvent event = getMouseEvent(); + if (event == null) { + // tracking canceled + return; + } + comp = (Component) event.getSource(); + if (log.isDebugEnabled()) { + log.debug("component traking " + comp.getName() + " : " + comp.getClass().getName()); + } + comp = SwingUtil.getDeepestObjectAt(comp, event.getX(), event.getY()); + if (log.isDebugEnabled()) { + log.debug("deepest component " + comp.getName() + " : " + comp.getClass().getName()); + } + } finally { + // restore the old cursors + if (topComponents != null) { + Enumeration<?> containers = topComponents.elements(); + while (containers.hasMoreElements()) { + resetAndRestoreCursors((Container) containers.nextElement()); + } + } + cursors = null; + } + + String helpID = findHelpId(comp); + showHelp(context, helpID); + } + + public String findHelpId(Component comp) { + String helpID = CSH.getHelpIDString(comp); + if (defaultID.equals(helpID)) { + String id = cache.get(comp); + // on verifie qu'on est bien sur sur le bon id + if (helpID.equals(id)) { + // ok + return helpID; + } + if (log.isDebugEnabled()) { + log.debug("will try to find better id for comp : " + comp.getName()); + } + // on est pas sur le bon id + // on recherche parmis les parents + helpID = findExtactHelpId(comp); + } + if (log.isInfoEnabled()) { + log.info("helpID " + helpID + " for comp " + comp.getName() + " : " + comp.getClass().getName()); + } + return helpID; + } + + protected String findExtactHelpId(Component comp) { + Container parent = comp.getParent(); + while (parent != null) { + String id = cache.get(parent); + if (id == null) { + // ce container n'a pas d'id + // on va directement sur le parent + parent = parent.getParent(); + continue; + } + // le parent possède un id + // on utilise cet id + return id; + } + // on a pas trouve d'id + // on retourne l'id par defaut + return defaultID; + } + } + + protected AbstractButton getShowHelpButton(JAXXObject c) { + return (AbstractButton) c.getObjectById("showHelp"); + } + + protected ActionListener getShowHelpAction() { + return new ShowHelpForTrackedComponentAction(); + } + + //------------------------------------------------------------------------- + //--- Copy CSH code but with accessible modifiers and little improvments + //------------------------------------------------------------------------- + /* + * Get all top level containers to change it's cursors + */ + + protected Vector<?> getTopContainers(Object source) { + // This method is used to obtain all top level components of application + // for which the changing of cursor to question mark is wanted. + // Method Frame.getFrames() is used to get list of Frames and + // Frame.getOwnedWindows() method on elements of the list + // returns all Windows, Dialogs etc. It works correctly in application. + // Problem is in applets. There is no way how to get reference to applets + // from elsewhere than applet itself. So, if request for CSH (this means + // pressing help button or select help menu item) does't come from component + // in a Applet, cursor for applets is not changed to question mark. Only for + // Frames, Windows and Dialogs is cursor changed properly. + + Vector<Component> containers = new Vector<Component>(); + Component topComponent = null; + topComponent = getRoot(source); + if (topComponent instanceof Applet) { + try { + Enumeration<Applet> applets = ((Applet) topComponent).getAppletContext().getApplets(); + while (applets.hasMoreElements()) { + containers.add(applets.nextElement()); + } + } catch (NullPointerException npe) { + containers.add(topComponent); + } + } + Frame frames[] = Frame.getFrames(); + for (int i = 0; i < frames.length; i++) { + Window[] windows = frames[i].getOwnedWindows(); + for (int j = 0; j < windows.length; j++) { + containers.add(windows[j]); + } + if (!containers.contains(frames[i])) { + containers.add(frames[i]); + } + } + return containers; + } + + protected Component getRoot(Object comp) { + Object parent = comp; + while (parent != null) { + comp = parent; + if (comp instanceof MenuComponent) { + parent = ((MenuComponent) comp).getParent(); + } else if (comp instanceof Component) { + if (comp instanceof Window) { + break; + } + if (comp instanceof Applet) { + break; + } + parent = ((Component) comp).getParent(); + } else { + break; + } + } + if (comp instanceof Component) { + return ((Component) comp); + } + return null; + } + + /* + * Set the cursor for a component and its children. + * Store the old cursors for future resetting + */ + + protected void setAndStoreCursors(Component comp, Cursor cursor) { + if (comp == null) { + return; + } + Cursor compCursor = comp.getCursor(); + if (compCursor != cursor) { + cursors.put(comp, compCursor); + log.debug("set cursor on " + comp); + comp.setCursor(cursor); + } + if (comp instanceof Container) { + Component component[] = ((Container) comp).getComponents(); + for (int i = 0; i < component.length; i++) { + setAndStoreCursors(component[i], cursor); + } + } + } + + /* + * Actually restore the cursor for a component and its children + */ + + protected void resetAndRestoreCursors(Component comp) { + if (comp == null) { + return; + } + Cursor oldCursor = cursors.get(comp); + if (oldCursor != null) { + log.debug("restored cursor " + oldCursor + " on " + comp); + comp.setCursor(oldCursor); + } + if (comp instanceof Container) { + Component component[] = ((Container) comp).getComponents(); + for (int i = 0; i < component.length; i++) { + resetAndRestoreCursors(component[i]); + } + } + } + + /** + * Context Sensitive Event Tracking + * <p/> + * Creates a new EventDispatchThread from which to dispatch events. This + * method returns when stopModal is invoked. + * + * @return MouseEvent The mouse event occurred. Null if + * cancelled on an undetermined object. + */ + public static MouseEvent getMouseEvent() { + // Should the cursor change to a quesiton mark here or + // require the user to change the cursor externally to this method? + // The problem is that each component can have it's own cursor. + // For that reason it might be better to have the user change the + // cusor rather than us. + + // To track context-sensitive events get the event queue and process + // the events the same way EventDispatchThread does. Filter out + // ContextSensitiveEvents SelectObject & Cancel (MouseDown & ???). + // Note: This code only handles mouse events. Accessiblity might + // require additional functionality or event trapping + + // If the eventQueue can't be retrieved, the thread gets interrupted, + // or the thread isn't a instanceof EventDispatchThread then return + // a null as we won't be able to trap events. + try { + if (EventQueue.isDispatchThread()) { + EventQueue eq = null; + + // Find the eventQueue. If we can't get to it then just return + // null since we won't be able to trap any events. + + try { + eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + } catch (Exception ee) { + log.debug(ee); + } + + // Safe guard + if (eq == null) { + return null; + } + + int eventNumber = -1; + + // Process the events until an object has been selected or + // the context-sensitive search has been canceled. + while (true) { + // This is essentially the body of EventDispatchThread + // modified to trap context-senstive events and act + // appropriately + eventNumber++; + AWTEvent event = eq.getNextEvent(); + Object src = event.getSource(); + // can't call eq.dispatchEvent + // so I pasted it's body here + + if (log.isDebugEnabled()) { + log.debug(event); + } + + // Not sure if I should suppress ActiveEvents or not + // Modal dialogs do. For now we will not suppress the + // ActiveEvent events + + if (event instanceof ActiveEvent) { + ((ActiveEvent) event).dispatch(); + continue; + } + + if (src instanceof Component) { + // Trap the context-sensitive events here + if (event instanceof KeyEvent) { + KeyEvent e = (KeyEvent) event; + // if this is the cancel key then exit + // otherwise pass all other keys up + if (e.getKeyCode() == KeyEvent.VK_CANCEL || + e.getKeyCode() == KeyEvent.VK_ESCAPE) { + e.consume(); + return null; + } else { + e.consume(); + // dispatchEvent(event); + } + } else if (event instanceof MouseEvent) { + MouseEvent e = (MouseEvent) event; + int eID = e.getID(); + + if ((eID == MouseEvent.MOUSE_CLICKED || + eID == MouseEvent.MOUSE_PRESSED || + eID == MouseEvent.MOUSE_RELEASED) && + SwingUtilities.isRightMouseButton(e)) { + // cancel tracking + e.consume(); + if (log.isDebugEnabled()) { + log.debug("tracking canceled!!!"); + } + return null; + } + + if ((eID == MouseEvent.MOUSE_CLICKED || + eID == MouseEvent.MOUSE_PRESSED || + eID == MouseEvent.MOUSE_RELEASED) && + SwingUtilities.isLeftMouseButton(e)) { + if (eID == MouseEvent.MOUSE_CLICKED) { + if (eventNumber == 0) { + dispatchEvent(event); + continue; + } + } + e.consume(); + return e; + } else { + e.consume(); + } + } else { + dispatchEvent(event); + } + } else if (src instanceof MenuComponent) { + if (event instanceof InputEvent) { + ((InputEvent) event).consume(); + } + } else { + log.error("unable to dispatch event: " + event); + } + } + } + } catch (InterruptedException e) { + if (log.isDebugEnabled()) { + log.debug(e); + } + } + if (log.isDebugEnabled()) { + log.debug("Fall Through code"); + } + return null; + } + + private static void dispatchEvent(AWTEvent event) { + Object src = event.getSource(); + if (event instanceof ActiveEvent) { + // This could become the sole method of dispatching in time. + ((ActiveEvent) event).dispatch(); + } else if (src instanceof Component) { + ((Component) src).dispatchEvent(event); + } else if (src instanceof MenuComponent) { + ((MenuComponent) src).dispatchEvent(event); + } else { + log.error("unable to dispatch event: " + event); + } + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUI.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUI.java new file mode 100644 index 0000000..8ee7a6f --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUI.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.help; + +import java.awt.Component; + +/** + * Contract to be added on JAXXObject which wants to use javax help. + * + * @param <B> type of broker. + * @author tchemit <chemit@codelutin.com> + * @see JAXXHelpBroker + * @since 1.3 + */ +public interface JAXXHelpUI<B extends JAXXHelpBroker> { + + B getBroker(); + + void registerHelpId(B broker, Component component, String helpId); + + void showHelp(String helpId); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUIHandler.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUIHandler.java new file mode 100644 index 0000000..050918d --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/help/JAXXHelpUIHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.help; + +import jaxx.runtime.JAXXContext; + +/** @author tchemit <chemit@codelutin.com> */ +public interface JAXXHelpUIHandler { + + void showHelp(JAXXContext context, JAXXHelpBroker broker, String helpID); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java new file mode 100644 index 0000000..58cda7c --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/AbstractGenericListSelectionModel.java @@ -0,0 +1,275 @@ +/* + * #%L + * JAXX :: Runtime + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.model; + +import com.google.common.collect.Lists; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Collection; +import java.util.List; +import javax.swing.DefaultListSelectionModel; +import javax.swing.event.EventListenerList; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public abstract class AbstractGenericListSelectionModel<B> extends DefaultListSelectionModel { + + public static final String PROPERTY_SELECTED_VALUE = "selectedValues"; + + protected EventListenerList listenerList = new EventListenerList(); + protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + protected List<B> selectedValues; + + public AbstractGenericListSelectionModel() { + this.selectedValues = Lists.newArrayList(); + } + + public B getSelectedValue() { + return selectedValues.get(0); + } + + public List<B> getSelectedValues() { + return Lists.newArrayList(selectedValues); + } + + public void setSelectedValues(List<B> selectedValues) { + this.selectedValues = selectedValues; + } + + protected void unSelectItems(Collection<B> values) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + for (B value : values) { + int index = selectedValues.indexOf(value); + removeSelectionIntervalWithoutFire(index, index); + } + fireSelectionRemoved(values); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + protected void unSelectItem(B value) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + int index = selectedValues.indexOf(value); + removeSelectionIntervalWithoutFire(index, index); + + fireSelectionRemoved(Lists.newArrayList(value)); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + public void addSelectedItem(B toSelect) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + selectedValues.add(toSelect); + int index = selectedValues.indexOf(toSelect); + super.addSelectionInterval(index, index); + + fireSelectionAdded(Lists.newArrayList(toSelect)); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + public boolean hasSelectedIndex() { + return !selectedValues.isEmpty(); + } + + @Override + public void addSelectionInterval(int index0, int index1) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + + addSelectionIntervalWithFire(index0, index1); + super.addSelectionInterval(index0, index1); + + Collection<B> newValue = Lists.newArrayList(selectedValues); + newValue.removeAll(oldValue); + fireSelectionAdded(newValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + @Override + public void setSelectionInterval(int index0, int index1) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + selectedValues.clear(); + addSelectionIntervalWithFire(index0, index1); + super.setSelectionInterval(index0, index1); + + Collection<B> newValue = Lists.newArrayList(selectedValues); + newValue.removeAll(oldValue); + fireSelectionAdded(newValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + @Override + public void removeSelectionInterval(int index0, int index1) { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + removeSelectionIntervalWithoutFire(index0, index1); + + Collection<B> newValue = Lists.newArrayList(selectedValues); + newValue.removeAll(oldValue); + fireSelectionRemoved(newValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + protected void removeSelectionIntervalWithoutFire(int index0, int index1) { + if (index0 > index1) { + int tmp = index1; + index1 = index0; + index0 = tmp; + } + for (int i=index0;i<=index1;i++) { + if (selectedValues.size() > i && i != -1) { + selectedValues.remove(i); + } + } + super.removeSelectionInterval(index0, index1); + } + + protected void addSelectionIntervalWithFire(int index0, int index1) { + if (index0 > index1) { + int tmp = index1; + index1 = index0; + index0 = tmp; + } + for (int i=index0;i<=index1;i++) { + + if (getSize() > i && i != -1) { + B value = getValueAt(i); + selectedValues.add(value); + } + } + } + + public abstract int getSize(); + + public abstract B getValueAt(int i); + + @Override + public void clearSelection() { + Collection<B> oldValue = Lists.newArrayList(selectedValues); + selectedValues.clear(); + super.clearSelection(); + + fireSelectionRemoved(oldValue); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, selectedValues); + } + + @Override + public int getSelectionMode() { + return MULTIPLE_INTERVAL_SELECTION; + } + + protected void fireValuesAdded(Collection<B> values) { + if (values.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, values); + } + ((GenericListListener)listeners[i+1]).valuesAdded(e); + } + } + } + + protected void fireValuesRemoved(Collection<B> values) { + if (values.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, values); + } + ((GenericListListener)listeners[i+1]).valuesRemoved(e); + } + } + } + + protected void fireSelectionAdded(Collection<B> selectedValues) { + if (selectedValues.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, selectedValues); + } + ((GenericListListener)listeners[i+1]).selectionAdded(e); + } + } + } + + protected void fireSelectionRemoved(Collection<B> selectedValues) { + if (selectedValues.isEmpty()) { + return; + } + Object[] listeners = listenerList.getListenerList(); + GenericListEvent<B> e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == GenericListListener.class) { + if (e == null) { + e = new GenericListEvent<B>(this, selectedValues); + } + ((GenericListListener)listeners[i+1]).selectionAdded(e); + } + } + } + + public void addGenericListListener(GenericListListener l) { + listenerList.add(GenericListListener.class, l); + } + + public void removeGenericListListener(GenericListListener l) { + listenerList.remove(GenericListListener.class, l); + } + + 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); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListEvent.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListEvent.java new file mode 100644 index 0000000..3d952b4 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListEvent.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Runtime + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.model; + +import java.util.Collection; +import java.util.EventObject; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class GenericListEvent<B> extends EventObject { + + protected Collection<B> values; + + public GenericListEvent(Object source, Collection<B> values) { + super(source); + this.values = values; + } + + public Collection<B> getValues() { + return values; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListListener.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListListener.java new file mode 100644 index 0000000..358e5ad --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListListener.java @@ -0,0 +1,40 @@ +/* + * #%L + * JAXX :: Runtime + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.model; + +import java.util.EventListener; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public interface GenericListListener extends EventListener { + + void valuesAdded(GenericListEvent event); + + void valuesRemoved(GenericListEvent event); + + void selectionAdded(GenericListEvent event); + + void selectionRemoved(GenericListEvent event); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListModel.java new file mode 100644 index 0000000..322a6a5 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListModel.java @@ -0,0 +1,164 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.model; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.List; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class GenericListModel<B> extends GenericListSelectionModel<B> implements ComboBoxModel { + + public GenericListModel() { + super(new DefaultListModel()); + } + + public GenericListModel(Collection<B> values) { + this(); + setElements(values); + } + + public void setElements(Collection<B> values) { + Collection<B> oldValues = getElements(); + Collection<B> oldSelectedValues = getSelectedValues(); + clearSelection(); + fireSelectionRemoved(oldSelectedValues); + + clearElements(); + fireValuesRemoved(oldValues); + + for (B value : values) { + getListModel().addElement(value); + } + + fireSelectionAdded(values); + } + + public void clearElements() { + Collection<B> elements = getElements(); + getListModel().clear(); + + fireValuesRemoved(elements); + } + + public Collection<B> getElements() { + int size = getListModel().getSize(); + Collection<B> result = Lists.newArrayList(); + for (int i=0;i<size;i++) { + result.add((B) getListModel().get(i)); + } + return result; + } + + public void addElement(int index, B valueToAdd) { + getListModel().add(index, valueToAdd); + + fireValuesAdded(Lists.newArrayList(valueToAdd)); + } + + public void addElement(B valueToAdd) { + getListModel().addElement(valueToAdd); + + fireValuesAdded(Lists.newArrayList(valueToAdd)); + } + + public void addElements(Collection<B> valuesToAdd) { + for (B value : valuesToAdd) { + getListModel().addElement(value); + } + + fireValuesAdded(valuesToAdd); + } + + public void removeElements(Collection<B> values) { + for (B value : values) { + getListModel().removeElement(value); + } + unSelectItems(values); + + fireValuesRemoved(values); + } + + @Override + public void setSelectedItem(Object anItem) { + List<B> oldValue = getSelectedValues(); + fireSelectionRemoved(oldValue); + + setSelectedValues(Lists.newArrayList((B) anItem)); + + List<B> newValues = getSelectedValues(); + fireSelectionAdded(newValues); + fireContentsChanged(this, -1, -1); + firePropertyChange(PROPERTY_SELECTED_VALUE, oldValue, newValues); + } + + @Override + public B getSelectedItem() { + List<B> selectedValues = getSelectedValues(); + if (selectedValues.isEmpty()) { + return null; + } + return selectedValues.get(0); + } + + @Override + public int getSize() { + return getListModel().size(); + } + + @Override + public Object getElementAt(int index) { + return getListModel().get(index); + } + + @Override + public void addListDataListener(ListDataListener l) { + getListModel().addListDataListener(l); + } + + @Override + public void removeListDataListener(ListDataListener l) { + getListModel().removeListDataListener(l); + } + + protected void fireContentsChanged(Object source, int index0, int index1) { + Object[] listeners = getListModel().getListDataListeners(); + ListDataEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ListDataListener.class) { + if (e == null) { + e = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, index0, index1); + } + ((ListDataListener)listeners[i+1]).contentsChanged(e); + } + } + } +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListSelectionModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListSelectionModel.java new file mode 100644 index 0000000..5548523 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/model/GenericListSelectionModel.java @@ -0,0 +1,53 @@ +/* + * #%L + * JAXX :: Runtime + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.model; + +import javax.swing.DefaultListModel; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class GenericListSelectionModel<B> extends AbstractGenericListSelectionModel<B> { + + protected DefaultListModel listModel; + + public GenericListSelectionModel(DefaultListModel listModel) { + super(); + this.listModel = listModel; + } + + public DefaultListModel getListModel() { + return listModel; + } + + @Override + public int getSize() { + return listModel.size(); + } + + @Override + public B getValueAt(int i) { + return (B)listModel.getElementAt(i); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavBridge.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavBridge.java new file mode 100644 index 0000000..c2d6804 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavBridge.java @@ -0,0 +1,125 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.EventListener; + +/** + * Contract of the bridge used by {@link NavHelper} to hold model and ui. + * + * @param <M> Type of model to bridge + * @param <N> Type of nodes of the model + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public interface NavBridge<M, N extends NavNode<M, N>> { + + //-------------------------------------------------------------------------- + //-- Model Queries + //-------------------------------------------------------------------------- + + M getModel(); + + N getRoot(); + + boolean isLeaf(Object node); + + int getChildCount(Object parent); + + N getChild(Object parent, int index); + + int getIndexOfChild(Object parent, Object child); + + TreeNode[] getPathToRoot(TreeNode aNode); + + //-------------------------------------------------------------------------- + //-- Model modification + //-------------------------------------------------------------------------- + + void setModel(M delegate); + + void setRoot(N node); + + void insertNodeInto(N newChild, N parent, int index); + + void removeNodeFromParent(N node); + + void reload(N node); + + boolean canLoadChild(N node); + + //-------------------------------------------------------------------------- + //-- Listeners notifications + //-------------------------------------------------------------------------- + + void valueForPathChanged(TreePath path, Object newValue); + + void nodeStructureChanged(TreeNode node); + + void nodeChanged(TreeNode node); + + void nodesChanged(TreeNode node, int[] childIndices); + + void nodesWereInserted(N parent, int[] indices); + + void nodeWereInserted(N parentNode, int childIndice, N node); + + void nodesWereRemoved(TreeNode node, int[] childIndices, Object[] removedChildren); + + /** + * Notifies that the {@code node} was inserted. + * <p/> + * <b>Note:</b> The method recurses on childs (always notify parent before child) + * + * @param node node inserted + */ + void notifyNodeInserted(N node); + + /** + * Notifies that all childs nodes of {@code node} were + * inserted. + * <p/> + * <b>Note:</b> The method recurses on childs (always notify parent before child) + * + * @param node node where all childs where inserted + */ + void notifyChildNodesInserted(N node); + + //-------------------------------------------------------------------------- + //-- TreeModelListener provider + //-------------------------------------------------------------------------- + + void addTreeModelListener(TreeModelListener l); + + void removeTreeModelListener(TreeModelListener l); + + TreeModelListener[] getTreeModelListeners(); + + <T extends EventListener> T[] getListeners(Class<T> listenerType); + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavDataProvider.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavDataProvider.java new file mode 100644 index 0000000..e71ebbf --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavDataProvider.java @@ -0,0 +1,46 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav; + +import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; + +/** + * Contract of provider of data. + * <p/> + * This object is used by {@link NavNodeChildLoador} to populate childs of node + * and by {@link AbstractNavTreeCellRenderer} to render nodes. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public interface NavDataProvider { + + /** + * @return {@code true} is provider is enabled and can provide datas, + * {@code false} otherwise. + */ + boolean isEnabled(); + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavHelper.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavHelper.java new file mode 100644 index 0000000..cb51c39 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavHelper.java @@ -0,0 +1,965 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav; + +import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Tree helper to deal with the build of trees and other usefull operations. + * <p/> + * A helper acts as an handler for a {@code tree}. It owns the {@link #getModel()} of + * the {@code #tree}. + * <p/> + * <b>Note:</b> A helper can NOT be used to manage multi-trees. + * <h2>Internal states</h2 + * <h3>Internal model</h3> + * To create the model, use method {@link #createModel(NavNode, Object...)} given a + * root node. + * <p/> + * To obtain the model, use method {@link #getModel()}. + * <p/> + * <b>Note:</b> The helper internal model can be different from the tree model, + * but must be the <b>lowest</b> model, other models must listen nicely this + * model to obtain model modification and selection notifications. + * <h3>Internal tree</h3> + * As said before, a helper matches exactly one tree. + * <p/> + * To register the tree, use method {@link #setUI(Object, boolean, TreeSelectionListener)}. + * <p/> + * To obtain the tree, use method {@link #getUI()}. + * <h3>Internal data provider</h3> + * To populate childs nodes and render nodes, we use a {@link NavDataProvider}. + * <p/> + * To register the data provider, use method {@link #setDataProvider(NavDataProvider)}. + * <p/> + * To obtain the data provider, use method {@link #getDataProvider()}. + * <h2>Internal listeners</h2> + * Several listeners are used to manage the auto-loading of nodes in model : + * <h3>{@link #expandListener}</h3> + * This listener will load node's childs before node expands if the node is not loaded. + * <p/> + * See the {@link NavNode#isLoaded()} method. + * <h3>{@link #treeModelListener}</h3> + * To listen modification of the model, it will mainly repopulate nodes when + * required. + * <p/> + * See the method {@link #populateNode(NavNode, Object[], boolean)}. + * <h3>{@link #selectionListener}</h3> + * To listen modification of the selection, it will mainly expand paths if required. + * <p/> + * This is a requirement, since childs of a node should NOT be loaded, so when + * selects a node, always check the path from root to selected node are all fully + * loaded. + * <h2>Model methods</h2> + * The helper offers some methods to modify and query the internal tree model. + * <h3>Model modification</h3> + * <ul> + * <li>{@link #createModel(NavNode, Object...)}</li> + * <li>{@link #insertNode(NavNode, NavNode)}</li> + * <li>{@link #removeNode(NavNode)}</li> + * <li>{@link #moveNode(NavNode, NavNode, int)}</li> + * <li>{@link #refreshNode(NavNode, boolean)}</li> + * <li>{@link #loadAllNodes(NavNode, NavDataProvider)}</li> + * <p/> + * </ul> + * <h3>Model selection modification</h3> + * <ul> + * <li>{@link #selectNode(NavNode)}</li> + * <li>{@link #selectNode(String...)}</li> + * <li>{@link #selectParentNode()}</li> + * </ul> + * <h3>Model query</h3> + * <ul> + * <li>{@link #findNode(NavNode, String...)}</li> + * </ul> + * <h3>Child loadors factory</h3> + * The class offers a factory of {@link NavNodeChildLoador}, use the method + * {@link #getChildLoador(Class)} to obtain the correct child loador given his type. + * + * @param <U> Type of ui to bridge + * @author tchemit <chemit@codelutin.com> + * @see NavNode + * @see NavNodeChildLoador + * @see AbstractNavTreeCellRenderer + * @since 2.1 + */ +public abstract class NavHelper<M, U, B extends NavBridge<M, N>, N extends NavNode<M, N>> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavHelper.class); + + //-------------------------------------------------------------------------- + //-- Methods to implement in your helper (related only to ui) + //-------------------------------------------------------------------------- + + public abstract void scrollPathToVisible(TreePath path); + + public abstract void setSelectionPath(TreePath path); + + public abstract void addSelectionPath(TreePath path); + + public abstract void addSelectionPaths(TreePath[] paths); + + public abstract void removeSelectionPath(TreePath path); + + public abstract void removeSelectionPaths(TreePath[] paths); + + public abstract TreeSelectionModel getSelectionModel(); + + public abstract boolean isExpanded(TreePath pathToExpand); + + public abstract void expandPath(TreePath pathToExpand); + + /** + * Register a new root node. + * <p/> + * If internal {@link #getModel()} does not exists, creates a new one from + * his given root {@code node}, otherwise just set the new root on the + * existing model. + * <p/> + * <b>Note:</b> As a side-effect, the model will be keep in field {@link #getModel()} + * and the {@link #treeModelListener} will be registred on this model. + * + * @param node the root node of the new model + * @param extraArgs extra args to create initial model + * @return the new model + */ + protected abstract M createModel(N node, Object... extraArgs); + + /** + * Obtains the {@link AbstractNavTreeCellRenderer} renderer of the + * registred tree. + * + * @return the renderer of the registred tree or null if no tree was + * registred nor the renderer is a {@link AbstractNavTreeCellRenderer}. + */ + public abstract AbstractNavTreeCellRenderer<M, N> getTreeCellRenderer(); + + /** + * Obtains the selected node of the registred tree. + * + * @return the selected tree or {@code null} if no registred tree nor + * selection empty. + */ + public abstract N getSelectedNode(); + + /** + * Obtains the selected nodes of the registred tree. + * + * @return the selected tree or {@code null} if no registred tree nor + * selection empty. + */ + public abstract List<N> getSelectedNodes(); + + /** + * Registers the given {@code tree} for this helper. + * <p/> + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and (if required) the + * {@link #selectionListener}. + * <b>Note :</b> as a second side-effect, it will register the given {@code willExpandListener} (if not null) + * for the ui and do it <b>BEFORE</b> the {@link #expandListener}. The main + * idea here is to be able to block any expand (or collapse). + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + * @param addOneClickSelectionListener a flag to expend when selection + * @param listener the optional selection listener to add + * @param willExpandListener the optional will expand listener to add <b>BEFORE</b> the default expand tree listener (if he was required) + * @since 2.1.2 + */ + public abstract void setUI(U tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener, + TreeWillExpandListener willExpandListener); + + + /** + * The shared bridge. + * <p/> + * A helper deals with only ONE model (this one), becuase we add some + * listeners on it, we prefer always to keep ONE instance (any way this is + * a good thing). + * <p/> + * If you want to create a new model, just creates the good root node and + * push it in this model. + * <p/> + * For example, if you wrap the shared model with a filter model... Anyway, all + * listeners of this helper apply always of THIs model. + */ + private final B bridge; + + /** the associated ui component */ + private U ui; + + /** The shared data provider used to obtain datas to populate nodes and render them. */ + protected NavDataProvider dataProvider; + + /** + * A {@link TreeWillExpandListener} used to listen when tree should expand. + * <p/> + * If so, the listener will load selected node childs if required + * (says when the {@link NavNode#isLoaded()} is sets to {@code false}). + */ + protected TreeWillExpandListener expandListener; + + /** + * pour ouvrir les fils d'un noeud que l'on vient de sélectionner pour + * éviter d'avoir à faire des doubles clics. + */ + protected TreeSelectionListener selectionListener; + + /** + * pour recharger le rendu des noeuds (et charger les fils si nécessaires) + * lors d'une modification dans le modèle de l'arbre. + */ + protected TreeModelListener treeModelListener; + + /** Cache of child loadors. */ + protected static Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> childLoadors; + + protected static Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> getChildLoadors() { + if (childLoadors == null) { + childLoadors = new HashSet<NavNodeChildLoador<?, ?, ?, ?, ?>>(); + } + return childLoadors; + } + + /** + * Obtains the {@link NavNodeChildLoador} of the given {@code type} from + * internal cache. + * <p/> + * <b>Note:</b> The loador will be instanciated if not found, and push in cache. + * + * @param type the type of loador to get + * @param <L> the type of loador to get + * @return the loador from cache + */ + @SuppressWarnings({"unchecked"}) + public static <L extends NavNodeChildLoador<?, ?, ?, ?, ?>> L getChildLoador(Class<L> type) { + Set<? super NavNodeChildLoador<?, ?, ?, ?, ?>> cache = getChildLoadors(); + NavNodeChildLoador<?, ?, ?, ?, ?> result = null; + for (Object loador : cache) { + if (type.equals(loador.getClass())) { + result = (NavNodeChildLoador<?, ?, ?, ?, ?>) loador; + break; + } + } + if (result == null) { + // add it in cache + try { + result = type.newInstance(); + cache.add(result); + if (log.isDebugEnabled()) { + log.debug("Add " + result + " in loadors cache (new size:" + cache.size() + ")."); + } + } catch (Exception e) { + throw new IllegalArgumentException("Could not instanciate loador [" + type.getName() + "]", e); + } + } + return (L) result; + } + + public NavHelper(B bridge) { + this.bridge = bridge; + + selectionListener = new TreeSelectionListener() { + + @Override + public void valueChanged(TreeSelectionEvent e) { + + if (!checkModel()) { + return; + } + + // Hack, because event.getSource for TreeTable doesnt return selectionModel + TreeSelectionModel source = getSelectionModel(); + + if (source.isSelectionEmpty()) { + + // empty selection + if (log.isDebugEnabled()) { + log.debug("Selection is empty."); + } + return; + } + + boolean debugEnabled = log.isDebugEnabled(); + boolean traceEnabled = log.isTraceEnabled(); + for (TreePath path : e.getPaths()) { + + N node = getNode(path); + if (node == null) { + + // pas de noeud selectionne + if (debugEnabled) { + log.debug("Skip for null node."); + } + continue; + } + + boolean isAdded = e.isAddedPath(path); + + TreePath pathToExpand = new TreePath(NavHelper.this.bridge.getPathToRoot(node)); + boolean pathExpanded = isExpanded(pathToExpand); + + if (traceEnabled || isAdded && debugEnabled) { + log.debug("==== Node selection ===================================="); + log.debug("node ? " + node); + log.debug("is added ? " + isAdded); + log.debug("is path expanded ? " + pathExpanded); + log.debug("is node static ? " + node.isStaticNode()); + log.debug("is node loaded ? " + node.isLoaded()); + log.debug("is node leaf ? " + node.isLeaf()); + log.debug("node nb childs ? " + node.getChildCount()); + } + + if (isAdded && !pathExpanded) { + + // ask to expand path + if (log.isDebugEnabled()) { + log.debug("expand node [" + pathToExpand + "]"); + } + expandPath(pathToExpand); + } + } + } + }; + expandListener = new TreeWillExpandListener() { + @Override + public void treeWillExpand(TreeExpansionEvent event) { + + if (!checkModel()) { + // no model + return; + } + + N source = getNode(event.getPath()); + + if (source.isLoaded()) { + + // node is already loaded, nothing to do + return; + } + + if (log.isDebugEnabled()) { + log.debug("will load childs of node [" + source + "]"); + } + // populate childs of node + source.populateChilds(getBridge(), getDataProvider()); + } + + @Override + public void treeWillCollapse(TreeExpansionEvent event) { + } + }; + + treeModelListener = new TreeModelListener() { + @Override + public void treeNodesInserted(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("inserted ", source, children)); + } + + // ask to populate children nodes + populateNode(null, children, false); + } + + @SuppressWarnings({"unchecked"}) + @Override + public void treeNodesRemoved(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("removed ", source, children)); + } + + // Invalidates nodes in renderer cache (if any) + AbstractNavTreeCellRenderer<M, N> renderer = getTreeCellRenderer(); + if (children != null && renderer != null) { + for (Object child : children) { + renderer.invalidateCache((N) child); + } + } + } + + @Override + public void treeNodesChanged(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("changed ", source, children)); + } + + // ask to populate modified child nodes + populateNode(null, children, false); + } + + @Override + public void treeStructureChanged(TreeModelEvent e) { + if (!checkModel()) { + // no model + return; + } + N source = getNode(e.getTreePath()); + Object[] children = e.getChildren(); + if (log.isDebugEnabled()) { + log.debug(getMessage("structure changed", source, children)); + } + + // ask to populate structure modified node and nodes recursively + populateNode(source, children, true); + } + + protected String getMessage(String action, N source, Object[] children) { + StringBuilder sb = new StringBuilder(); + sb.append("==== Nodes "); + sb.append(action); + sb.append(" ================="); + sb.append("\nsource : ").append(source); + sb.append("\nnb nodes : "); + sb.append(children == null ? 0 : children.length); + if (children != null) { + int i = 0; + for (Object child : children) { + sb.append("\n ["); + sb.append(i++); + sb.append("] - "); + sb.append(child); + } + } + return sb.toString(); + } + }; + } + + /** + * Obtains the attached data provider used to populate and render nodes. + * + * @return the attached data provider + */ + protected NavDataProvider getDataProvider() { + return dataProvider; + } + + /** + * Obtains the model. + * + * @return the internal tree model or {@code null} if none was created. + */ + public M getModel() { + return bridge.getModel(); + } + + /** + * Obtains the bridge . + * + * @return the internal bridge used by helper. + */ + protected B getBridge() { + return bridge; + } + + /** + * Obtains the ui associated with model in helper. + * + * @return the ui (or {@code null} if no ui attached) + */ + public U getUI() { + return ui; + } + + public N getRootNode() { + if (!checkModel()) { + return null; + } + return bridge.getRoot(); + } + + /** + * Obtains the path of ids fro the root node to the selected node on the + * registred tree. + * + * @return the array of ids from root node to selected node. + */ + public String[] getSelectedIds() { + List<String> result = new ArrayList<String>(); + N selectedNode = getSelectedNode(); + while (selectedNode != null && !selectedNode.isRoot()) { + + result.add(selectedNode.getId()); + selectedNode = selectedNode.getParent(); + } + Collections.reverse(result); + return result.toArray(new String[result.size()]); + } + + /** + * Registers the given {@code tree} for this helper. + * <p/> + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and the {@link #selectionListener}. + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + */ + public void setUI(U tree, + boolean addExpandTreeListener) { + setUI(tree, addExpandTreeListener, null); + } + + /** + * Registers the given {@code tree} for this helper. + * <p/> + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and the {@link #selectionListener}. + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + * @param listener the optional selection listener to add + */ + public void setUI(U tree, + boolean addExpandTreeListener, + TreeSelectionListener listener) { + + setUI(tree, addExpandTreeListener, true, listener); + } + + /** + * Registers the given {@code tree} for this helper. + * <p/> + * <b>Note:</b> as a side-effect, it will register (if required) the + * {@link #expandListener} listener and (if required) the + * {@link #selectionListener}. + * + * @param tree the tree to register + * @param addExpandTreeListener a flag to add expand listener + * @param addOneClickSelectionListener a flag to expend when selection + * @param listener the optional selection listener to add + */ + public void setUI(U tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener) { + setUI(tree, + addExpandTreeListener, + addOneClickSelectionListener, + listener, + null + ); + } + + /** + * Registers the {@code dataProvider} for the helper. + * <p/> + * <b>Node:</b> As a side-effect, the provider will be propagate to the + * renderer of the registred tree (if any). + * + * @param dataProvider the data provider to use + */ + public void setDataProvider(NavDataProvider dataProvider) { + this.dataProvider = dataProvider; + AbstractNavTreeCellRenderer<M, N> renderer = getTreeCellRenderer(); + if (renderer != null) { + + // dispatch provider to renderer + renderer.setDataProvider(dataProvider); + } + } + + /** + * Inserts the given node to the given {@code parentNode}. + * <p/> + * The node will be added to his parent, then creation listeners will be + * fired. + * + * @param parentNode the parent node where to insert the new node * + * @param newNode the node to insert + */ + public void insertNode(N parentNode, N newNode) { + parentNode.add(newNode); + bridge.notifyNodeInserted(newNode); + } + + /** + * Inserts the given node to the given {@code parentNode}. + * <p/> + * The node will be added to his parent, then creation listeners will be + * fired. + * + * @param parentNode the parent node where to insert the new node * + * @param newNode the node to insert + * @param position position of node is inserted + */ + public void insertNode(N parentNode, N newNode, int position) { + parentNode.insert(newNode, position); + bridge.notifyNodeInserted(newNode); + } + + /** + * Removes the given {@code node} from the registred tree model and returns + * his parent. + * + * @param node the node to remove + * @return the parent node of the removed node. + */ + public N removeNode(N node) { + N parentNode = node.getParent(); + bridge.removeNodeFromParent(node); + return parentNode; + } + + /** + * Moves the given {@code node} to the new {@code position}. + * + * @param parentNode the parent node + * @param node the node to move + * @param position the new position of the node + */ + public void moveNode(N parentNode, N node, int position) { + parentNode.remove(node); + parentNode.insert(node, position); + bridge.nodeStructureChanged(parentNode); + } + + /** + * Refreshs the given {@code node}. + * <p/> + * If flag {@code deep} is set to {@code true}, then it will refresh + * recursively children nodes. + * <p/> + * <b>Note:</b>As a side-effect, evvery node involved will become + * {@code dirty}. + * + * @param node the node to refresh + * @param deep un flag pour activer la repainte de la descendance du + * noeud + * @see NavNode#isDirty() + */ + @SuppressWarnings({"unchecked"}) + public void refreshNode(N node, boolean deep) { + if (log.isDebugEnabled()) { + log.debug("Will refresh (deep ? " + deep + ") node " + node); + } + bridge.nodeChanged(node); + if (deep) { + // repaint childs nodes + Enumeration<N> e = node.children(); + while (e.hasMoreElements()) { + N child = e.nextElement(); + refreshNode(child, true); + } + } + } + + /** + * To load all nodes of a model. + * + * @param node the root node to load + * @param dataProvider the data provider used to populate nodes + */ + @SuppressWarnings({"unchecked"}) + public void loadAllNodes(N node, NavDataProvider dataProvider) { + if (!checkModel()) { + return; + } + if (!node.isLoaded()) { + node.populateChilds(getBridge(), dataProvider); + Enumeration<? extends NavNode<?, ?>> enumeration = node.children(); + while (enumeration.hasMoreElements()) { + N jaxxNode = (N) enumeration.nextElement(); + loadAllNodes(jaxxNode, dataProvider); + } + } + } + + /** + * Selects the parent of the currently selected node. + * <p/> + * <b>Note:</> If selection is empty, then throws a NPE. + * + * @throws NullPointerException if selection is empty + */ + public void selectParentNode() throws NullPointerException { + + N node = getSelectedNode(); + + if (node == null) { + // pas de noeud selectionne + throw new NullPointerException("no selected node in context"); + } + node = node.getParent(); + + selectNode(node); + } + + /** + * Selects the given {@code node} in the registred tree. + * + * @param node the node to select + */ + public void selectNode(N node) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node [" + node + "]"); + } + TreePath path = new TreePath(bridge.getPathToRoot(node)); + + addSelectionPath(path); + scrollPathToVisible(path); + } + + /** + * Selects the given {@code nodes} in the registred tree. + * + * @param nodes the nodes to select + */ + public void selectNodes(List<N> nodes) { + if (!checkModel()) { + + // no model + return; + } + List<TreePath> paths = new ArrayList<TreePath>(); + for (N node : nodes) { + paths.add(new TreePath(bridge.getPathToRoot(node))); + } + addSelectionPaths(paths.toArray(new TreePath[paths.size()])); + } + + /** + * Unselects the given {@code node} in the registred tree. + * + * @param node the node to select + */ + public void unSelectNode(N node) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node [" + node + "]"); + } + TreePath path = new TreePath(bridge.getPathToRoot(node)); + + removeSelectionPath(path); + } + + /** + * Selects the given {@code nodes} in the registred tree. + * + * @param nodes the nodes to select + */ + public void unSelectNodes(List<N> nodes) { + if (!checkModel()) { + + // no model + return; + } + for (N node : nodes) { + unSelectNode(node); + } + } + + /** + * Selects the node described by his given {@code path} of ids. + * + * @param path the absolute path of ids from root node to node to select. + */ + public void selectNode(String... path) { + if (!checkModel()) { + + // no model + return; + } + if (log.isDebugEnabled()) { + log.debug("try to select node from ids " + Arrays.toString(path)); + } + N root = bridge.getRoot(); + N node = findNode(root, path); + if (log.isDebugEnabled()) { + log.debug("selected node [" + node + "]"); + } + if (node != null) { + selectNode(node); + } + } + + /** + * Finds a node from the given root {@code node}, applying the path given + * by {@code ids}. + * + * @param node the starting node + * @param ids the path of ids to apply on the node. + * @return the find node or {@code null} if no node matchs. + */ + public N findNode(N node, String... ids) { + if (!checkModel()) { + + // no model + return null; + } + N result = null; + for (String id : ids) { + + result = node.findNodeById(id, getBridge(), getDataProvider()); + + if (result == null) { + + // un des noeud n'a pas ete trouve, on sort + break; + } + node = result; + } + return result; + } + + /** + * Finds a node from the given root {@code node}, and return child searched + * + * @param node the starting node + * @param id id of searched child + * @return the find node or {@code null} if no node matchs. + */ + public N getChild(N node, String id) { + if (!checkModel()) { + + // no model + return null; + } + N result = node.getChild(id, getBridge(), getDataProvider()); + + return result; + } + + /** + * Checks if internal model was created. + * + * @return {@code true} if model was created, {@code false} otherwise. + */ + protected boolean checkModel() { + if (getModel() == null) { + + // no model set, + if (log.isWarnEnabled()) { + log.warn("No model set in " + this); + } + return false; + } + // model is set + return true; + } + + /** + * Populates nodes. + * <p/> + * If {@code node} is not {@code null}, then populate it. + * <p/> + * If {@code children} is not {@code null}, then populate them, moreover + * if {@code recurse} is set to {@code true} then do a recurse refresh on + * children. + * + * @param node the parent node to populate (optional) + * @param children the child nodes to populate (optional) + * @param recurse flag sets to {@code true} if should do recurse refresh on + * given {@code children} nodes. + */ + @SuppressWarnings({"unchecked"}) + protected void populateNode(N node, + Object[] children, + boolean recurse) { + NavDataProvider dataProvider = getDataProvider(); + if (node != null) { + if (log.isDebugEnabled()) { + log.debug("Will populate node : " + node); + } + node.populateNode(getBridge(), dataProvider, false); + } + if (children != null) { + for (Object o : children) { + N child = (N) o; + if (log.isDebugEnabled()) { + log.debug("Will populate child node : " + child); + } + child.populateNode(getBridge(), dataProvider, recurse); + } + } + } + + /** + * Convinient method to objet the casted node of a {@link TreePath}. + * + * @param path the path contaning the node. + * @return the casted node from the path. + */ + @SuppressWarnings({"unchecked"}) + protected N getNode(TreePath path) { + N result = (N) path.getLastPathComponent(); + return result; + } + + protected void setUI(U ui) { + this.ui = ui; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNode.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNode.java new file mode 100644 index 0000000..4020adf --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNode.java @@ -0,0 +1,223 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav; + +import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; + +import javax.swing.tree.TreeNode; +import java.io.Serializable; + +/** + * Definition of a node with a optional {@code childLoador} to build childs of + * node. + * <p/> + * A node is identified by an {@link #getId} of an associated data of type + * {@link #getInternalClass}. + * <p/> + * <b>Note:</b> + * <p><i> While using a {@code childLoador}, we can not know before node + * was loaded the exact count of his childs. As a matter of facts, real leaf + * nodes appears at the beginning in ui as a not leaf (there is a root handler). + * When node was loaded, a leaf node will be then displayed as required. + * </i></p> + * <p/> + * <h2>Why NavNode is generic ?</h2> + * In a project, you should implements your own Node extending with one like this : + * <pre> + * class MyNode extends NavNode<MyNode> { ... } + * </pre> + * While in this class, you overrides every method with a node return type, + * co-variance you'll be able to use this code : + * <pre> + * MyNode parentNode = new MyNode(); + * MyNode node = parentNode.getFirstNode(); + * </pre> + * So for final application this generic type avoid any cast for your own node + * type, this is quite convinient. + * <p/> + * Even if in your project, you wants to have a heriarchy of nodes, this will + * still works (if you use a genercic type on your abstract nodes). + * <h2>Internal states</h2> + * <ul> + * <li><b>internalClass</b> : the type of data associated with the node</li> + * <li><b>context</b> : an optinal context to distinguish different types of + * node with same {@code internalclass}</li> + * <li><b>id</b> : id of the data associated with the node</li> + * <li><b>dirty</b> : flag sets to {@code true} when node render MUST be recomputed</li> + * <li><b>loaded</b> : flag sets to {@code true} when node was loaded</li> + * <li><b>childLoador</b> : optional loador of childs</li> + * </ul> + * <h2>Static nodes</h2> + * Some nodes do not need auto-loading, we call them {@code static nodes}. + * The method {@link #isStaticNode()} gives this state. + * <p/> + * <b>Note:</b> A static node has no {@code childLoador}. + * <h2>Node loading</h2> + * Initialy node has no data child nodes, ({@link #isLoaded()} equals + * {@code false}). + * when model requires node's childs, it can load them via method + * {@link #populateNode(NavBridge, NavDataProvider, boolean)} + * and {@link #populateChilds(NavBridge, NavDataProvider)} methods. + * <h2>Node rendering</h2 + * the {@link AbstractNavTreeCellRenderer} looks the {@link #isDirty} state to + * know when render should be (re-)compute and set back the state to {@code false}. + * <p/> + * Each time, a node is modified, the {@link #isDirty} should be set to {@code true}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public interface NavNode<M, N extends NavNode<M, N>> extends Cloneable, TreeNode, Serializable { + + String getId(); + + String getContext(); + + Class<?> getInternalClass(); + + boolean isLoaded(); + + boolean isDirty(); + + /** + * Convinient method to known if the node is a {@code String} typed. + * + * @return {@code true} if the type of node if + */ + boolean isStringNode(); + + /** + * To know if the node is static. + * <p/> + * A {@code static} node has no {@code childLoador}. + * + * @return {@code true} when the node is static : says, the node has + * no {@code childLoador}. + */ + boolean isStaticNode(); + + /** + * Gets the first node form this one to the root which has a none + * {@code String} type. + * + * @return the first concrete node type + */ + N getContainerNode(); + + /** + * Given an {@code id}, obtain the child with matching id. + * <p/> + * If node is NOT {@code loaded}, then first loads it (method + * {@link #populateChilds(NavBridge, NavDataProvider)}) then do search + * on direct childs of the node recursivly. + * + * @param id the id of the researched node + * @param bridge model owner of nodes + * @param provider data provider + * @return the found node or {@code null} if not found + */ + N findNodeById(String id, + NavBridge<M, N> bridge, + NavDataProvider provider); + + /** + * Given an {@code id}, obtain the child with matching id. + * <p/> + * If node is NOT {@code loaded}, then first loads it (method + * {@link #populateChilds(NavBridge, NavDataProvider)}) then return + * on direct childs of the node. + * + * @param id the id of the researched node + * @param bridge model owner of nodes + * @param provider data provider + * @return the found node or {@code null} if not found + */ + N getChild(String id, + NavBridge<M, N> bridge, + NavDataProvider provider); + + /** + * Changes the {@link #isDirty} state. + * <p/> + * As a side effect, when a renderer will use this node, it will force to + * reload the render from the {@link NavDataProvider}. + * + * @param dirty the new dirty value + */ + void setDirty(boolean dirty); + + @Override + boolean isLeaf(); + + Object getUserObject(); + + @Override + String toString(); + + //-------------------------------------------------------------------------- + //-- Populate methods + //-------------------------------------------------------------------------- + + /** + * To populate the node. A side-effect of this method is to set {@code dirty} + * the node (renderer will recompute the render of the node). + * <p/> + * If {@code populateChilds} is set to {@code true}, then also populate + * childs of the node using the given {@code dataProvider}. + * + * @param bridge le delegate modèles content le noeud + * @param provider le provider de données + * @param populateChilds un drapeau pour charger aussi les fils du noeud courant + */ + void populateNode(NavBridge<M, N> bridge, + NavDataProvider provider, + boolean populateChilds); + + /** + * To populate childs of the node (only when a none static node). + * A side-effect of this method is to set {@code loaded} of the node. + * <p/> + * For a static node, do nothing. + * + * @param bridge model owner of the node + * @param provider data provider + */ + void populateChilds(NavBridge<M, N> bridge, NavDataProvider provider); + + //-------------------------------------------------------------------------- + //-- Overrides to use generic type as return + //-------------------------------------------------------------------------- + + boolean isRoot(); + + @Override + N getParent(); + + void add(N node); + + void remove(N node); + + void insert(N node, int position); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNodeChildLoador.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNodeChildLoador.java new file mode 100644 index 0000000..22dfec2 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/NavNodeChildLoador.java @@ -0,0 +1,170 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.Serializable; +import java.util.List; + +/** + * Object to load childs of a node. + * <p/> + * It uses {@link NavDataProvider} in method + * {@link #loadChilds(NavBridge, NavNode, NavDataProvider)} to obtain datas + * then build childs nodes. + * <p/> + * A factory of such objects can be found in {@link NavHelper} to make + * them reusable in other places than inside a {@link NavNode} to auto-load + * childs. + * <p/> + * For example when you want to creat by hand a new node, always prefer to reuse + * a such object rathen than duplicate same code in helper... + * + * @param <T> type of data used to create nodes (can be just a String type to use only ids) + * @param <O> type of data associated with nodes + * @param <N> type of node to used (to make possible full co-variance and no cast in fal implementations). + * @author tchemit <chemit@codelutin.com> + * @see NavHelper + * @see NavNode + * @since 2.1 + */ +public abstract class NavNodeChildLoador<T, O, M, B extends NavBridge<M, N>, N extends NavNode<M, N>> implements Serializable { + + /** Logger. */ + static private final Log log = LogFactory.getLog(NavNodeChildLoador.class); + + private static final long serialVersionUID = 1L; + + /** Type of data of the node */ + protected final Class<O> beanType; + + protected NavNodeChildLoador(Class<O> beanType) { + this.beanType = beanType; + } + + /** + * Obtain the list of data used to create nodes. + * <p/> + * If type {@code T} is {@code O}, we directly use the data associated with nodes. + * + * @param parentClass type of parent + * @param parentId id of parent + * @param dataProvider the data provider + * @return the list of data + * @throws Exception if any problem + */ + public abstract List<T> getData(Class<?> parentClass, + String parentId, + NavDataProvider dataProvider) throws Exception; + + /** + * Hook to create a child node given his {@code data}. + * + * @param data the data of the node to create + * @param dataProvider the data provider + * @return the created node + */ + public abstract N createNode(T data, NavDataProvider dataProvider); + + /** + * Returns the type of data associated with nodes to create. + * + * @return the type of data associated with created nodes. + */ + public Class<O> getBeanType() { + return beanType; + } + + /** + * Load childs of the given {@code parentnode}. + * + * @param bridge the model owner of nodes + * @param parentNode the parent node where to insert nodes + * @param dataProvider data provider + * @throws Exception pour tout probleme de recuperation de donnees + */ + public void loadChilds(B bridge, + N parentNode, + NavDataProvider dataProvider) throws Exception { + + N containerNode = parentNode.getContainerNode(); + + List<T> datas; + if (containerNode == null) { + + // pas d'ancetre, il doit s'agir d'un premier noeud de données + // depuis le noeud root + + // recuperation des objets fils (sans connaitre de parent) + datas = getData(null, null, dataProvider); + + } else { + if (log.isDebugEnabled()) { + log.debug("search data for " + containerNode.getInternalClass() + + " : " + containerNode.getId()); + } + + // recuperation des objets fils + datas = getData(containerNode.getInternalClass(), + containerNode.getId(), + dataProvider); + } + + // on charge les fils + addChildNodes(parentNode, datas, dataProvider); + + // notifie le modele d'un ajout de noeuds + bridge.notifyChildNodesInserted(parentNode); + } + + /** + * Add childs to given {@code parentNode} using retrive {@code datas} from + * the data provider. + * <p/> + * This method is invoked by the {@link #loadChilds(NavBridge, NavNode, NavDataProvider)}. + * + * @param parentNode the node where to insert + * @param datas the data used to create node + * @param dataProvider the data provider + */ + protected void addChildNodes(N parentNode, + List<T> datas, + NavDataProvider dataProvider) { + + // creation des noeuds fils + if (datas != null) { + for (T o : datas) { + if (log.isDebugEnabled()) { + log.debug("[" + parentNode + "] Will add child node for " + o); + } + N node = createNode(o, dataProvider); + parentNode.add(node); + } + } + } + +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html new file mode 100644 index 0000000..c608765 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/package.html @@ -0,0 +1,87 @@ +<!-- + #%L + JAXX :: Runtime + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>JAXX - nav api</h1> + +This package contains a little framework to build dynamic nodes. + +Tow implementations are offers : + +<ul> + <li>One for the <b>JTree</b> in <b>jaxx.runtime.swing.nav.tree</b></li> + <li>One for the <b>JXTreeTable</b> in + <b>jaxx.runtime.swing.nav.treetable</b></li> +</ul> + +<p> + Replace the previous framework from package + <code>jaxx.runtime.swing.navigation</code> +</p> + +<h1>Why this api ?</h1> + +<p> + The main goal of this api is to offer an auto-loading system of tree + model. +</p> + +<p> + While previous api we had to load all the model in memory, now we can build + a tree model with no data. +</p> + +<p> + When the tree will need to expand a node, it will ask first in childs of + node were loaded, if not, load them then give by hand to system. +</p> + +<p> + This api allow to switch easily between tree implementation and tree table + api. +</p> + + +<h1>Api</h1> + + +<h2>DataProvider</h2> +Contract of objet responsible of acquiring data to populate nodes and render +them. + +<h2>JaxxNode</h2> +Jaxx node contract customized for our purpose (loaded, dirty states,...). + +<h2>JaxxNodeChildLoador</h2> +Contract to load childs of a JaxxNode using DataProvider. + +<h2>JaxxNavHelper</h2> +Helper to manage a tree or a tree table using auto-loading nodes. + +<h2>JaxxNavBridge</h2> +Bridge to encapsulate models. + +</body> +</html> diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java new file mode 100644 index 0000000..da9d5bc --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/AbstractNavTreeCellRenderer.java @@ -0,0 +1,128 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.tree; + +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.NavNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.tree.DefaultTreeCellRenderer; +import java.util.HashMap; +import java.util.Map; + +import static org.nuiton.i18n.I18n._; + +/** + * Le renderer abstrait (qui a toutes les methodes qui aident) pour implanter de + * vrai renderer pour les différents cas d'utilisation de l'abre de navigation. + * + * @author chemit <chemit@codelutin.com> + * @since 1.2 + */ +public abstract class AbstractNavTreeCellRenderer<M, N extends NavNode<M, N>> extends DefaultTreeCellRenderer { + + /** Logger */ + protected static final Log log = + LogFactory.getLog(AbstractNavTreeCellRenderer.class); + + /** source de donnée */ + protected NavDataProvider dataProvider; + + /** le cache de rendu */ + protected final Map<N, String> renderCache = new HashMap<N, String>(); + + /** + * Determines the text render of a node using the {@link #dataProvider}. + * + * @param node the node to render + * @return the text render of the node + */ + protected abstract String computeNodeText(N node); + + protected AbstractNavTreeCellRenderer() { + } + + public NavDataProvider getDataProvider() { + return dataProvider; + } + + public void setDataProvider(NavDataProvider dataProvider) { + this.dataProvider = dataProvider; + + // une nouvelle source utilisée, on vide le cache + clearCache(); + } + + public void clearCache() { + renderCache.clear(); + } + + public void invalidateCache(N node) { + renderCache.remove(node); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + clearCache(); + } + + public String getNodeText(N node) { + if (node == null) { + return null; + } + String text; + + if (node.isDirty() || !renderCache.containsKey(node)) { + + // calculer le rendu du noeud + if (node.isStringNode()) { + text = _(node.getId()); + + } else { + + text = computeNodeText(node); + } + + if (log.isDebugEnabled()) { + log.debug("text for node [" + node + "] = <" + text + ">"); + } + + // sauvegarde dans le cache + renderCache.put(node, text); + + // le noeud est de nouveau propre + node.setDirty(false); + + } else { + + // recupération directement du rendu dans le cache + text = renderCache.get(node); + } + + return text; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeBridge.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeBridge.java new file mode 100644 index 0000000..3f93903 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeBridge.java @@ -0,0 +1,240 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.tree; + +import jaxx.runtime.swing.nav.NavBridge; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.Enumeration; +import java.util.EventListener; + +/** + * Delegate model used to switch between tree model and tree table model api + * + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavTreeBridge<N extends NavTreeNode<N>> implements NavBridge<DefaultTreeModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeBridge.class); + + /** bridge model */ + protected DefaultTreeModel model; + + /** bridge ui */ +// protected JTree ui; +// public NavTreeBridge() { +// } + + //-------------------------------------------------------------------------- + //-- Model Queries + //-------------------------------------------------------------------------- + @Override + public DefaultTreeModel getModel() { + return model; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getRoot() { + return (N) model.getRoot(); + } + + @Override + public boolean isLeaf(Object node) { + return model.isLeaf(node); + } + + @Override + public int getChildCount(Object parent) { + return model.getChildCount(parent); + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getChild(Object parent, int index) { + return (N) model.getChild(parent, index); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + return model.getIndexOfChild(parent, child); + } + + @Override + public TreeNode[] getPathToRoot(TreeNode aNode) { + return model.getPathToRoot(aNode); + } + + //-------------------------------------------------------------------------- + //-- Model modification + //-------------------------------------------------------------------------- + + @Override + public void setModel(DefaultTreeModel model) { + this.model = model; + } + + @Override + public void setRoot(N node) { + model.setRoot(node); + } + + @Override + public void insertNodeInto(N newChild, N parent, int index) { + model.insertNodeInto(newChild, parent, index); + } + + @Override + public void removeNodeFromParent(N node) { + model.removeNodeFromParent(node); + } + + @Override + public void reload(N node) { + model.reload(); + } + + @Override + public boolean canLoadChild(N node) { + return true; + } + + //-------------------------------------------------------------------------- + //-- Model Listeners notifications + //-------------------------------------------------------------------------- + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + model.valueForPathChanged(path, newValue); + } + + @Override + public void nodesWereInserted(N parent, int[] indices) { + model.nodesWereInserted(parent, indices); + } + + @Override + public void nodeWereInserted(N parentNode, int childIndice, N node) { + int[] indices = new int[1]; + indices[0] = childIndice; + model.nodesWereInserted(parentNode, indices); + } + + @Override + public void nodeChanged(TreeNode node) { + model.nodeChanged(node); + } + + @Override + public void nodeStructureChanged(TreeNode node) { + model.nodeStructureChanged(node); + } + + @Override + public void nodesWereRemoved(TreeNode node, int[] childIndices, + Object[] removedChildren) { + model.nodesWereRemoved(node, childIndices, removedChildren); + } + + @Override + public void nodesChanged(TreeNode node, int[] childIndices) { + model.nodesChanged(node, childIndices); + } + + @Override + @SuppressWarnings({"unchecked"}) + public void notifyChildNodesInserted(N node) { + int count = node.getChildCount(); + if (count < 1) { + if (log.isDebugEnabled()) { + log.debug("Skip for leaf node : " + node); + } + return; + } + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", " + count + " child(s) inserted."); + } + int[] indices = new int[count]; + for (int i = 0; i < count; i++) { + indices[i] = i; + } + + nodesWereInserted(node, indices); + + // recurse notify on childs + for (Enumeration<? extends NavTreeNode<?>> childs = node.children(); + childs.hasMoreElements(); ) { + N child = (N) childs.nextElement(); + notifyChildNodesInserted(child); + } + } + + @Override + public void notifyNodeInserted(N node) { + + N parent = node.getParent(); + if (parent != null) { + int indice = parent.getIndex(node); + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", for parent [" + parent + "] child " + indice + " inserted."); + } + nodesWereInserted(parent, new int[]{indice}); + notifyChildNodesInserted(node); + } + } + + //-------------------------------------------------------------------------- + //-- TreeModelListener provider + //-------------------------------------------------------------------------- + + @Override + public void addTreeModelListener(TreeModelListener l) { + model.addTreeModelListener(l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) { + model.removeTreeModelListener(l); + } + + @Override + public TreeModelListener[] getTreeModelListeners() { + return model.getTreeModelListeners(); + } + + @Override + @SuppressWarnings({"unchecked"}) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { + return model.getListeners(listenerType); + } + +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeHelper.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeHelper.java new file mode 100644 index 0000000..aa2cb39 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeHelper.java @@ -0,0 +1,185 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.tree; + +import jaxx.runtime.swing.nav.NavHelper; + +import javax.swing.JTree; +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.util.ArrayList; +import java.util.List; + +/** + * The implementation of {@link NavHelper} base on a {@link JTree} component. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public class NavTreeHelper<N extends NavTreeNode<N>> extends NavHelper<DefaultTreeModel, JTree, NavTreeBridge<N>, N> { + + public NavTreeHelper() { + this(new NavTreeBridge<N>()); + } + + public NavTreeHelper(NavTreeBridge<N> bridge) { + super(bridge); + } + + @Override + public void scrollPathToVisible(TreePath path) { + getUI().scrollPathToVisible(path); + } + + @Override + public void setSelectionPath(TreePath path) { + getUI().setSelectionPath(path); + } + + @Override + public void addSelectionPaths(TreePath[] paths) { + getUI().addSelectionPaths(paths); + } + + @Override + public void addSelectionPath(TreePath path) { + getUI().addSelectionPath(path); + } + + @Override + public void removeSelectionPaths(TreePath[] path) { + getUI().removeSelectionPaths(path); + } + + @Override + public void removeSelectionPath(TreePath path) { + getUI().removeSelectionPath(path); + } + + @Override + public TreeSelectionModel getSelectionModel() { + return getUI().getSelectionModel(); + } + + @Override + public boolean isExpanded(TreePath pathToExpand) { + return getUI().isExpanded(pathToExpand); + } + + @Override + public void expandPath(TreePath pathToExpand) { + getUI().expandPath(pathToExpand); + } + + @SuppressWarnings({"unchecked"}) + @Override + public AbstractNavTreeCellRenderer<DefaultTreeModel, N> getTreeCellRenderer() { + JTree t = getUI(); + if (t == null) { + return null; + } + TreeCellRenderer r = t.getCellRenderer(); + if (r instanceof AbstractNavTreeCellRenderer) { + return (AbstractNavTreeCellRenderer<DefaultTreeModel, N>) r; + } + return null; + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getSelectedNode() { + JTree tree = getUI(); + if (tree == null) { + return null; + } + TreePath path = tree.getSelectionPath(); + N node = null; + if (path != null) { + node = (N) path.getLastPathComponent(); + } + return node; + } + + @SuppressWarnings({"unchecked"}) + @Override + public List<N> getSelectedNodes() { + JTree tree = getUI(); + if (tree == null) { + return null; + } + TreePath[] paths = tree.getSelectionPaths(); + List<N> nodes = new ArrayList<N>(); + if (paths != null) { + for (TreePath path : paths) { + if (path != null) { + nodes.add((N) path.getLastPathComponent()); + } + } + } + return nodes; + } + + @Override + public void setUI(JTree tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener, + TreeWillExpandListener willExpandListener) { + setUI(tree); + if (willExpandListener != null) { + tree.addTreeWillExpandListener(willExpandListener); + } + if (addExpandTreeListener) { + tree.addTreeWillExpandListener(expandListener); + } + if (listener != null) { + tree.addTreeSelectionListener(listener); + } + if (addOneClickSelectionListener) { + tree.addTreeSelectionListener(selectionListener); + } + } + + @Override + protected DefaultTreeModel createModel(N node, Object... extraArgs) { + NavTreeBridge<N> bridge = getBridge(); + DefaultTreeModel model = bridge.getModel(); + if (model == null) { + model = new DefaultTreeModel(node); + bridge.setModel(model); + bridge.addTreeModelListener(treeModelListener); + } else { + bridge.setRoot(node); + } + + // notify structure has changed + bridge.nodeStructureChanged(getRootNode()); + return model; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNode.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNode.java new file mode 100644 index 0000000..7caf15b --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNode.java @@ -0,0 +1,428 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.tree; + +import jaxx.runtime.swing.nav.NavBridge; +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.NavNode; +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.Enumeration; + +/** + * Implementation of {@link NavNode} used to create in tree table + * This node extends {@link DefaultMutableTreeNode} + * + * @author tchemit <chemit@codelutin.com> + * @since 2.2 + */ +public class NavTreeNode<N extends NavTreeNode<N>> extends DefaultMutableTreeNode implements NavNode<DefaultTreeModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavNode.class); + + private static final long serialVersionUID = 1L; + + /** Type of data associated with the node */ + protected final Class<?> internalClass; + + /** + * Optinal context to distinguish different nodes with same + * {@link #internalClass}. + */ + protected final String context; + + /** Id of the data associated with the node. */ + protected final String id; + + /** Flag to know when renderer should (re-)compute render of the node. */ + protected boolean dirty = true; + + /** Flag to know when the none static node was loaded. */ + protected boolean loaded; + + /** Optional child loador to lazy create childs of the node. */ + protected final NavTreeNodeChildLoador<?, ?, N> childLoador; + + protected NavTreeNode(String id) { + this(String.class, id, null, null); + } + + public NavTreeNode(Class<?> internalClass, + String id, + String context, + NavTreeNodeChildLoador<?, ?, N> childLoador) { + this.internalClass = internalClass; + this.id = id; + this.context = context; + this.childLoador = childLoador; + if (isStaticNode()) { + + // A static node is always full loaded + loaded = true; + } + if (log.isDebugEnabled()) { + log.debug("new node : " + this); + } + } + + @Override + public String getId() { + return id; + } + + @Override + public String getContext() { + return context; + } + + @Override + public Class<?> getInternalClass() { + return internalClass; + } + + @Override + public boolean isLoaded() { + return loaded; + } + + @Override + public boolean isDirty() { + return dirty; + } + + @Override + public boolean isStringNode() { + return String.class.equals(internalClass); + } + + @Override + public boolean isStaticNode() { + return childLoador == null; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getContainerNode() { + if (isRoot()) { + // si on arrive sur le root, quelque chose ne va pas, + // on bloque par null, a defaut de declancher une exception + return null; + } + + if (isStringNode()) { + // on est sur un noeud de type String, donc on regarde sur le parent + return getParent().getContainerNode(); + } + + // cas final : sur un noeud de donnee + classe interne de donnee + return (N) this; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N findNodeById(String id, + NavBridge<DefaultTreeModel, N> model, + NavDataProvider provider) { + if (id == null) { + + // id null ? donc rien a faire + return null; + } + if (id.equals(getId())) { + + // on a trouve le bon noeud + return (N) this; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(model, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N node = enumeration.nextElement(); + N nodeById = node.findNodeById(id, model, provider); + if (nodeById != null) { + return nodeById; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public N getChild(String id, + NavBridge<DefaultTreeModel, N> bridge, + NavDataProvider provider) { + + if (id == null) { + + // id null ? donc rien a faire + return null; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(bridge, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N child = enumeration.nextElement(); + if (id.equals(child.getId())) { + return child; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + @Override + public boolean isLeaf() { + // there is two behaviours for the test : + // 1 - when the node is static, then can directly use his number of child + // to determine if node is a leaf (no child) + // 2 - when the node is dynamic, then ALWAYS says the node is NOT a leaf until + // it was loaded, otherwise the WillExpand listener will not load the childs... + // Once the node is loaded, use back the normal behaviour (count number of childs) + return isStaticNode() ? super.isLeaf() : isLoaded() && getChildCount() == 0; + } + + @Override + public Object getUserObject() { + return id; + } + + @Override + public String toString() { + return System.identityHashCode(this) + "-" + id; + } + + //-------------------------------------------------------------------------- + //-- Populate methods + //-------------------------------------------------------------------------- + + @Override + public void populateNode(NavBridge<DefaultTreeModel, N> model, + NavDataProvider provider, + boolean populateChilds) { + + // on indique que le noeud n'est plus propre + setDirty(true); + + if (populateChilds) { + + // chargement des fils + populateChilds(model, provider); + } + } + + @Override + @SuppressWarnings({"unchecked"}) + public void populateChilds(NavBridge<DefaultTreeModel, N> bridge, + NavDataProvider provider) { + if (isStaticNode()) { + + if (log.isDebugEnabled()) { + log.debug("is static node " + this); + } + + // noeud static, rien a faire + return; + } + + if (!bridge.canLoadChild((N) this)) { + + // can not load childs + if (log.isDebugEnabled()) { + log.debug("Will Skip populateChilds for node : " + this); + } + return; + } + + // chargement des noeuds fils du noeud courant + try { + if (log.isDebugEnabled()) { + log.debug("Will load childs for " + this); + } + childLoador.loadChilds((NavTreeBridge<N>) bridge, (N) this, provider); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + + // au final, on passe le noeud a l'état chargé + loaded = true; + } + } + + //-------------------------------------------------------------------------- + //-- Overrides to use generic type as return + //-------------------------------------------------------------------------- + + @SuppressWarnings({"unchecked"}) + @Override + public N getParent() { + return (N) super.getParent(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getRoot() { + return (N) super.getRoot(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getFirstChild() { + return (N) super.getFirstChild(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getLastChild() { + return (N) super.getLastChild(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildAfter(TreeNode aChild) { + return (N) super.getChildAfter(aChild); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildBefore(TreeNode aChild) { + return (N) super.getChildBefore(aChild); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getNextSibling() { + return (N) super.getNextSibling(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getPreviousSibling() { + return (N) super.getPreviousSibling(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getFirstLeaf() { + return (N) super.getFirstLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getLastLeaf() { + return (N) super.getLastLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getNextLeaf() { + return (N) super.getNextLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getPreviousLeaf() { + return (N) super.getPreviousLeaf(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getNextNode() { + return (N) super.getNextNode(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getPreviousNode() { + return (N) super.getPreviousNode(); + } + + @SuppressWarnings({"unchecked"}) + public N getSharedAncestor(N aNode) { + return (N) getSharedAncestor((DefaultMutableTreeNode) aNode); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildAt(int index) { + return (N) super.getChildAt(index); + } + + @SuppressWarnings({"unchecked"}) + @Override + public Enumeration<N> children() { + return (Enumeration<N>) super.children(); + } + + @Override + public void add(N node) { + super.add(node); + } + + @Override + public void remove(N node) { + super.remove(node); + } + + @Override + public void insert(N node, int position) { + super.insert(node, position); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java new file mode 100644 index 0000000..cda90d1 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/NavTreeNodeChildLoador.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.tree; + +import jaxx.runtime.swing.nav.NavNodeChildLoador; + +import javax.swing.tree.DefaultTreeModel; + +/** + * Implementation for tree of {@link NavNodeChildLoador} + * + * @author sletellier <letellier@codelutin.com> + * @since 2.2 + */ +public abstract class NavTreeNodeChildLoador<T, O, N extends NavTreeNode<N>> extends NavNodeChildLoador<T, O, DefaultTreeModel, NavTreeBridge<N>, N> { + + private static final long serialVersionUID = 1L; + + protected NavTreeNodeChildLoador(Class<O> beanType) { + super(beanType); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/package.html b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/package.html new file mode 100644 index 0000000..90239b4 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/tree/package.html @@ -0,0 +1,45 @@ +<!-- + #%L + JAXX :: Runtime + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +package.html +<html> +<body> +<h1>JAXX - nav tree implementation</h1> + +This package contains the implementation of nav api for the <b>JTree</b> + +<h2>NavTreeNode</h2> +An override of DefaultMutableTreeNode implement JaxxNode. + +<h2>NavTreeChildLoador</h2> +Object to load childs of a tree node using DataProvider. + +<h2>NavTreeHelper</h2> +Helper to manage a tree using auto-loading nodes. + +<h2>AbstractNavTreeCellRenderer</h2> +Abstract renderer using DataProvider to acquire node render. + +</body> +</html> diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java new file mode 100644 index 0000000..3f008df --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableBridge.java @@ -0,0 +1,297 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.treetable; + +import jaxx.runtime.swing.nav.NavBridge; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.treetable.TreeTableNode; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.List; + +/** + * Delegate model used to switch between tree model and tree table model api + * + * @author sletellier <letellier@codelutin.com> + * @since 2.1 + */ +public class NavTreeTableBridge<N extends NavTreeTableNode<N>> implements NavBridge<NavTreeTableModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeTableBridge.class); + + /** bridge model */ + protected NavTreeTableModel model; + + /** bridge ui */ +// protected JXTreeTable ui; + +// public NavTreeTableBridge() { +// if (log.isDebugEnabled()) { +// log.debug("New " + this); +// } +// } + + //-------------------------------------------------------------------------- + //-- Model Queries + //-------------------------------------------------------------------------- + @Override + public NavTreeTableModel getModel() { + return model; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getRoot() { + return (N) model.getRoot(); + } + + @Override + public boolean isLeaf(Object node) { + return model.isLeaf(node); + } + + @Override + public int getChildCount(Object parent) { + return model.getChildCount(parent); + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getChild(Object parent, int index) { + return (N) model.getChild(parent, index); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + return model.getIndexOfChild(parent, child); + } + + @Override + public TreeNode[] getPathToRoot(TreeNode aNode) { + return model.getPathToRoot((TreeTableNode) aNode); + } + + //-------------------------------------------------------------------------- + //-- Model modification + //-------------------------------------------------------------------------- + + + @Override + public void setModel(NavTreeTableModel model) { + this.model = model; + } + + @Override + public void setRoot(N node) { + model.setRoot(node); + } + + @Override + public void insertNodeInto(N newChild, N parent, int index) { + parent.insert(newChild, index); + model.getModelSupport().fireChildAdded(getTreePath(parent), index, newChild); + } + + @Override + public void removeNodeFromParent(N node) { + N parent = node.getParent(); + int index = parent.getIndex(node); + if (index == -1) { + throw new IllegalArgumentException("Node " + node + " is not in tree"); + } + parent.remove(node); + +// It's not enougth to fire model support... +// model.getModelSupport().fireChildRemoved(path, index, node); + model.getModelSupport().fireTreeStructureChanged(getTreePath(parent)); + } + + @Override + public void reload(N node) { + model.getModelSupport().fireTreeStructureChanged(getTreePath(node)); + } + + @Override + public boolean canLoadChild(N node) { + return true; + } + + //-------------------------------------------------------------------------- + //-- Listeners notifications + //-------------------------------------------------------------------------- + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + model.valueForPathChanged(path, newValue); + } + + @Override + public void nodeStructureChanged(TreeNode node) { + model.nodeStructureChanged((NavTreeTableNode<?>) node); + } + + @Override + public void nodeChanged(TreeNode node) { + model.nodeChanged((NavTreeTableNode<?>) node); + } + + @Override + public void nodesChanged(TreeNode node, int[] childIndices) { + // changé par le node en lui meme + NavTreeTableNode<?> tableNode = (NavTreeTableNode<?>) node; + + // Extract children + Object[] children = getChildren(tableNode, childIndices); + + model.getModelSupport().fireChildrenChanged(getTreePath(tableNode), childIndices, children); + } + + @Override + public void nodesWereInserted(N parent, int[] indices) { + // Extract children + Object[] children = getChildren(parent, indices); + + model.getModelSupport().fireChildrenAdded(getTreePath(parent), indices, children); + } + + @Override + public void nodeWereInserted(N parentNode, int index, N node) { + + model.getModelSupport().fireChildAdded(getTreePath(parentNode), index, node); + } + + @Override + public void nodesWereRemoved(TreeNode node, int[] childIndices, + Object[] removedChildren) { + + model.getModelSupport().fireChildrenRemoved(getTreePath(node), + childIndices, + removedChildren); + } + + @Override + @SuppressWarnings({"unchecked"}) + public void notifyChildNodesInserted(N node) { + int count = node.getChildCount(); + if (count < 1) { + if (log.isDebugEnabled()) { + log.debug("Skip for leaf node : " + node); + } + return; + } + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", " + count + " child(s) inserted."); + } + int[] indices = new int[count]; + for (int i = 0; i < count; i++) { + indices[i] = i; + } + + nodesWereInserted(node, indices); + + // recurse notify on childs + for (Enumeration<? extends NavTreeTableNode<?>> childs = node.children(); + childs.hasMoreElements(); ) { + N child = (N) childs.nextElement(); + notifyChildNodesInserted(child); + } + } + + @Override + public void notifyNodeInserted(N node) { + + N parent = node.getParent(); + if (parent != null) { + int index = parent.getIndex(node); + if (index == -1) { + throw new IllegalArgumentException("Node " + node + " is not in tree"); + } + if (log.isDebugEnabled()) { + log.debug("Notify for node : " + node + ", for parent [" + parent + "] child " + index + " inserted."); + } + nodesWereInserted(parent, new int[]{index}); + notifyChildNodesInserted(node); + } + } + + //-------------------------------------------------------------------------- + //-- TreeModelListener provider + //-------------------------------------------------------------------------- + + + @Override + public void addTreeModelListener(TreeModelListener l) { + model.addTreeModelListener(l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) { + model.removeTreeModelListener(l); + } + + @Override + public TreeModelListener[] getTreeModelListeners() { + return model.getModelSupport().getTreeModelListeners(); + } + + @Override + @SuppressWarnings({"unchecked"}) + public <T extends EventListener> T[] getListeners(Class<T> listenerType) { + TreeModelListener[] treeModelListeners = getTreeModelListeners(); + List<TreeModelListener> result = new ArrayList<TreeModelListener>(); + for (TreeModelListener listener : treeModelListeners) { + if (listener.getClass().isAssignableFrom(listenerType)) { + result.add(listener); + } + } + return (T[]) result.toArray(); + } + + // Extract children + protected Object[] getChildren(NavTreeTableNode<?> tableNode, int[] childIndices) { + + int size = childIndices.length; + Object[] children = new Object[size]; + for (int i = 0; i < size; i++) { + int index = childIndices[i]; + NavTreeTableNode<?> child = tableNode.getChildAt(index); + children[i] = child; + } + return children; + } + + // Create tree path for node in param + protected TreePath getTreePath(TreeNode node) { + return new TreePath(getPathToRoot(node)); + } + +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java new file mode 100644 index 0000000..14f5331 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableHelper.java @@ -0,0 +1,183 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.treetable; + +import jaxx.runtime.swing.nav.NavHelper; +import jaxx.runtime.swing.nav.tree.AbstractNavTreeCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; + +import javax.swing.event.TreeSelectionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.util.ArrayList; +import java.util.List; + +/** + * The implementation of {@link NavHelper} based on a {@link JXTreeTable} component. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public class NavTreeTableHelper<N extends NavTreeTableNode<N>> extends NavHelper<NavTreeTableModel, JXTreeTable, NavTreeTableBridge<N>, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeTableHelper.class); + + public NavTreeTableHelper() { + super(new NavTreeTableBridge<N>()); + } + + @Override + public void scrollPathToVisible(TreePath path) { + getUI().scrollPathToVisible(path); + } + + @Override + public void setSelectionPath(TreePath path) { + getUI().getTreeSelectionModel().setSelectionPath(path); + } + + @Override + public void addSelectionPath(TreePath path) { + getUI().getTreeSelectionModel().addSelectionPath(path); + } + + @Override + public void addSelectionPaths(TreePath[] paths) { + getUI().getTreeSelectionModel().addSelectionPaths(paths); + } + + @Override + public void removeSelectionPath(TreePath path) { + getUI().getTreeSelectionModel().removeSelectionPath(path); + } + + @Override + public void removeSelectionPaths(TreePath[] paths) { + getUI().getTreeSelectionModel().removeSelectionPaths(paths); + } + + @Override + public TreeSelectionModel getSelectionModel() { + return getUI().getTreeSelectionModel(); + } + + @Override + public boolean isExpanded(TreePath pathToExpand) { + return getUI().isExpanded(pathToExpand); + } + + @Override + public void expandPath(TreePath pathToExpand) { + getUI().expandPath(pathToExpand); + } + + @Override + public AbstractNavTreeCellRenderer<NavTreeTableModel, N> getTreeCellRenderer() { + //FIXME Implements it if possible + return null; + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getSelectedNode() { + TreePath path = getSelectionModel().getSelectionPath(); + N node = null; + if (path != null) { + node = (N) path.getLastPathComponent(); + } + return node; + } + + @SuppressWarnings({"unchecked"}) + @Override + public List<N> getSelectedNodes() { + JXTreeTable tree = getUI(); + if (tree == null) { + return null; + } + TreePath[] paths = tree.getTreeSelectionModel().getSelectionPaths(); + List<N> nodes = new ArrayList<N>(); + if (paths != null) { + for (TreePath path : paths) { + if (path != null) { + nodes.add((N) path.getLastPathComponent()); + } + } + } + return nodes; + } + + @Override + public void setUI(JXTreeTable tree, + boolean addExpandTreeListener, + boolean addOneClickSelectionListener, + TreeSelectionListener listener, + TreeWillExpandListener willExpandListener) { + setUI(tree); + if (willExpandListener != null) { + tree.addTreeWillExpandListener(willExpandListener); + } + if (addExpandTreeListener) { + tree.addTreeWillExpandListener(expandListener); + } + if (listener != null) { + tree.addTreeSelectionListener(listener); + } + if (addOneClickSelectionListener) { + tree.addTreeSelectionListener(selectionListener); + } + } + + @Override + protected NavTreeTableModel createModel(N node, Object... extraArgs) { + + // must have a single extra params with delegate model + if (extraArgs.length != 1) { + throw new IllegalArgumentException("Should have exactly one extra parameter (delegate model)"); + } + if (!(extraArgs[0] instanceof NavTreeTableModel.MyDefaultTreeTableModel)) { + throw new IllegalArgumentException("extra parameter is not instance of " + NavTreeTableModel.MyDefaultTreeTableModel.class.getName()); + } + NavTreeTableModel.MyDefaultTreeTableModel delegate = (NavTreeTableModel.MyDefaultTreeTableModel) extraArgs[0]; + NavTreeTableBridge<N> bridge = getBridge(); + NavTreeTableModel model = bridge.getModel(); + if (model == null) { + model = new NavTreeTableModel(delegate); + bridge.setModel(model); +// model = new NavTreeTableBridge(tableModel); + bridge.addTreeModelListener(treeModelListener); +// ((NavTreeTableModel) model).addTreeModelListener(treeModelListener); + } + bridge.setRoot(node); + + // notify structure has changed + bridge.nodeStructureChanged(getRootNode()); + return model; + } +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java new file mode 100644 index 0000000..cd47f74 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableModel.java @@ -0,0 +1,215 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.treetable; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.tree.TreeModelSupport; +import org.jdesktop.swingx.treetable.DefaultTreeTableModel; +import org.jdesktop.swingx.treetable.TreeTableModel; +import org.jdesktop.swingx.treetable.TreeTableNode; + +import javax.swing.event.TreeModelListener; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +/** + * Model of the tree table used for a jaxx tree table api. + * + * @author sletellier <letellier@codelutin.com> + * @since 2.2 + */ +public class NavTreeTableModel implements TreeTableModel { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavTreeTableModel.class); + + /** + * Hack to acces to the modelSupport + * + * @author sletellier + * @since 2.2 + */ + public static abstract class MyDefaultTreeTableModel extends DefaultTreeTableModel { + + public TreeModelSupport getModelSupport() { + return modelSupport; + } + + public abstract String[] getColumnsNames(); + + } + + /** the delegate model */ + protected MyDefaultTreeTableModel delegate; + + public NavTreeTableModel(MyDefaultTreeTableModel delegate) { + this.delegate = delegate; + } + + @SuppressWarnings({"SuspiciousSystemArraycopy"}) + public TreeTableNode[] getPathToRoot(TreeTableNode aNode) { + if (aNode == null) { + return null; + } + TreeNode[] treeNodes = getDelegate().getPathToRoot(aNode); + NavTreeTableNode<?>[] result = new NavTreeTableNode[treeNodes.length]; + System.arraycopy(treeNodes, 0, result, 0, treeNodes.length); + return result; + } + + public void nodeStructureChanged(NavTreeTableNode<?> node) { + if (node != null) { + NavTreeTableNode<?> parentNode = node.getParent(); + if (parentNode == null || parentNode.isRoot()) { + getModelSupport().fireNewRoot(); + } else { + TreeNode[] treeNodes = getPathToRoot(parentNode); + if (treeNodes != null) { + getModelSupport().fireTreeStructureChanged(new TreePath(treeNodes)); + } + // FIXME : it's append.... +// else { +// log.error("[Node structure changed] Path to root is null !"); +// } + } + } else { + log.error("Node is null !"); + } + } + + public void nodeChanged(NavTreeTableNode<?> node) { + if (node != null) { + NavTreeTableNode<?> parent = node.getParent(); + TreeNode[] treeNodes = getPathToRoot(parent); + if (treeNodes != null) { + getModelSupport().fireChildChanged( + new TreePath(treeNodes), parent.getIndex(node), node); + // FIXME : it's append.... +// else { +// log.error("[Node changed] Path to root is null !"); +// } + } + } else { + log.error("Node is null !"); + } + } + + public MyDefaultTreeTableModel getDelegate() { + return delegate; + } + + public TreeModelSupport getModelSupport() { + return delegate.getModelSupport(); + } + + public String[] getColomnsNames() { + return delegate.getColumnsNames(); + } + + public void setRoot(TreeTableNode root) { + delegate.setRoot(root); + } + + //-------------------------------------------------------------------------- + //-- Overrides delegate methode + //-------------------------------------------------------------------------- + + @Override + public TreeTableNode getRoot() { + return delegate.getRoot(); + } + + @Override + public Object getChild(Object parent, int index) { + return delegate.getChild(parent, index); + } + + @Override + public int getChildCount(Object parent) { + return delegate.getChildCount(parent); + } + + @Override + public boolean isLeaf(Object node) { + return delegate.isLeaf(node); + } + + @Override + public void valueForPathChanged(TreePath path, Object newValue) { + delegate.valueForPathChanged(path, newValue); + } + + @Override + public int getIndexOfChild(Object parent, Object child) { + return delegate.getIndexOfChild(parent, child); + } + + @Override + public void addTreeModelListener(TreeModelListener l) { + delegate.addTreeModelListener(l); + } + + @Override + public void removeTreeModelListener(TreeModelListener l) { + delegate.removeTreeModelListener(l); + } + + @Override + public Class<?> getColumnClass(int i) { + return getDelegate().getColumnClass(i); + } + + @Override + public int getColumnCount() { + return getColomnsNames().length; + } + + @Override + public String getColumnName(int column) { + return getColomnsNames()[column]; + } + + @Override + public int getHierarchicalColumn() { + return getDelegate().getHierarchicalColumn(); + } + + @Override + public Object getValueAt(Object o, int i) { + return getDelegate().getValueAt(o, i); + } + + @Override + public boolean isCellEditable(Object o, int i) { + return getDelegate().isCellEditable(o, i); + } + + @Override + public void setValueAt(Object o, Object o1, int i) { + getDelegate().setValueAt(o, o1, i); + } + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java new file mode 100644 index 0000000..9aceb83 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNode.java @@ -0,0 +1,379 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.treetable; + +import jaxx.runtime.swing.nav.NavBridge; +import jaxx.runtime.swing.nav.NavDataProvider; +import jaxx.runtime.swing.nav.NavNode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.JXTreeTable; +import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; +import org.jdesktop.swingx.treetable.MutableTreeTableNode; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +/** + * Implementation of {@link NavNode} used to create in tree table + * This node extends {@link DefaultMutableTreeTableNode} used by + * {@link JXTreeTable} + * + * @author sletellier <letellier@codelutin.com> + * @since 2.2 + */ +public class NavTreeTableNode<N extends NavTreeTableNode<N>> extends DefaultMutableTreeTableNode implements NavNode<NavTreeTableModel, N> { + + /** Logger */ + static private final Log log = LogFactory.getLog(NavNode.class); + + private static final long serialVersionUID = 1L; + + /** Type of data associated with the node */ + protected final Class<?> internalClass; + + /** + * Optinal context to distinguish different nodes with same + * {@link #internalClass}. + */ + protected final String context; + + /** Id of the data associated with the node. */ + protected final String id; + + /** Flag to know when renderer should (re-)compute render of the node. */ + protected boolean dirty = true; + + /** Flag to know when the none static node was loaded. */ + protected boolean loaded; + + /** Optional child loador to lazy create childs of the node. */ + protected final NavTreeTableNodeChildLoador<?, ?, N> childLoador; + + protected NavTreeTableNode(String id) { + this(String.class, id, null, null); + } + + public NavTreeTableNode(Class<?> internalClass, + String id, + String context, + NavTreeTableNodeChildLoador<?, ?, N> childLoador) { + this.internalClass = internalClass; + this.id = id; + this.context = context; + this.childLoador = childLoador; + if (isStaticNode()) { + + // A static node is always full loaded + loaded = true; + } + if (log.isDebugEnabled()) { + log.debug("new node : " + this); + } + } + + @Override + public String getId() { + return id; + } + + @Override + public String getContext() { + return context; + } + + @Override + public Class<?> getInternalClass() { + return internalClass; + } + + @Override + public boolean isLoaded() { + return loaded; + } + + @Override + public boolean isDirty() { + return dirty; + } + + @Override + public boolean isStringNode() { + return String.class.equals(internalClass); + } + + @Override + public boolean isStaticNode() { + return childLoador == null; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N getContainerNode() { + if (isRoot()) { + // si on arrive sur le root, quelque chose ne va pas, + // on bloque par null, a defaut de declancher une exception + return null; + } + + if (isStringNode()) { + // on est sur un noeud de type String, donc on regarde sur le parent + return getParent().getContainerNode(); + } + + // cas final : sur un noeud de donnee + classe interne de donnee + return (N) this; + } + + public boolean isRoot() { + return getParent() == null; + } + + @Override + @SuppressWarnings({"unchecked"}) + public N findNodeById(String id, + NavBridge<NavTreeTableModel, N> model, + NavDataProvider provider) { + if (id == null) { + + // id null ? donc rien a faire + return null; + } + if (id.equals(getId())) { + + // on a trouve le bon noeud + return (N) this; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(model, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N node = enumeration.nextElement(); + N nodeById = node.findNodeById(id, model, provider); + if (nodeById != null) { + return nodeById; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public N getChild(String id, + NavBridge<NavTreeTableModel, N> bridge, + NavDataProvider provider) { + + if (id == null) { + + // id null ? donc rien a faire + return null; + } + + if (!isLoaded()) { + + // il faut charger les fils du noeud pour effectuer la recherche + populateChilds(bridge, provider); + } + + if (isLeaf()) { + + // au final le noeud est une feuille, donc ne convient pas + return null; + } + + // on recherche dans les fils + Enumeration<N> enumeration = children(); + while (enumeration.hasMoreElements()) { + N node = enumeration.nextElement(); + if (id.equals(node.getId())) { + return node; + } + } + + // aucun des noeud fils ne convient + return null; + } + + @Override + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + @Override + public boolean isLeaf() { + // there is two behaviours for the test : + // 1 - when the node is static, then can directly use his number of child + // to determine if node is a leaf (no child) + // 2 - when the node is dynamic, then ALWAYS says the node is NOT a leaf until + // it was loaded, otherwise the WillExpand listener will not load the childs... + // Once the node is loaded, use back the normal behaviour (count number of childs) + return isStaticNode() ? super.isLeaf() : isLoaded() && getChildCount() == 0; + } + + @Override + public Object getUserObject() { + return id; + } + + @Override + public String toString() { + return System.identityHashCode(this) + "-" + id; + } + + //-------------------------------------------------------------------------- + //-- Populate methods + //-------------------------------------------------------------------------- + + @Override + public void populateNode(NavBridge<NavTreeTableModel, N> model, + NavDataProvider provider, + boolean populateChilds) { + + // on indique que le noeud n'est plus propre + setDirty(true); + + if (populateChilds) { + + // chargement des fils + populateChilds(model, provider); + } + } + + @Override + @SuppressWarnings({"unchecked"}) + public void populateChilds(NavBridge<NavTreeTableModel, N> bridge, + NavDataProvider provider) { + if (isStaticNode()) { + + // noeud static, rien a faire + return; + } + + if (!bridge.canLoadChild((N) this)) { + + // can not load childs + if (log.isDebugEnabled()) { + log.debug("Will Skip populateChilds for node : " + this); + } + return; + } + + // chargement des noeuds fils du noeud courant + try { + if (log.isDebugEnabled()) { + log.debug("Will load childs for " + this); + } + childLoador.loadChilds((NavTreeTableBridge<N>) bridge, (N) this, provider); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } finally { + + // au final, on passe le noeud a l'état chargé + loaded = true; + } + } + + //-------------------------------------------------------------------------- + //-- Overrides to use generic type as return + //-------------------------------------------------------------------------- + + @SuppressWarnings({"unchecked"}) + @Override + public N getParent() { + return (N) super.getParent(); + } + + @SuppressWarnings({"unchecked"}) + @Override + public N getChildAt(int index) { + return (N) super.getChildAt(index); + } + + // It's a hack to prevent concurent modification exception, caused by + // children() of AbstractMutableTreeTableNode return Collections.enumeration + @SuppressWarnings({"unchecked"}) + @Override + public Enumeration<N> children() { + List<? extends MutableTreeTableNode> newChildrenList = + new ArrayList<MutableTreeTableNode>(children); + + return (Enumeration<N>) Collections.enumeration(newChildrenList); + } + + public void removeAllChildren() { + children.clear(); + } + + @Override + public void add(N node) { + super.add(node); + } + + @SuppressWarnings({"unchecked"}) + public N[] getPathToRoot(NavTreeTableNode aNode, int depth) { + + NavTreeTableNode[] retNodes; + + /* Check for null, in case someone passed in a null node, or + they passed in an element that isn't rooted at root. */ + if (aNode == null) { + if (depth == 0) { + return null; + } else { + retNodes = new NavTreeTableNode[depth]; + } + } else { + depth++; + retNodes = getPathToRoot(aNode.getParent(), depth); + retNodes[retNodes.length - depth] = aNode; + } + return (N[]) retNodes; + } + + @Override + public void remove(N node) { + super.remove(node); + } + + @Override + public void insert(N node, int position) { + super.insert(node, position); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java new file mode 100644 index 0000000..d4e46c3 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/NavTreeTableNodeChildLoador.java @@ -0,0 +1,42 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.nav.treetable; + +import jaxx.runtime.swing.nav.NavNodeChildLoador; + +/** + * Implementation for tree table of {@link NavNodeChildLoador} + * + * @author sletellier <letellier@codelutin.com> + * @since 2.2 + */ +public abstract class NavTreeTableNodeChildLoador<T, O, N extends NavTreeTableNode<N>> extends NavNodeChildLoador<T, O, NavTreeTableModel, NavTreeTableBridge<N>, N> { + + private static final long serialVersionUID = 1L; + + protected NavTreeTableNodeChildLoador(Class<O> beanType) { + super(beanType); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/package.html b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/package.html new file mode 100644 index 0000000..bb6c5dd --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/nav/treetable/package.html @@ -0,0 +1,45 @@ +<!-- + #%L + JAXX :: Runtime + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +package.html +<html> +<body> +<h1>JAXX - nav tree table implementation</h1> + +This package contains the implementation of nav api for the <b>JXTreeTable</b> + +<h2>NavTreeTableNode</h2> +An override of DefaultMutableTreeTableNode implement JaxxNode + +<h2>NavTreeTableChildLoador</h2> +Object to load childs of a tree table node using DataProvider. + +<h2>NavTreeTableHelper</h2> +Helper to manage a tree table using auto-loading nodes. + +<h2>JaxxTreeTableModel</h2> +Implementation of TreeTableModel used by JaxxDelegateTreeModel + +</body> +</html> diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/BooleanCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/BooleanCellRenderer.java new file mode 100644 index 0000000..2119803 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/BooleanCellRenderer.java @@ -0,0 +1,85 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Color; +import java.awt.Component; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class BooleanCellRenderer extends JPanel implements TableCellRenderer { + + private static final long serialVersionUID = 1L; + + protected TableCellRenderer defaultDelegate; + + protected JCheckBox checkBox; + + public BooleanCellRenderer(TableCellRenderer delegate) { + //super(new BorderLayout()); + this.checkBox = new JCheckBox(); + checkBox.setHorizontalAlignment(JLabel.CENTER); + checkBox.setBorderPainted(true); + this.defaultDelegate = delegate; + } + + public BooleanCellRenderer(TableCellRenderer delegate, Icon icon) { + //super(new BorderLayout()); + this.checkBox = new JCheckBox(icon); + checkBox.setHorizontalAlignment(JLabel.CENTER); + checkBox.setVerticalTextPosition(JLabel.TOP); + checkBox.setBorderPainted(true); + this.defaultDelegate = delegate; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + ((JComponent) defaultDelegate).setBackground(null); + JComponent render = (JComponent) defaultDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if (isSelected) { + setForeground(table.getSelectionForeground()); + setBackground(table.getSelectionBackground()); + } else { + setForeground(render.getForeground()); + setBackground(render.getBackground()); + //fixme make this works... and remove the test + if (row % 2 == 1) { + setBackground(Color.WHITE); + } + } + checkBox.setSelected((value != null && (Boolean) value)); + setBorder(render.getBorder()); + return checkBox; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java new file mode 100644 index 0000000..1988d36 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorListCellRenderer.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import org.nuiton.util.decorator.Decorator; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import java.awt.Component; + +/** + * A {@link ListCellRenderer} which compute text with the given {@link #decorator} + * and leave the hand to the {@link #delegate} to perform the visual renderer. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.7.2 + */ +public class DecoratorListCellRenderer implements ListCellRenderer { + + /** Delegate cell renderer */ + protected ListCellRenderer delegate; + + /** Decorator to produce text to render */ + protected Decorator<?> decorator; + + public DecoratorListCellRenderer(Decorator<?> decorator) { + this(new DefaultListCellRenderer(), decorator); + } + + public DecoratorListCellRenderer(ListCellRenderer delegate, + Decorator<?> decorator) { + this.delegate = delegate; + this.decorator = decorator; + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + if (value == null) { + value = " "; + } + if (!(value instanceof String) && decorator != null) { + value = decorator.toString(value); + } + return delegate.getListCellRendererComponent(list, + value, + index, + isSelected, + cellHasFocus + ); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java new file mode 100644 index 0000000..7b7c889 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderListCellRenderer.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import org.nuiton.util.decorator.Decorator; +import org.nuiton.util.decorator.DecoratorProvider; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import java.awt.Component; + +/** + * A {@link ListCellRenderer} which use decorators from the {@link #provider} to obtain the text to display. + * <p/> + * The interest of this renderer is to define a unique renderer for your application (put it in JAXXContext) + * and then use it simply :) + * <p/> + * User: chemit + * Date: 29 oct. 2009 + * Time: 03:00:53 + * + * @see DecoratorProvider + * @since 2.0.0 + */ +public class DecoratorProviderListCellRenderer implements ListCellRenderer { + + /** Delegate cell renderer */ + protected ListCellRenderer delegate; + + /** provider of decorators */ + protected DecoratorProvider provider; + + public DecoratorProviderListCellRenderer(DecoratorProvider provider) { + this(new DefaultListCellRenderer(), provider); + } + + public DecoratorProviderListCellRenderer(ListCellRenderer delegate, DecoratorProvider provider) { + this.delegate = delegate; + this.provider = provider; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value != null) { + Decorator<?> decorator = provider.getDecorator(value); + + if (decorator != null) { + value = decorator.toString(value); + } + } else { + value = " "; + } + return delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java new file mode 100644 index 0000000..cd4c64c --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorProviderTableCellRenderer.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import org.nuiton.util.decorator.Decorator; +import org.nuiton.util.decorator.DecoratorProvider; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * A {@link TableCellRenderer} which use decorators from the {@link #provider} to obtain the text to display. + * <p/> + * The interest of this renderer is to define a unique renderer for your application (put it in JAXXContext) + * and then use it simply :) + * <p/> + * User: chemit + * Date: 29 oct. 2009 + * Time: 03:00:53 + * + * @see DecoratorProvider + * @since 2.0.0 + */ +public class DecoratorProviderTableCellRenderer implements TableCellRenderer { + + /** Delegate cell renderer */ + protected TableCellRenderer delegate; + + /** provider of decorators */ + protected DecoratorProvider provider; + + public DecoratorProviderTableCellRenderer(DecoratorProvider provider) { + this(new DefaultTableCellRenderer(), provider); + } + + public DecoratorProviderTableCellRenderer(TableCellRenderer delegate, DecoratorProvider provider) { + this.delegate = delegate; + this.provider = provider; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { + if (value != null) { + Decorator<?> decorator = provider.getDecorator(value); + + if (decorator != null) { + value = decorator.toString(value); + } + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); + } +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java new file mode 100644 index 0000000..8656f21 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/DecoratorTableCellRenderer.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import org.nuiton.util.decorator.Decorator; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * A {@link TableCellRenderer} which compute text with the given {@link #decorator} + * and leave the hand to the {@link #delegate} to perform the visual renderer. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.7.2 (was previously {@code jaxx.runtime.swing.DecoratorTableCellRenderer}). + */ +public class DecoratorTableCellRenderer implements TableCellRenderer { + + /** Delegate cell renderer */ + protected TableCellRenderer delegate; + + /** Decorator to produce text to render */ + protected Decorator<?> decorator; + + public DecoratorTableCellRenderer(Decorator<?> decorator) { + this(new DefaultTableCellRenderer(), decorator); + } + + public DecoratorTableCellRenderer(TableCellRenderer delegate, Decorator<?> decorator) { + this.delegate = delegate; + this.decorator = decorator; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasfocus, int row, int column) { + if (value != null) { + value = decorator.toString(value); + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasfocus, row, column); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java new file mode 100644 index 0000000..329f8c0 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EmptyNumberTableCellRenderer.java @@ -0,0 +1,64 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; + +/** + * A {@link TableCellRenderer} which does not display numbers when they are + * equals to 0. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class EmptyNumberTableCellRenderer implements TableCellRenderer { + + protected final Integer ZERO = 0; + + protected final Float ZEROF = 0F; + + protected final Double ZEROD = 0D; + + private TableCellRenderer delegate; + + public EmptyNumberTableCellRenderer() { + this(new DefaultTableCellRenderer()); + } + + public EmptyNumberTableCellRenderer(TableCellRenderer delegate) { + this.delegate = delegate; + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (value == null || ZERO.equals(value) || ZEROF.equals(value) || ZEROD.equals(value)) { + value = null; + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java new file mode 100644 index 0000000..2adaefc --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/EnumTableCellRenderer.java @@ -0,0 +1,69 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.util.EnumSet; + +/** + * A {@link TableCellRenderer} which displays enum values from their ordinal value. + * + * @param <E> le type de l'énumération. + * @author tchemit <chemit@codelutin.com> + * @since 1.5 + */ +public class EnumTableCellRenderer<E extends Enum<E>> implements TableCellRenderer { + + private TableCellRenderer delegate; + + private EnumSet<E> enumValues; + + public EnumTableCellRenderer(TableCellRenderer delegate, Class<E> enumClass) { + this.delegate = delegate; + this.enumValues = EnumSet.allOf(enumClass); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + + if (value != null) { + //FIXME : should be also able to read it by name ? + Integer ordinal = Integer.valueOf(value + ""); + if (ordinal == -1) { + value = null; + } else { + for (E enumValue : enumValues) { + if (ordinal == enumValue.ordinal()) { + value = enumValue; + break; + } + } + } + } + return delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java new file mode 100644 index 0000000..106cb35 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/I18nTableCellRenderer.java @@ -0,0 +1,109 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import java.awt.Component; + +import static org.nuiton.i18n.I18n._; + +/** + * A simple TableCellRenderer using a delegate TableCellRenderer to render + * everything elese thant the text : the text is I18nalize. + * + * @author tchemit <chemit@codelutin.com> + */ +public class I18nTableCellRenderer implements TableCellRenderer { + + /** i18n keys of libelles to display */ + protected final String[] keys; + + /** i18n keys of toolTipTexts to display */ + protected final String[] tips; + + /** the delegate cell renderer */ + protected TableCellRenderer delegate; + + public I18nTableCellRenderer(TableCellRenderer delegate, + String... keysAndTips) { + this.delegate = delegate; + if (keysAndTips.length == 0) { + throw new IllegalArgumentException( + "can not have empty keysAndTips parameters (means no " + + "column ?)"); + } + if (keysAndTips.length % 2 == 1) { + throw new IllegalArgumentException( + "must have some couple (text,tooltTipText), but had an" + + " even number of data in keysAndTips parameter"); + } + int size = keysAndTips.length / 2; + keys = new String[size]; + tips = new String[size]; + for (int i = 0; i < size; i++) { + keys[i] = keysAndTips[2 * i]; + tips[i] = keysAndTips[2 * i + 1]; + } + } + + @Override + 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); + } + TableColumn col = table.getColumn(table.getColumnName(column)); + int index = col.getModelIndex(); + value = _(keys[index]); + JComponent rendererComponent = (JComponent) + delegate.getTableCellRendererComponent( + table, + value, + isSelected, + hasfocus, + row, + column + ); + rendererComponent.setToolTipText(_(tips[index])); + return rendererComponent; + } + + public String[] getKeys() { + return keys; + } + + public String[] getTips() { + return tips; + } + +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java new file mode 100644 index 0000000..6305bd6 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/LocaleListCellRenderer.java @@ -0,0 +1,152 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JList; +import java.awt.Component; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/** @author tchemit <chemit@codelutin.com> */ +public class LocaleListCellRenderer extends DefaultListCellRenderer { + + public static final Log log = LogFactory.getLog(LocaleListCellRenderer.class); + + private static final long serialVersionUID = 1L; + + protected final Map<Locale, Icon> cache = new HashMap<Locale, Icon>(); + + protected boolean showIcon; + + protected boolean showText; + + public LocaleListCellRenderer() { + this(true, true); + } + + public LocaleListCellRenderer(boolean showIcon, boolean showText) { + this.showIcon = showIcon; + this.showText = showText; + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + Locale locale = (Locale) value; + if (locale != null) { + Icon icon = getIcon(locale); + comp.setIcon(icon); + } + String text = getText(locale); + String tip = getToolTipText(locale); + comp.setText(text); + comp.setToolTipText(tip); + return comp; + } + + public String getText(Locale locale) { + String text = null; + if (showText) { + text = getSafeText(locale); + } + return text; + } + + public Icon getIcon(Locale locale) { + if (!showIcon) { + return null; + } + synchronized (cache) { + Icon icon = getSafeIcon(locale); + return icon; + } + } + + public String getToolTipText(Locale locale) { + String tip = locale.getDisplayName(Locale.getDefault()); + return tip; + } + + public boolean isShowText() { + return showText; + } + + public boolean isShowIcon() { + return showIcon; + } + + public void setShowIcon(boolean showIcon) { + boolean old = this.showIcon; + this.showIcon = showIcon; + firePropertyChange("showIcon", old, showIcon); + } + + public void setShowText(boolean showText) { + boolean old = this.showText; + this.showText = showText; + firePropertyChange("showText", old, showText); + } + + public String getSafeText(Locale locale) { + String text = locale.getDisplayName(Locale.getDefault()); + return text; + } + + public synchronized Icon getSafeIcon(Locale locale) { + Icon icon = cache.get(locale); + if (icon != null) { + return icon; + } + + icon = SwingUtil.getUIManagerActionIcon("i18n-" + locale.toString()); + + if (icon == null) { + log.warn("could not find icon action.i18n-" + locale.toString()); + if (locale.getCountry() != null) { + icon = SwingUtil.getUIManagerActionIcon("i18n-" + locale.getCountry().toLowerCase()); + if (icon == null) { + log.warn("could not find icon action.i18n-" + locale.getCountry().toLowerCase()); + + icon = SwingUtil.createActionIcon("i18n-" + locale.getCountry().toLowerCase()); + if (icon == null) { + log.warn("could not find icon action.i18n-" + locale.getCountry().toLowerCase()); + } + } + + } + } + + cache.put(locale, icon); + return icon; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java new file mode 100644 index 0000000..655dc4f --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorListCellRenderer.java @@ -0,0 +1,85 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import org.nuiton.util.decorator.Decorator; +import org.nuiton.util.decorator.JXPathDecorator; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link ListCellRenderer} which compute text with the matching decorator + * from {@link #decorators} and leave the hand to the {@link #delegate} to + * perform the visual renderer. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class MultiDecoratorListCellRenderer implements ListCellRenderer { + + /** Delegate cell renderer */ + protected ListCellRenderer delegate; + + /** accepted types */ + protected List<Class<?>> types; + + /** decorators for accepted types */ + protected Decorator<?>[] decorators; + + public MultiDecoratorListCellRenderer(ListCellRenderer delegate, JXPathDecorator<?>... decorator) { + this.delegate = delegate; + this.types = new ArrayList<Class<?>>(); + List<Decorator<?>> tmp = new ArrayList<Decorator<?>>(); + for (JXPathDecorator<?> d : decorator) { + if (types.contains(d.getInternalClass())) { + throw new IllegalArgumentException("can not have twice a decorator of type " + d.getInternalClass()); + } + types.add(d.getInternalClass()); + tmp.add(d); + } + decorators = tmp.toArray(new Decorator<?>[tmp.size()]); + } + + public MultiDecoratorListCellRenderer(JXPathDecorator<?>... decorator) { + this(new DefaultListCellRenderer(), decorator); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + if (value != null) { + int i = types.indexOf(value.getClass()); + if (i != -1) { + Decorator<?> d = decorators[i]; + value = d.toString(value); + } + } + return delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java new file mode 100644 index 0000000..91c5f1f --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/renderer/MultiDecoratorTableCelleRenderer.java @@ -0,0 +1,100 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import org.nuiton.util.decorator.Decorator; +import org.nuiton.util.decorator.JXPathDecorator; + +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +/** + * A {@link TableCellRenderer} which compute text with the matching decorator + * from {@link #decorators} based on the type of value and leave the hand to + * the {@link #delegate} to perform the visual renderer. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class MultiDecoratorTableCelleRenderer implements TableCellRenderer { + + /** Delegate cell renderer */ + protected TableCellRenderer delegate; + + /** accepted types */ + protected List<Class<?>> types; + + /** decorators for accepted types */ + protected Decorator<?>[] decorators; + + public MultiDecoratorTableCelleRenderer(JXPathDecorator<?>... decorator) { + this(new DefaultTableCellRenderer(), decorator); + } + + public MultiDecoratorTableCelleRenderer(TableCellRenderer delegate, + JXPathDecorator<?>... decorator) { + this.delegate = delegate; + + types = new ArrayList<Class<?>>(); + List<Decorator<?>> tmp = new ArrayList<Decorator<?>>(); + for (JXPathDecorator<?> d : decorator) { + if (types.contains(d.getType())) { + throw new IllegalArgumentException( + "can not have twice a decorator of type " + + d.getType()); + } + types.add(d.getType()); + tmp.add(d); + } + decorators = tmp.toArray(new Decorator<?>[tmp.size()]); + } + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasfocus, + int row, + int column) { + if (value != null) { + int i = types.indexOf(value.getClass()); + if (i != -1) { + Decorator<?> d = decorators[i]; + value = d.toString(value); + } + } + return delegate.getTableCellRendererComponent(table, + value, + isSelected, + hasfocus, + row, + column + ); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/BusyChangeListener.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/BusyChangeListener.java new file mode 100644 index 0000000..87087ae --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/BusyChangeListener.java @@ -0,0 +1,116 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard; + +import jaxx.runtime.swing.BlockingLayerUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Component; +import java.awt.Cursor; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * To listen the busy state of a {@link WizardModel}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public class BusyChangeListener implements PropertyChangeListener { + + /** Logger */ + private static final Log log = LogFactory.getLog(BusyChangeListener.class); + + protected Cursor busyCursor; + + protected Cursor defaultCursor; + + protected final Component ui; + + protected BlockingLayerUI blockingUI; + + public BusyChangeListener(Component ui) { + this.ui = ui; + } + + public Component getUi() { + return ui; + } + + public BlockingLayerUI getBlockingUI() { + return blockingUI; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Boolean value = (Boolean) evt.getNewValue(); + if (log.isDebugEnabled()) { + log.debug("busy state changed to " + value); + } + if (value != null && value) { + setBusy(ui); + + } else { + setUnBusy(ui); + } + } + + public void setBlockingUI(BlockingLayerUI blockingUI) { + this.blockingUI = blockingUI; + } + + protected void setBusy(Component ui) { + if (ui != null) { + ui.setCursor(getBusyCursor()); + } + if (blockingUI != null) { + blockingUI.setBlock(true); + } + } + + protected void setUnBusy(Component ui) { + if (ui != null) { + ui.setCursor(getDefaultCursor()); + } + if (blockingUI != null) { + blockingUI.setBlock(false); + } + } + + protected Cursor getBusyCursor() { + if (busyCursor == null) { + busyCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + } + return busyCursor; + } + + protected Cursor getDefaultCursor() { + if (defaultCursor == null) { + defaultCursor = Cursor.getDefaultCursor(); + } + return defaultCursor; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java new file mode 100644 index 0000000..18a4cd1 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java @@ -0,0 +1,312 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard; + +import jaxx.runtime.JAXXUtil; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Un modèle de wizard. + * <p/> + * <p/> + * <b>Note:</b> le type des étapes doit être uné énumération qui implante {@link + * WizardStep}. + * + * @param <E> le type des étapes. + * @author tchemit <chemit@codelutin.com> + * @see WizardStep + * @since 1.3 + */ +public abstract class WizardModel<E extends WizardStep> { + + public static final String STEPS_PROPERTY_NAME = "steps"; + + public static final String STEP_PROPERTY_NAME = "step"; + + public static final String PREVIOUS_STEP_PROPERTY_NAME = "previousStep"; + + public static final String NEXT_STEP_PROPERTY_NAME = "nextStep"; + + public static final String VALID_STEP_PROPERTY_NAME = "validStep"; + + public static final String BUSY_PROPERTY_NAME = "busy"; + + /** le type d'une etape du model (doit etre une enumeration) */ + protected final Class<E> stepClass; + + /** Toutes les étapes à passer */ + protected List<E> steps; + + /** les etapes a exclure */ + protected List<E> excludeSteps; + + /** L'étape courante */ + protected E step; + + /** drapeau pour valider l'état de l'étape courante */ + protected boolean validStep; + + /** un drapeau pour savoir si le modèle est occupé. */ + private boolean busy; + + /** + * drapeau lorsque le modele effectue des operations de transformation de + * modele mais que les écouteurs ne devraient pas tenir compte des + * modifications + */ + protected boolean valueAdjusting; + + /** pour propager les changements dans le modèle vers l'ui */ + protected PropertyChangeSupport pcs; + + public WizardModel(Class<E> stepClass, E... steps) { + if (!Enum.class.isAssignableFrom(stepClass)) { + throw new IllegalArgumentException("stepClass must be an" + + " Enumeration but was " + stepClass.getName()); + } + this.stepClass = stepClass; + pcs = new PropertyChangeSupport(this); + this.steps = new ArrayList<E>(); + if (steps.length > 0) { + setSteps(steps); + } + } + + public void start() { + if (steps.isEmpty()) { + throw new IllegalStateException("can not start, no step found"); + } + step = null; + E startStep = steps.get(0); + setStep(startStep); + } + + public void destroy() { + // suppression de tous les listeners + JAXXUtil.destroy(pcs); + } + + public void gotoNextStep() { + E nextStep = getNextStep(); + if (nextStep == null) { + throw new IllegalStateException("no next step to go"); + } + setStep(nextStep); + } + + public void gotoPreviousStep() { + E previousStep = getPreviousStep(); + if (previousStep == null) { + throw new IllegalStateException("no previous step to go"); + } + setStep(previousStep); + } + + public void gotoStep(E e) { + if (e == null) { + throw new NullPointerException("step can not be null"); + } + if (!steps.contains(e)) { + throw new IllegalStateException("step " + e.toString() + + " is not in universe of steps (" + steps + ')'); + } + setBusy(true); + try { + setStep(e); + } finally { + setBusy(false); + } + } + + public E getStep() { + return step; + } + + public int getStepIndex(E s) { + int index = steps.indexOf(s); + return index; + } + + public boolean isValidStep() { + return validStep; + } + + public E getPreviousStep() { + E e = getPreviousStep(step); + return e; + } + + public E getPreviousStep(E step) { + int index = getStepIndex(step); + if (index < 1) { + // si pas de step ou sur premier step + return null; + } + return steps.get(index - 1); + } + + public E getNextStep(E step) { + int index = getStepIndex(step); + if (index < 1) { + // si pas de step ou sur premier step + return null; + } + return steps.get(index - 1); + } + + public E getNextStep() { + int index = getStepIndex(step); + if (index == -1 || index == steps.size() - 1) { + // si pas de step positionne ou dernier etape + return null; + } + return steps.get(index + 1); + } + + public List<E> getSteps() { + return steps; + } + + public boolean containsStep(E step) { + return getSteps().contains(step); + } + + public boolean isValueAdjusting() { + return valueAdjusting; + } + + public boolean isBusy() { + return busy; + } + + public void setBusy(boolean busy) { + boolean oldValue = this.busy; + this.busy = busy; + firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy); + } + + /** + * Change l'univers des etapes. + * <p/> + * Note: on presume ici que l'étape courante est toujours la meme. + * + * @param steps le nouvel univers des etapes + */ + public void setSteps(E... steps) { + List<E> oldValue = this.steps; + this.steps = Collections.unmodifiableList(Arrays.asList(steps)); + firePropertyChange(STEPS_PROPERTY_NAME, oldValue, this.steps); + // la propriete nextStep peut avoir changee + firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep()); + } + + public void setValueAdjusting(boolean valueAdjusting) { + this.valueAdjusting = valueAdjusting; + } + + public void setExcludeSteps(List<E> excludeSteps) { + this.excludeSteps = excludeSteps; + } + + public boolean validate(E s) { + return step != null; + } + + 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 void removePropertyChangeListeners() { + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } + + public void validate() { + if (step == null) { + // pas de validation quand aucune etape n'est sélectionnée + return; + } + boolean validate = validate(step); + validStep = validate; + // toujours forcer la propagation + firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep); + } + + public abstract void updateUniverse(); + + public Class<E> getStepClass() { + return stepClass; + } + + protected void setStep(E step) { + E oldValue = this.step; + this.step = step; + firePropertyChange(STEP_PROPERTY_NAME, oldValue, step); + // la propriete nextStep peut avoir changee + firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep()); + // la propriete previousStep peut avoir changee + firePropertyChange(PREVIOUS_STEP_PROPERTY_NAME, null, getPreviousStep()); + validate(); + } + + protected void firePropertyChange(String propertyName, Object oldValue, + Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected void firePropertyChange(String propertyName, Object newValue) { + pcs.firePropertyChange(propertyName, null, newValue); + } + + protected void fireIndexedPropertyChange(String propertyName, int index, + Object oldValue, Object newValue) { + pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java new file mode 100644 index 0000000..e712d55 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard; + +import java.io.Serializable; + +/** + * le contrat d'une étape d'un wizard. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public interface WizardStep extends Serializable { + + String name(); + + int ordinal(); + + String getLabel(); + + String getDescription(); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java new file mode 100644 index 0000000..78e1b74 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java @@ -0,0 +1,38 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard; + +/** + * Le contrat d'une ui d'étape. + * + * @param <E> le type d'étape + * @param <M> le type de modèle + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public interface WizardStepUI<E extends WizardStep, M extends WizardModel<E>> { + + E getStep(); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java new file mode 100644 index 0000000..47a2eb9 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java @@ -0,0 +1,84 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard; + +import javax.swing.JTabbedPane; + +/** + * Contrat a respecter pour une ui de wizard. + * + * @param <E> le type d'etape + * @param <M> le type de model + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public interface WizardUI<E extends WizardStep, M extends WizardModel<E>> { + + /** @return le modèle de wizard */ + M getModel(); + + /** @return l'étape courante */ + E getSelectedStep(); + + /** @return l'ui de l'étape courante */ + WizardStepUI<E, M> getSelectedStepUI(); + + /** + * @param step l'étape donnée + * @return l'ui de l'étape donnée + */ + WizardStepUI<E, M> getStepUI(E step); + + /** + * @param stepIndex la position de l'étape + * @return l'ui de l'étape donée + */ + WizardStepUI<E, M> getStepUI(int stepIndex); + + /** démarre le wizard */ + void start(); + + /** + * //TODO il faudrait supprimer cette méthode + * + * @return le conteneur d'ui d'étapes + */ + JTabbedPane getTabs(); + + /** + * Méthode invoquée lorsque l'univers des étapes a été modifié dans le + * modèle. + * + * @param steps les nouvelles étapes + */ + void onStepsChanged(E[] steps); + + /** + * Méthode invoquée lorsque l'étape courante a changé dans le modèle. + * + * @param newStep la nouvelle étape courante + */ + void onStepChanged(E newStep); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java new file mode 100644 index 0000000..6c2052e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java @@ -0,0 +1,255 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard; + +import jaxx.runtime.JAXXContext; +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.context.JAXXContextEntryDef; +import jaxx.runtime.context.JAXXInitialContext; + +import javax.swing.ImageIcon; +import java.awt.Window; + +/** + * Une classe pour lancer une ui de wizard. + * + * @param <E> le type des etapes + * @param <M> le type de modele + * @param <UI> le type d'ui + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public abstract class WizardUILancher<E extends WizardStep, M extends WizardModel<E>, UI extends WizardUI<E, M>> { + + /** the jaxx context entry to store the apply action */ + public static final JAXXContextEntryDef<Runnable> APPLY_DEF = + JAXXUtil.newContextEntryDef("apply", Runnable.class); + + /** the jaxx context entry to store the cancel action */ + public static final JAXXContextEntryDef<Runnable> CANCEL_DEF = + JAXXUtil.newContextEntryDef("cancel", Runnable.class); + + public static <M extends WizardModel<?>> JAXXContextEntryDef<M> newModelEntry(Class<M> modelType) { + return JAXXUtil.newContextEntryDef("incoming", modelType); + } + + protected UI ui; + + public WizardUILancher(JAXXContext context, + Class<UI> uiClass, + Class<M> modelClass, + String title, + String tip, + ImageIcon icon) { + this(context, uiClass, modelClass, null, title, tip, icon); + } + + public WizardUILancher(JAXXContext context, + Class<UI> uiClass, + Class<M> modelClass, + M model, + String title, + String tip, + ImageIcon icon) { + try { + ui = createUI(context, + uiClass, + modelClass, + model, + title, + tip, + icon + ); + } catch (Exception ex) { + throw new RuntimeException( + "could not instanciate launcher for reason " + + ex.getMessage(), ex); + } + } + + public WizardUILancher(JAXXContext context, + Window mainUI, + Class<UI> uiClass, + Class<M> modelClass, + M model) { + try { + ui = createUI(context, + mainUI, + uiClass, + modelClass, + model + ); + } catch (Exception ex) { + throw new RuntimeException( + "could not instanciate launcher for reason " + + ex.getMessage(), ex); + } + } + + public WizardUILancher(JAXXContext context, + Window mainUI, + Class<UI> uiClass, + Class<M> modelClass) { + this(context, mainUI, uiClass, modelClass, null); + } + + public void start() { + init(ui); + start(ui); + } + + protected void start(UI ui) { + ui.start(); + } + + public <T> T getContextValue(Class<T> clazz, String name) { + if (ui == null) { + throw new NullPointerException("ui can not be null"); + } + if (!(ui instanceof JAXXObject)) { + throw new ClassCastException("ui can not be casted to JAXXObject "); + } + + return ((JAXXObject) ui).getContextValue(clazz, name); + } + + public <T> T getContextValue(Class<T> clazz) { + return getContextValue(clazz, null); + } + + protected void init(UI ui) { + } + + protected void doAction(UI ui) { + } + + protected void doCancel(UI ui) { + } + + protected void doClose(UI ui, boolean wasCanceld) { + } + + protected UI createUI(JAXXContext context, + Window mainUI, + Class<UI> uiClass, + Class<M> modelClass, + M model) throws Exception { + JAXXInitialContext uiContext = new JAXXInitialContext(); + uiContext.add(mainUI == null ? context : mainUI); + // parent context model + uiContext.add(modelClass.newInstance()); + if (model != null) { + uiContext.add(newModelEntry(modelClass), model); + } + // apply action + uiContext.add(APPLY_DEF, new Runnable() { + + @Override + public void run() { + try { + doAction(ui); + } finally { + doClose(ui, false); + } + } + }); + // cancel action + uiContext.add(CANCEL_DEF, new Runnable() { + + @Override + public void run() { + try { + doCancel(ui); + } finally { + doClose(ui, true); + } + } + }); + + // instanciate ui + + UI newUI = JAXXUtil.invokeConstructor( + uiClass, + new Class[]{Window.class, JAXXContext.class}, + mainUI, uiContext + ); + return newUI; + } + + protected UI createUI(JAXXContext context, + Class<UI> uiClass, + Class<M> modelClass, + M model, + String title, + String tip, + ImageIcon icon) throws Exception { + JAXXInitialContext uiContext = new JAXXInitialContext(); + uiContext.add(context); + // parent context model + uiContext.add(modelClass.newInstance()); + if (model != null) { + uiContext.add(newModelEntry(modelClass), model); + } + // apply action + uiContext.add(APPLY_DEF, new Runnable() { + + @Override + public void run() { + try { + doAction(ui); + } finally { + doClose(ui, false); + } + } + }); + + // cancel action + uiContext.add(CANCEL_DEF, new Runnable() { + + @Override + public void run() { + try { + doCancel(ui); + } finally { + doClose(ui, true); + } + } + }); + + // instanciate ui + UI newUI = JAXXUtil.invokeConstructor( + uiClass, + new Class[]{ + JAXXContext.class, + String.class, + String.class, + ImageIcon.class + }, + uiContext, title, tip, icon + ); + return newUI; + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java new file mode 100644 index 0000000..146ad5e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java @@ -0,0 +1,194 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JTabbedPane; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Array; +import java.util.List; + +import static org.nuiton.i18n.I18n._; + +/** + * Classe de méthodes utiles sur les wizard. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public class WizardUtil { + + /** Logger */ + static private Log log = LogFactory.getLog(WizardUI.class); + + protected WizardUtil() { + } + +// public static boolean acceptStates(WizardState state, WizardState... accepted) { +// for (WizardState s : accepted) { +// if (s == state) { +// return true; +// } +// } +// return false; +// } +// +// public static boolean rejectStates(WizardState state, WizardState... rejected) { +// for (WizardState s : rejected) { +// if (s == state) { +// return false; +// } +// } +// return true; +// } + + public static void addDebugLogListener(final Log log, WizardModel<?> model) { + if (log.isDebugEnabled()) { + model.addPropertyChangeListener(new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + log.debug(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">"); + } + }); + } + } + + public static void addTraceLogListener(final Log log, WizardModel<?> model) { + if (log.isTraceEnabled()) { + model.addPropertyChangeListener(new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + log.trace(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">"); + } + }); + } + } + + public static <E extends WizardStep, M extends WizardModel<E>> void installWizardUIListeners(final WizardUI<E, M> ui) { + ui.getModel().addPropertyChangeListener(new PropertyChangeListener() { + + @Override + @SuppressWarnings("unchecked") + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); +// if (WizardExtModel.WAS_STARTED_PROPERTY_NAME.equals(propertyName)) { +// ui.onWasStarted(); +// return; +// } + if (WizardModel.STEPS_PROPERTY_NAME.equals(propertyName)) { + List<E> steps = (List<E>) evt.getNewValue(); + ui.onStepsChanged( + steps.toArray((E[]) Array.newInstance( + ui.getModel().stepClass, steps.size())) + ); + return; + } + if (WizardModel.STEP_PROPERTY_NAME.equals(propertyName)) { + ui.onStepChanged((E) evt.getNewValue()); +// return; + } + /*if (WizardModel.VALID_STEP_PROPERTY_NAME.equals(propertyName)) { + Boolean value = (Boolean) evt.getNewValue(); + if (value == null || !value) { + ui.onModelStateChanged(WizardState.NEED_FIX); + } else { + ui.onModelStateChanged(WizardState.PENDING); + } + return; + } + if (WizardExtModel.MODEL_STATE_PROPERTY_NAME.equals(propertyName)) { + //TODO should be unicast : only for good stepUI ? + ui.onModelStateChanged((WizardState) evt.getNewValue()); + return; + } + if (WizardExtModel.STEP_STATE_PROPERTY_NAME.equals(propertyName)) { + IndexedPropertyChangeEvent e = (IndexedPropertyChangeEvent) evt; + int stepIndex = e.getIndex(); + E step = ui.getModel().getSteps().get(stepIndex); + ui.onOperationStateChanged(step, (WizardState) evt.getNewValue()); + return; + }*/ + } + }); + } + + /** + * Ajoute un listener sur le modele pour gere la politique d'affichage des + * onglets. + * <p/> + * Dans cette implantation, les onglets sont ouverts jusqu'a l'etape + * courante. Lorsque l'on revient en arrière, les onglets d'etapes + * superieurs sont fermes. + * + * @param <E> le type d'un etape de l'assistant + * @param <M> le type du modele de l'assistant + * @param ui l'ui de l'assitant + * @since 1.7.1 + */ + public static <E extends WizardStep, M extends WizardModel<E>> void addTabsDisplayUntilStepListener(final WizardUI<E, M> ui) { + // on écoute les changements d'étapes + ui.getModel().addPropertyChangeListener(WizardModel.STEP_PROPERTY_NAME, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + M model = (M) evt.getSource(); + E oldStep = (E) evt.getOldValue(); + E newStep = (E) evt.getNewValue(); + log.debug("step has changed <old:" + oldStep + ", new:" + newStep + ">"); + int oldStepIndex = oldStep == null ? -1 : model.getStepIndex(oldStep); + int newStepIndex = model.getStepIndex(newStep); + JTabbedPane tabs = ui.getTabs(); + if (oldStepIndex + 1 == newStepIndex) { + // creation d'un nouvel onglet + WizardStepUI<E, M> c = ui.getStepUI(newStep); + String title = _(newStep.getLabel()); + String tip = _(newStep.getDescription()); + tabs.addTab(title, null, (Component) c, tip); + // selection du nouvel onglet + int index = tabs.indexOfComponent((Component) c); + if (index > -1) { + tabs.setSelectedIndex(index); + } + } else if (oldStepIndex > newStepIndex) { + // il s'agit d'un retour en arrière + // on supprime tous les onglets obsoletes + int index = newStepIndex + 1; + while (tabs.getTabCount() > index) { + log.trace("remove tab : " + index); + tabs.remove(index); + } + } else { + throw new IllegalStateException("can not go from " + oldStep + " to " + newStep); + } + } + }); + } +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtModel.java new file mode 100644 index 0000000..49f9e68 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtModel.java @@ -0,0 +1,438 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard.ext; + +import jaxx.runtime.swing.wizard.WizardModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Un modèle de wizard avec des opérations. + * + * @param <E> le type des étapes. + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public abstract class WizardExtModel<E extends WizardExtStep> extends WizardModel<E> { + + /** Logger */ + private static final Log log = LogFactory.getLog(WizardExtModel.class); + + public static final String OPERATIONS_PROPERTY_NAME = "operations"; + + public static final String STEP_STATE_PROPERTY_NAME = "stepState"; + + public static final String MODEL_STATE_PROPERTY_NAME = "modelState"; + + public static final String WAS_STARTED_PROPERTY_NAME = "wasStarted"; + + /** La liste des opérations à effectuer */ + protected Set<E> operations; + + /** le dictionnaire des modèles d'opération */ + protected final Map<E, WizardExtStepModel<E>> models; + + /** Pour conserver les états des opérations */ + protected Map<E, WizardState> stepStates; + + /** L'état générale du modèle */ + protected WizardState modelState; + + /** un drapeau pour savoir siune opération a été lancée */ + protected boolean wasStarted; + + @SuppressWarnings("unchecked") + public <T extends Enum<T>> WizardExtModel(Class<E> stepClass, E... steps) { + super(stepClass, steps); + Class<T> k = (Class<T>) stepClass; + stepStates = new EnumMap(k); + operations = (Set<E>) EnumSet.noneOf(k); + models = (Map<E, WizardExtStepModel<E>>) new EnumMap(k); + } + + public Set<E> getOperations() { + return operations; + } + + public WizardState getModelState() { + return modelState; + } + + public boolean isWasStarted() { + return wasStarted; + } + + public boolean containsOperation(E step) { + return getOperations().contains(step); + } + + @SuppressWarnings("unchecked") + public E getOperation() { + return getStep() != null && getStep().isOperation() ? getStep() : null; + } + + public WizardState getStepState() { + E operation = getOperation(); + return getStepState(operation); + } + + public WizardState getStepState(E step) { + return stepStates.get(step); + } + + public void setStepState(WizardState newState) { + E operation = getOperation(); + setStepState(operation, newState); + } + + public void setStepState(E step, WizardState newState) { + WizardState oldValue = getStepState(step); + stepStates.put(step, newState); + if (valueAdjusting) { + return; + } + fireIndexedPropertyChange(STEP_STATE_PROPERTY_NAME, getSteps().indexOf(step), oldValue, newState); + updateModelState(step, newState); + validate(); + } + + public boolean[] getAccessibleSteps() { + if (log.isDebugEnabled()) { + log.debug("compute with steps " + getSteps()); + } + boolean[] result = new boolean[getSteps().size()]; + int index = getSteps().indexOf(getStep()); + if (index != -1) { + + for (int i = 0, j = steps.size(); i < j; i++) { + if (i <= index) { + // tous les onglets inferieur ou egal au courant sont accessibles + result[i] = true; + continue; + } + // les onglets au dela de l'onglet sélectionné sont accessibles + // uniquement si l'onglet precedent est accessible, valide et son etat est a SUCCESSED + E previousStep = steps.get(i - 1); + result[i] = modelState == WizardState.SUCCESSED || + result[i - 1] && + validate(previousStep) && + (!previousStep.isOperation() || getStepState(previousStep) == WizardState.SUCCESSED); + } + } + if (log.isDebugEnabled()) { + log.debug("accessibles steps -------- " + Arrays.toString(result)); + } + return result; + } + + @Override + public void start() { +// super.start(); + + if (steps.isEmpty()) { + throw new IllegalStateException("can not start, no step found"); + } + + // update universe of steps and actions + updateUniverse(); + + // set first step + step = null; + E startStep = steps.get(0); + setStep(startStep); + + // model is ready + setModelState(WizardState.PENDING); + + validate(); + } + + public void cancel() { + + for (E op : operations) { + if (getStepState(op) == WizardState.PENDING) { + // on annule l'opération à venir + setStepState(op, WizardState.CANCELED); + } + } + setModelState(WizardState.CANCELED); + } + + public WizardExtModel<E> addOperation(E operation) { + if (operations.contains(operation)) { + + // skip add + return this; + } + + log.info("Add operation " + operation); + operations.add(operation); + // mis a jour de l'univers des etapes et operations + updateUniverse(); + // validation + validate(); + return this; + } + + public void removeOperation(E operation) { + if (!operations.contains(operation)) { + + // skip remove + return; + } + operations.remove(operation); + + // mis a jour de l'univers des etapes et operations + updateUniverse(); + // validation + validate(); + } + + @Override + public void setSteps(E... steps) { + super.setSteps(steps); + if (valueAdjusting) { + return; + } + // on force la propagation de la nouvelle liste + firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); + } + + public WizardExtStepModel<E> getStepModel(E operation) { + if (operation == null) { + return null; + } + if (!operation.isOperation()) { + throw new IllegalStateException("step [" + operation + "] is not an operation."); + } + return models.get(operation); + } + + public void updateStepStates(List<E> steps) { + int index = 0; + for (E e : steps) { + fireIndexedPropertyChange(STEP_STATE_PROPERTY_NAME, index++, null, getStepState(e)); + } + firePropertyChange(MODEL_STATE_PROPERTY_NAME, null, modelState); + } + + protected void setModelState(WizardState modelState) { + WizardState oldValue = this.modelState; + this.modelState = modelState; + firePropertyChange(MODEL_STATE_PROPERTY_NAME, oldValue, modelState); + if (!wasStarted) { + if ((oldValue == null || oldValue == WizardState.PENDING) && modelState == WizardState.RUNNING) { + wasStarted = true; + firePropertyChange(WAS_STARTED_PROPERTY_NAME, false, true); + } + } + } + + protected void updateModelState(E step, WizardState newState) { + + switch (newState) { + case RUNNING: + //le modele est occupé + setModelState(WizardState.RUNNING); + break; + case FAILED: + //le modele est en erreur + setModelState(WizardState.FAILED); + break; + case CANCELED: + //le modele devient annulé + setModelState(WizardState.CANCELED); + return; + case PENDING: + //le modele est en attente + setModelState(WizardState.PENDING); + break; + case NEED_FIX: + //le modele est en attente + setModelState(WizardState.PENDING); + break; + case SUCCESSED: + // on regarde si on peut passer le model a l'état success + boolean valid = true; + for (E o : operations) { + if (getStepState(o) != WizardState.SUCCESSED) { + valid = false; + break; + } + } + if (valid) { + setModelState(WizardState.SUCCESSED); + } else { + setModelState(WizardState.PENDING); + } + break; + } + updateStepStates(steps); + } + + @Override + public void updateUniverse() { +// setValueAdjusting(true); + + List<E> oldSteps = new ArrayList<E>(getSteps()); + log.info("Start updateUniverse (oldSteps = " + oldSteps + ")"); + E[] newSteps = updateStepUniverse(); + log.info("newSteps = " + Arrays.toString(newSteps)); + + // do nothing if steps has not changed + boolean skip = true; + for (E newStep : newSteps) { + if (!oldSteps.contains(newStep)) { + skip = false; + } + } + + if (skip && oldSteps.size() == newSteps.length) { + + // same steps, so nothing to do + log.info("Steps are same, do not modify anything"); + return; + } + + for (WizardExtStepModel<E> model : models.values()) { + log.info("Destroy previous model : " + model); + model.destroy(); + } + models.clear(); + + List<E> toAdd = new ArrayList<E>(Arrays.asList(newSteps)); + + log.info("Will add models for " + toAdd); + + Iterator<E> itr = toAdd.iterator(); + while (itr.hasNext()) { + + E step = itr.next(); + + if (step.getModelClass() == null) { + + // no model attach to the step + itr.remove(); + continue; + } + + if (step.isOperation()) { + + // step is operation, model must be instanciate + WizardExtStepModel<E> model = (WizardExtStepModel<E>) step.newModel(); + if (log.isInfoEnabled()) { + log.info("[" + step + "] Add primary model " + model); + } + models.put(step, model); + + itr.remove(); + } + + // step has a model + } + + if (!toAdd.isEmpty()) { + + // there is some steps with model to attach + itr = toAdd.iterator(); + while (itr.hasNext()) { + + E step = itr.next(); + Class<? extends WizardExtStepModel<?>> modelClass = step.getModelClass(); + WizardExtStepModel<E> selectedModel = null; + // find out in models a + for (WizardExtStepModel<E> model : models.values()) { + if (modelClass.isAssignableFrom(model.getClass())) { + // find one + selectedModel = model; + break; + } + } + + if (selectedModel == null) { + throw new IllegalStateException("Could not find a primary model " + modelClass + " for step [" + step + "]"); + } + + log.info("[" + step + "] Attach model " + selectedModel); + models.put(step, selectedModel); + itr.remove(); + } + + if (!toAdd.isEmpty()) { + throw new IllegalStateException("There is some step no model : " + toAdd); + } + } + + setSteps(newSteps); + + // on met a jour les états des étapes + stepStates.clear(); + for (E step : newSteps) { + if (!stepStates.containsKey(step)) { + setStepState(step, WizardState.PENDING); + } + } + + // finally set the steps (this will refire a lot) + + log.info("Ending updateUniverse"); + +// setValueAdjusting(false); + } + + protected abstract E[] updateStepUniverse(); + + @Override + public void destroy() { + super.destroy(); + + for (WizardExtStepModel<E> model : models.values()) { + if (log.isDebugEnabled()) { + log.debug("destroy model " + model); + } + model.destroy(); + } + } + + protected int getOperationIndex(E operation) { + int index = 0; + for (E o : operations) { + if (o.equals(operation)) { + return index; + } + index++; + } + return -1; + } +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStep.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStep.java new file mode 100644 index 0000000..b7eba8e --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStep.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard.ext; + +import jaxx.runtime.swing.wizard.WizardStep; +import jaxx.runtime.swing.wizard.WizardStepUI; + + +/** + * Extension de {@link WizardStep} avec des états supplémentaires. + * <p/> + * Chaque étape possède un modèle de type {@link #getModelClass()}. + * Ce modèle peut être partagé par plusieurs étapes. + * <p/> + * De plus, on a deux drapeaux {@link #isConfig()} pour savoir si l'étape est une phase de configuration. + * <p/> + * Le drapeau {@link #isOperation()} quand à lui permet de savoir si l'étape est une opération. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ +public interface WizardExtStep extends WizardStep { + + /** @return le label de l'opération */ + String getOperationLabel(); + + /** @return la description de l'opération */ + String getOperationDescription(); + + /** @return le type du modèle de l'action */ + Class<? extends WizardExtStepModel<?>> getModelClass(); + + /** @return le type de l'ui de l'opération */ + Class<? extends WizardStepUI<?, ?>> getUiClass(); + + /** @return {@code true} si l'étape a une opération associée, {@code false} sinon. */ + boolean isOperation(); + + /** @return {@code true} si l'étape est une phase de configuration, {@code false} sinon. */ + boolean isConfig(); + + /** + * Instancie le modèle associée à l'étape. + * + * @return le nouveau modèle associé à l'étape + */ + WizardExtStepModel<?> newModel(); + + /** + * Construit l'ui associée à l'étape. + * + * @param ui l'ui principale du wiard + * @return la noveau ui associé à l'étape + */ + WizardStepUI<?, ?> newUI(WizardExtUI<?, ?> ui); +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java new file mode 100644 index 0000000..d82c66d --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtStepModel.java @@ -0,0 +1,111 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard.ext; + +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * Abstract model of {@link WizardExtStep}. + * + * @author tchemit <chemit@codelutin.com> + * @see WizardExtStep + * @since 2.1 + */ +public abstract class WizardExtStepModel<E extends WizardExtStep> { + + /** Logger */ + private static final Log log = LogFactory.getLog(WizardExtStepModel.class); + + /** for properties change support */ + private final PropertyChangeSupport pcs; + + /** step of the model */ + protected final E step; + + /** to store if an error occurs while running */ + protected Exception error; + + protected WizardExtStepModel(E step) { + this.step = step; + pcs = new PropertyChangeSupport(this); + } + + public final E getStep() { + return step; + } + + public final Exception getError() { + return error; + } + + public void setError(Exception error) { + this.error = error; + } + + public final void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + + public final void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public void destroy() { + if (log.isDebugEnabled()) { + log.debug("will destroy " + this); + } + + // remove all listeners + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } + + protected final void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected final void firePropertyChange(String propertyName, Object newValue) { + pcs.firePropertyChange(propertyName, null, newValue); + } +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUI.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUI.java new file mode 100644 index 0000000..5a190d3 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUI.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard.ext; + +import jaxx.runtime.swing.wizard.WizardUI; + +/** + * Contrat a respecter pour une ui de wizard. + * + * @param <E> le type d'etape + * @param <M> le type de model + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public interface WizardExtUI<E extends WizardExtStep, M extends WizardExtModel<E>> extends WizardUI<E, M> { + + /** Méthode invoqué lorsque le modèle a été initialisé. */ + void onWasInit(); + + /** Méthode invoqué lorsque la première opération du modèlé a été démarrée. */ + void onWasStarted(); + + /** + * Méthode invoquée lorsque l'état interne du modèle a changé. + * + * @param newState le nouvelle état du modèle de wizard + */ + void onModelStateChanged(WizardState newState); + + /** + * Méthode invoqué lorsque l'état d'une opération a changé. + * + * @param step l'étape dont l'état a changé + * @param newState le nouvel état pour l'étape donné + */ + void onOperationStateChanged(E step, WizardState newState); + +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java new file mode 100644 index 0000000..1b08b44 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardExtUtil.java @@ -0,0 +1,124 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard.ext; + +import jaxx.runtime.swing.wizard.WizardModel; +import jaxx.runtime.swing.wizard.WizardUI; +import jaxx.runtime.swing.wizard.WizardUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.IndexedPropertyChangeEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Array; +import java.util.List; + +/** + * Classe de méthodes utiles sur les wizard. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public class WizardExtUtil extends WizardUtil { + + /** Logger */ + static private Log log = LogFactory.getLog(WizardUI.class); + + protected WizardExtUtil() { + } + + public static boolean acceptStates(WizardState state, WizardState... accepted) { + for (WizardState s : accepted) { + if (s == state) { + return true; + } + } + return false; + } + + public static boolean rejectStates(WizardState state, WizardState... rejected) { + for (WizardState s : rejected) { + if (s == state) { + return false; + } + } + return true; + } + + public static <E extends WizardExtStep, M extends WizardExtModel<E>> void installWizardUIListeners(final WizardExtUI<E, M> ui) { + + + PropertyChangeListener dispatcher = new PropertyChangeListener() { + + @Override + @SuppressWarnings("unchecked") + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + if (WizardExtModel.WAS_STARTED_PROPERTY_NAME.equals(propertyName)) { + ui.onWasStarted(); + return; + } + WizardExtModel<E> model = (WizardExtModel<E>) evt.getSource(); + if (WizardModel.STEPS_PROPERTY_NAME.equals(propertyName)) { + List<E> steps = (List<E>) evt.getNewValue(); + ui.onStepsChanged( + steps.toArray((E[]) Array.newInstance( + model.getStepClass(), steps.size())) + ); + return; + } + if (WizardModel.STEP_PROPERTY_NAME.equals(propertyName)) { + ui.onStepChanged((E) evt.getNewValue()); + return; + } + if (WizardModel.VALID_STEP_PROPERTY_NAME.equals(propertyName)) { + Boolean value = (Boolean) evt.getNewValue(); + if (value == null || !value) { + ui.onModelStateChanged(WizardState.NEED_FIX); + } else { + ui.onModelStateChanged(WizardState.PENDING); + } + return; + } + if (WizardExtModel.MODEL_STATE_PROPERTY_NAME.equals(propertyName)) { + //TODO should be unicast : only for good stepUI ? + ui.onModelStateChanged((WizardState) evt.getNewValue()); + return; + } + if (WizardExtModel.STEP_STATE_PROPERTY_NAME.equals(propertyName)) { + IndexedPropertyChangeEvent e = (IndexedPropertyChangeEvent) evt; + int stepIndex = e.getIndex(); + E step = model.getSteps().get(stepIndex); + ui.onOperationStateChanged(step, (WizardState) evt.getNewValue()); + } + } + }; + M model = ui.getModel(); + log.info("Adding dispatcher " + dispatcher + " to model " + model); + model.addPropertyChangeListener(dispatcher); + } + +} \ No newline at end of file diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardState.java b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardState.java new file mode 100644 index 0000000..fe0c815 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/WizardState.java @@ -0,0 +1,51 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.wizard.ext; + +/** + * Pour caractériser l'état d'une opération. + * + * @author tchemit <chemit@codelutin.com> + */ +public enum WizardState { + + /** quand l'opération n'a pas encore été réalisée */ + PENDING, + + /** quand l'opération est en cours */ + RUNNING, + + /** quand l'opération est annulé en cours d'exécution */ + CANCELED, + + /** quand une erreur s'est produite pendant l'exécution */ + FAILED, + + /** quand l'exécution s'est terminée mais requière des corrections */ + NEED_FIX, + + /** quand l'exécution s'est terminée et ne requière pas de correction */ + SUCCESSED +} diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/package.html b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/package.html new file mode 100644 index 0000000..73a2ed3 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/ext/package.html @@ -0,0 +1,33 @@ +<!-- + #%L + JAXX :: Runtime + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>JAXX - Wizard framework</h1> + +This package contains all the classes of the wizard framework ext. + +This is a enriched wizard with operation on some steps. +</body> +</html> diff --git a/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/package.html b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/package.html new file mode 100644 index 0000000..6ee2461 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/package.html @@ -0,0 +1,33 @@ +<!-- + #%L + JAXX :: Runtime + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>JAXX - Wizard framework</h1> + +This package contains all the classes of the wizard framework. + +TODO +</body> +</html> diff --git a/trunk/jaxx-runtime/src/main/resources/i18n/jaxx-runtime_en_GB.properties b/trunk/jaxx-runtime/src/main/resources/i18n/jaxx-runtime_en_GB.properties new file mode 100644 index 0000000..531dd82 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/resources/i18n/jaxx-runtime_en_GB.properties @@ -0,0 +1,15 @@ +swing.error.desktop.browse.not.supported=Action 'Go to' not available +swing.error.desktop.not.supported=Desktop not accessible +validator.field.header=Field +validator.field.header.tip=The field involved +validator.field.tip=Property '%1$s' +validator.message.header=Message +validator.message.header.tip=Message +validator.message.tip=Message \: %1$s +validator.scope.error.label=Error +validator.scope.fatal.label=Fatal error +validator.scope.header=... +validator.scope.header.tip=Severity of the message +validator.scope.info.label=Information +validator.scope.tip=Message scope \: '%1$s' +validator.scope.warning.label=Warning diff --git a/trunk/jaxx-runtime/src/main/resources/i18n/jaxx-runtime_fr_FR.properties b/trunk/jaxx-runtime/src/main/resources/i18n/jaxx-runtime_fr_FR.properties new file mode 100644 index 0000000..05ce468 --- /dev/null +++ b/trunk/jaxx-runtime/src/main/resources/i18n/jaxx-runtime_fr_FR.properties @@ -0,0 +1,15 @@ +swing.error.desktop.browse.not.supported=Action 'aller \u00E0' non disponible +swing.error.desktop.not.supported=Desktop non accessible +validator.field.header=Champ +validator.field.header.tip=Le champ surquel intervient le message +validator.field.tip=Propri\u00E9t\u00E9 '%1$s' +validator.message.header=Message +validator.message.header.tip=Le texte du message +validator.message.tip=Message \: %1$s +validator.scope.error.label=Erreur +validator.scope.fatal.label=Erreur fatale +validator.scope.header=... +validator.scope.header.tip=Le type de message +validator.scope.info.label=Information +validator.scope.tip=Type de message \: '%1$s' +validator.scope.warning.label=Avertissement diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-delete.png b/trunk/jaxx-runtime/src/main/resources/icons/action-delete.png new file mode 100644 index 0000000..184f762 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-delete.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-config-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-config-16.png new file mode 100644 index 0000000..9460dfc Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-config-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-config.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-config.png new file mode 100644 index 0000000..8ef7275 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-config.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-message-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-message-16.png new file mode 100644 index 0000000..12cd1ae Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-message-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-message.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-message.png new file mode 100644 index 0000000..5aed843 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-message.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-next-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-next-16.png new file mode 100644 index 0000000..6ef8de7 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-next-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-next.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-next.png new file mode 100644 index 0000000..3fe7568 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-next.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-pause-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-pause-16.png new file mode 100644 index 0000000..2d9ce9c Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-pause-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-pause.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-pause.png new file mode 100644 index 0000000..76ba422 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-pause.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-previous-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-previous-16.png new file mode 100644 index 0000000..659cd90 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-previous-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-previous.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-previous.png new file mode 100644 index 0000000..9bab29c Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-previous.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-refresh-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-refresh-16.png new file mode 100644 index 0000000..0de2656 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-refresh-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-refresh.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-refresh.png new file mode 100644 index 0000000..ae1f596 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-refresh.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-start-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-start-16.png new file mode 100644 index 0000000..0846555 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-start-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-start.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-start.png new file mode 100644 index 0000000..8d36e63 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-start.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-canceled-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-canceled-16.png new file mode 100644 index 0000000..c149c2b Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-canceled-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-canceled.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-canceled.png new file mode 100644 index 0000000..296415e Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-canceled.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-failed-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-failed-16.png new file mode 100644 index 0000000..c37bd06 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-failed-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-failed.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-failed.png new file mode 100644 index 0000000..bed8b4f Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-failed.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-need_fix-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-need_fix-16.png new file mode 100644 index 0000000..628cf2d Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-need_fix-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-need_fix.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-need_fix.png new file mode 100644 index 0000000..1c6b8eb Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-need_fix.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-pending-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-pending-16.png new file mode 100644 index 0000000..893bb60 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-pending-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-pending.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-pending.png new file mode 100644 index 0000000..2415154 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-pending.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-running-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-running-16.png new file mode 100644 index 0000000..0846555 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-running-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-running.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-running.png new file mode 100644 index 0000000..de1a5f3 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-running.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-successed-16.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-successed-16.png new file mode 100644 index 0000000..a9925a0 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-successed-16.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-successed.png b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-successed.png new file mode 100644 index 0000000..743ef89 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/action-wizard-state-successed.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/error.png b/trunk/jaxx-runtime/src/main/resources/icons/error.png new file mode 100644 index 0000000..c37bd06 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/error.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/fatal.png b/trunk/jaxx-runtime/src/main/resources/icons/fatal.png new file mode 100644 index 0000000..08f2493 Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/fatal.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/info.png b/trunk/jaxx-runtime/src/main/resources/icons/info.png new file mode 100644 index 0000000..12cd1ae Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/info.png differ diff --git a/trunk/jaxx-runtime/src/main/resources/icons/warning.png b/trunk/jaxx-runtime/src/main/resources/icons/warning.png new file mode 100644 index 0000000..628cf2d Binary files /dev/null and b/trunk/jaxx-runtime/src/main/resources/icons/warning.png differ diff --git a/trunk/jaxx-runtime/src/site/rst/index.rst b/trunk/jaxx-runtime/src/site/rst/index.rst new file mode 100644 index 0000000..f8ec3d7 --- /dev/null +++ b/trunk/jaxx-runtime/src/site/rst/index.rst @@ -0,0 +1,39 @@ +.. - +.. * #%L +.. * JAXX :: Runtime +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============ +jaxx-runtime +============ + +.. contents:: + + +Présentation +------------ + +Api des objets utilisables au runtime. + +**Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes +librairies.** diff --git a/trunk/jaxx-runtime/src/site/site_fr.xml b/trunk/jaxx-runtime/src/site/site_fr.xml new file mode 100644 index 0000000..cad7dc6 --- /dev/null +++ b/trunk/jaxx-runtime/src/site/site_fr.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Runtime + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <src>http://maven-site.chorem.org/public/images/logos/jaxx-logo.png</src> + <href>index.html</href> + </bannerLeft> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="index.html"/> + </breadcrumbs> + + <menu ref="parent"/> + + <menu name="Utilisateur"> + <item name="Accueil" href="index.html"/> + </menu> + + <menu ref="reports"/> + + <menu ref="modules"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + </body> +</project> diff --git a/trunk/jaxx-runtime/src/test/java/jaxx/runtime/UtilTest.java b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/UtilTest.java new file mode 100644 index 0000000..572d96d --- /dev/null +++ b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/UtilTest.java @@ -0,0 +1,53 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +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 = JAXXUtil.getEventListener(DocumentListener.class, this, "incCount"); + listener.insertUpdate(null); + Assert.assertEquals(count, 1); + DocumentListener listener2 = JAXXUtil.getEventListener(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 diff --git a/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DataContextEntryIteratorTest.java b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DataContextEntryIteratorTest.java new file mode 100644 index 0000000..fe6411b --- /dev/null +++ b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DataContextEntryIteratorTest.java @@ -0,0 +1,288 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.context.DataContext.DataContextEntry; +import jaxx.runtime.context.DataContext.DataContextEntryIterator; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.regex.Pattern; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Tests {@link DataContext}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.1 + */ +public class DataContextEntryIteratorTest { + + static DataContextEntry<?>[] entries; + + static class DataContextEntry2 extends DataContextEntry<Object> { + + public DataContextEntry2() { + super(Object.class); + } + + public DataContextEntry2(DataContextEntry<?> previous) { + super(Object.class, previous); + } + + @Override + public Pattern getPattern() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getContextPath(Object... args) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean acceptType(Class<?> type) { + throw new UnsupportedOperationException("Not supported yet."); + } + } + + @BeforeClass + public static void setUpClass() throws Exception { + entries = new DataContextEntry<?>[3]; + entries[0] = new DataContextEntry2(); + entries[1] = new DataContextEntry2(entries[0]); + entries[2] = new DataContextEntry2(entries[1]); + } + + DataContextEntryIterator instance; + + @Test + public void testEmptyIterator() { + + instance = new DataContextEntryIterator( + DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY); + + boolean result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testEmptyReverseIterator() { + + instance = new DataContextEntryIterator( + DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY, true); + + boolean result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testEmptyLevelIterator() { + + instance = new DataContextEntryIterator( + DataContext.EMPTY_DATA_CONTEXT_ENTRY_ARRAY, 0); + + boolean result = instance.hasNext(); + assertEquals(false, result); + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[1]}, 0); + + result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testSingletonIterator() { + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testSingletonReverseIterator() { + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}, true); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + } + + @Test + public void testSingletonLevelIterator() { + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}, 0); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + instance = new DataContextEntryIterator( + new DataContextEntry<?>[]{entries[0]}, 1); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + instance = new DataContextEntryIterator(entries, 0); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + } + + @Test + public void testIterator() { + + instance = new DataContextEntryIterator(entries); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[1], data); + assertEquals(1, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[2], data); + assertEquals(2, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + + } + + @Test + public void testReverseIterator() { + + instance = new DataContextEntryIterator(entries, true); + + boolean result = instance.hasNext(); + assertEquals(true, result); + Object data = instance.next(); + assertNotNull(data); + assertEquals(entries[2], data); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[1], data); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + + result = instance.hasNext(); + assertEquals(false, result); + + + } + + @Test + public void testLevelIterator() { + + instance = new DataContextEntryIterator(entries, 2); + + boolean result = instance.hasNext(); + assertEquals(true, result); + DataContextEntry<?> data = instance.next(); + assertNotNull(data); + assertEquals(entries[0], data); + assertEquals(0, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[1], data); + assertEquals(1, data.getLevel()); + + result = instance.hasNext(); + assertEquals(true, result); + data = instance.next(); + assertNotNull(data); + assertEquals(entries[2], data); + assertEquals(2, data.getLevel()); + + result = instance.hasNext(); + assertEquals(false, result); + + + } +} diff --git a/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultApplicationContextTest.java b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultApplicationContextTest.java new file mode 100644 index 0000000..0f43742 --- /dev/null +++ b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultApplicationContextTest.java @@ -0,0 +1,224 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.context.DefaultApplicationContext.AutoLoad; +import jaxx.runtime.context.DefaultApplicationContext.MethodAccess; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** @author tchemit <chemit@codelutin.com> */ +public class DefaultApplicationContextTest { + + /** Logger */ + private static final Log log = + LogFactory.getLog(DefaultApplicationContextTest.class); + + static int helloCount; + + static int helloGetCount; + + static final JAXXContextEntryDef<String> STRING_ENTRY = + JAXXUtil.newContextEntryDef("myStringEntryKey", String.class); + + static final JAXXContextEntryDef<List<String>> LIST_STRING_ENTRY = + JAXXUtil.newListContextEntryDef("myListEntryKey"); + + @AutoLoad + @MethodAccess(methodName = "hello", target = String.class) + public static class Hello { + + public Hello() { + helloCount++; + } + + public String hello(String name) { + helloGetCount++; + return "hello " + name; + } + } + + DefaultApplicationContext context; + + @BeforeClass + public static void setUpClass() throws Exception { + helloCount = 0; + helloGetCount = 0; + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + context = new DefaultApplicationContext(); + assertEquals(0, helloCount); + assertEquals(0, helloGetCount); + } + + @After + public void tearDown() { + context = null; + helloCount = helloGetCount = 0; + } + + @Test(expected = IllegalArgumentException.class) + public void testAutoLoadNamed() { + context.getContextValue(Hello.class, "fakeName"); + } + + @Test + public void testAutoLoad() { + Hello hello = context.getContextValue(Hello.class); + assertNotNull(hello); + assertEquals(1, helloCount); + + Hello hello2 = context.getContextValue(Hello.class); + assertNotNull(hello2); + assertEquals(1, helloCount); + assertEquals(hello, hello2); + } + + @Test + public void testForward() { + context.getContextValue(Hello.class); + assertEquals(1, helloCount); + String response = context.getContextValue(String.class, "John"); + assertNotNull(response); + assertEquals(1, helloGetCount); + assertEquals(new Hello().hello("John"), response); + } + + @Test + public void testRemove() { + String response; + + context.getContextValue(Hello.class); + assertEquals(1, helloCount); + assertEquals(1, context.forwards.size()); + response = context.getContextValue(String.class, "John"); + assertNotNull(response); + + context.removeContextValue(Hello.class); + assertEquals(0, context.forwards.size()); + response = context.getContextValue(String.class, "John"); + assertEquals(1, helloCount); + assertNull(response); + + // reinstanciate the service + context.getContextValue(Hello.class); + assertEquals(2, helloCount); + assertEquals(1, context.forwards.size()); + + // no effect with a name + context.removeContextValue(Hello.class, "fake"); + assertEquals(1, context.forwards.size()); + context.getContextValue(Hello.class); + assertEquals(2, helloCount); + } + + static int yoCount; + + @Test + public void testEntryListener() { + + PropertyChangeListener listener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isInfoEnabled()) { + log.info("changed detected on " + evt.getSource()); + } + yoCount++; + } + }; + context.addPropertyChangeListener(STRING_ENTRY, "myKey", listener); + + STRING_ENTRY.setContextValue(context, "myValue"); + + Assert.assertEquals(1, yoCount); + + STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(2, yoCount); + + context.removePropertyChangeListener(STRING_ENTRY, "myKey", listener); + + // test that nothing changed now + + STRING_ENTRY.setContextValue(context, "myValue"); + + Assert.assertEquals(2, yoCount); + + STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(2, yoCount); + + // test with a list entry + + context.addPropertyChangeListener(LIST_STRING_ENTRY, "myKey2", listener); + + LIST_STRING_ENTRY.setContextValue(context, Arrays.asList("myValue")); + + Assert.assertEquals(3, yoCount); + + LIST_STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(4, yoCount); + + + // test that nothing changed now + + context.removePropertyChangeListener(LIST_STRING_ENTRY, "myKey2", listener); + + LIST_STRING_ENTRY.setContextValue(context, Arrays.asList("myValue2")); + + Assert.assertEquals(4, yoCount); + + LIST_STRING_ENTRY.removeContextValue(context); + + Assert.assertEquals(4, yoCount); + + + } + + +} diff --git a/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultJAXXContextTest.java b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultJAXXContextTest.java new file mode 100644 index 0000000..5fef82c --- /dev/null +++ b/trunk/jaxx-runtime/src/test/java/jaxx/runtime/context/DefaultJAXXContextTest.java @@ -0,0 +1,259 @@ +/* + * #%L + * JAXX :: Runtime + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.context; + +import jaxx.runtime.JAXXContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** @author tchemit <chemit@codelutin.com> */ +public class DefaultJAXXContextTest { + + DefaultJAXXContext ctxt; + + @Before + public void initContext() throws Exception { + + // instanciate a new empty context + ctxt = new DefaultJAXXContext(); + } + + @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")); + + } + +} diff --git a/trunk/jaxx-runtime/src/test/resources/log4j.properties b/trunk/jaxx-runtime/src/test/resources/log4j.properties new file mode 100644 index 0000000..0b8ecde --- /dev/null +++ b/trunk/jaxx-runtime/src/test/resources/log4j.properties @@ -0,0 +1,32 @@ +### +# #%L +# JAXX :: Runtime +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +# 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=INFO diff --git a/trunk/jaxx-swing-action/LICENSE.txt b/trunk/jaxx-swing-action/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/jaxx-swing-action/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/jaxx-swing-action/README.txt b/trunk/jaxx-swing-action/README.txt new file mode 100644 index 0000000..d2e50d3 --- /dev/null +++ b/trunk/jaxx-swing-action/README.txt @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install diff --git a/trunk/jaxx-swing-action/changelog.txt b/trunk/jaxx-swing-action/changelog.txt new file mode 100644 index 0000000..aebecde --- /dev/null +++ b/trunk/jaxx-swing-action/changelog.txt @@ -0,0 +1,10 @@ +1.3 chemit 20090409 + +1.1 chemit 20090220 + * 20090122 [chemit] - refactor poms (sibling dependencies, pluginsManagment,...) + - rename i18n bundles according artifactId + +1.0 chemit 20090111 + +0.7 chemit 200812?? + * 20081207 [chemit] use lutinproject 3.1 \ No newline at end of file diff --git a/trunk/jaxx-swing-action/pom.xml b/trunk/jaxx-swing-action/pom.xml new file mode 100644 index 0000000..4d18505 --- /dev/null +++ b/trunk/jaxx-swing-action/pom.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Swing-Action + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jaxx</artifactId> + <version>2.0.2-SNAPSHOT</version> + </parent> + + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-swing-action</artifactId> + + <dependencies> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>jboss</groupId> + <artifactId>javassist</artifactId> + <version>3.7.ga</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JAXX :: Swing-Action</name> + <description>JAXX Action framework</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + <packaging>jar</packaging> + + <build> + + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <!-- the code contains some AnnotationProcessor --> + <compilerArgument>-proc:none</compilerArgument> + </configuration> + </plugin> + </plugins> + </pluginManagement> + + <plugins> + + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + +</project> diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/AbstractActionConfigurationResolver.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/AbstractActionConfigurationResolver.java new file mode 100644 index 0000000..bced7af --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/AbstractActionConfigurationResolver.java @@ -0,0 +1,88 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import javax.swing.JComponent; +import java.lang.annotation.Annotation; + +/** + * Common abstract class of a resolver of action configuration. + * <p/> + * The class implements the logic of research of the configuration annotation. + * + * @param <A> type of annotation + * @param <C> type of component + * @author tchemit <chemit@codelutin.com> + */ +public abstract class AbstractActionConfigurationResolver<A extends Annotation, C extends JComponent> implements ActionConfigurationResolver<A, C> { + + /** the type of configuration's annotation */ + protected final Class<A> annotationImpl; + + /** the type of component that can fire an action */ + protected final Class<C> componentImpl; + + /** + * The typed method (on component) to apply configuration on the action and component. + * + * @param component the component which fires the action + * @param action the given action + * @return the configuration's annotation + */ + protected abstract A applyConfiguration0(C component, MyAbstractAction action); + + protected AbstractActionConfigurationResolver(Class<A> annotationImpl, Class<C> componentImpl) { + this.annotationImpl = annotationImpl; + this.componentImpl = componentImpl; + } + + @Override + public A resolveConfiguration(MyAbstractAction action) { + if (action.hasDelegate()) { + return resolveConfiguration(action.getDelegate()); + } + return action.getClass().getAnnotation(annotationImpl); + } + + @SuppressWarnings({"unchecked"}) + @Override + public A applyConfiguration(JComponent component, MyAbstractAction action) { + if (component != null && componentImpl.isAssignableFrom(component.getClass())) { + return applyConfiguration0((C) component, action); + } + + return null; + } + + @Override + public Class<A> getAnnotationImpl() { + return annotationImpl; + } + + @Override + public Class<C> getComponentImpl() { + return componentImpl; + } +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionAnnotationProcessing.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionAnnotationProcessing.java new file mode 100644 index 0000000..391127b --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionAnnotationProcessing.java @@ -0,0 +1,408 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import org.nuiton.util.SortedProperties; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedOptions; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.AnnotationValueVisitor; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.SimpleAnnotationValueVisitor6; +import javax.tools.FileObject; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; + + +@SupportedAnnotationTypes(value = {"org.nuiton.jaxx.action.*"}) +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedOptions({"jaxx.verbose"}) +/** + * Annotation processor to compute actions mapping. + * + * @author tchemit <chemit@codelutin.com> */ +public class ActionAnnotationProcessing extends AbstractProcessor { + + /** the {@link ActionProvider} service declaration relative path */ + protected String providerDeclarationLocation = "META-INF/services/" + ActionProvider.class.getName(); + + /** the relative path where to store actions mapping, will be complete with the name of base action to use */ + protected String actionsFileLocation = ActionProviderFromProperties.actionsFileLocation; + + /** verbose flag (can be activated by passing an annotation parameter to compiler via <code>-Ai18n.verbose</code>) */ + protected boolean verbose; + + /** the list of class processed by the processor */ + protected List<String> processedClass; + + /** the map of actions processed, keys are the action commaned and values are fqn of implementations */ + protected Properties actions; + + /** Extractor of values of annotations found */ + protected AnnotationValueVisitor<Object, Void> annotationValueExtractor; + + /** the type element of the base action to be used by {@link ActionProvider} */ + protected TypeElement baseActionElement; + + /** the fqn of the action provider to generate */ + protected String providerFQN; + + /** the fqn of the base action class to be used */ + protected String baseFQN; + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + parseOptions(); + printDebug("verbose : " + verbose); + printDebug("FileLocation : " + actionsFileLocation); + processedClass = new ArrayList<String>(); + actions = new SortedProperties(); + } + + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + + Set<? extends Element> annotatedWith = roundEnv.getElementsAnnotatedWith(annotation); + + if (annotation.getQualifiedName().toString().equals(ActionProviderAnnotation.class.getName())) { + // init provider + if (annotatedWith.size() != 1) { + throw new IllegalStateException("can have only one provider defined by the annotation " + ActionProviderAnnotation.class); + } + + baseActionElement = (TypeElement) annotatedWith.iterator().next(); + + //fixme it is not possible to know if baseActionElement is assigned from MyAbstractAction, since we + // can NOT garanted at this stage thaht the class was compiled... + + baseFQN = baseActionElement.asType().toString(); + int index = baseFQN.lastIndexOf(".") + 1; + String baseSimpleName = baseFQN.substring(index); + String packageName = baseFQN.substring(0, index); + + providerFQN = packageName + baseSimpleName + "Provider"; + printDebug("providerFQN " + providerFQN); + actionsFileLocation = String.format(actionsFileLocation, baseSimpleName); + continue; + } + + for (Element e : annotatedWith) { + String className = e.toString(); + + if (processedClass.contains(className)) { + printWarning("class already processed " + className); + // do not process class twice + continue; + } + + boolean wasTreated = registerActionsForClass(annotation.asType(), e); + if (wasTreated) { + printDebug("process class " + className); + processedClass.add(className); + } else { + printDebug("class was not processed " + e); + } + } + } + + if ((roundEnv.processingOver())) { + printDebug("round is over " + roundEnv); + try { + if (baseActionElement != null) { + // found the base action class to be compiled, so we have to write provider things... + writeProviderClass(); + writeProviderServiceDeclaration(); + } else { + + // baseActionClass was not compiled at this time, must find it back + // this means they should have an already mapping file written + + actionsFileLocation = findMappingFile(); + + printInfo("reused actionFilesLocation " + actionsFileLocation); + } + + writeActionMapping(); + + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + processedClass.clear(); + actions.clear(); + } + } + + return true; + } + + protected String findMappingFile() throws IOException { + String path = String.format(actionsFileLocation, "dummy_" + System.nanoTime()); + + + FileObject oldFo = processingEnv.getFiler().getResource(StandardLocation.SOURCE_OUTPUT, "", path); + File dummyFile = new File(oldFo.toUri().toString()).getParentFile(); + File[] files = dummyFile.listFiles(new FilenameFilter() { + + public boolean accept(File dir, String name) { + return name.startsWith("jaxx-") && name.endsWith("-actions.properties"); + } + }); + if (files.length < 1) { + // this is not normal, should have exactly one file here + throw new IllegalStateException("no provider name found, you must add on baseaction the annotation " + ActionProviderAnnotation.class); + } + File f = files[0]; + int index = f.getAbsolutePath().indexOf("META-INF"); + + return f.getAbsolutePath().substring(index); + } + + protected boolean registerActionsForClass(TypeMirror annotationType, Element e) { + boolean doTreate = false; + for (AnnotationMirror mirror : e.getAnnotationMirrors()) { + if (!mirror.getAnnotationType().equals(annotationType)) { + // do not treate other annotations + continue; + } + doTreate = true; + printDebug("found a annotation to treate : " + mirror + " for action : " + e.toString()); + for (String name : getActionNames(mirror)) { + actions.put("action." + name, e.toString()); + printDebug("registerActionForClass " + name + " : " + e.toString()); + } + } + return doTreate; + } + + protected void parseOptions() { + Map options = processingEnv.getOptions(); + verbose = options.containsKey("jaxx.verbose"); + } + + protected void writeProviderClass() throws IOException, NotFoundException, CannotCompileException, ClassNotFoundException { + OutputStream outputStream = null; + try { + + ClassPool pool = ClassPool.getDefault(); + + pool.appendClassPath(new LoaderClassPath(ActionProviderFromProperties.class.getClassLoader())); + + CtClass superClass = pool.get(ActionProviderFromProperties.class.getName()); + CtClass clazz = pool.makeClass(providerFQN); + // define the base action class in javassist pool to make possible compilation + pool.makeClass(baseFQN); + clazz.setSuperclass(superClass); + // add constructor + CtConstructor constructor = new CtConstructor(null, clazz); + constructor.setBody("super( " + baseFQN + ".class);"); + clazz.addConstructor(constructor); + byte[] byteCode = clazz.toBytecode(); + + JavaFileObject fo = processingEnv.getFiler().createClassFile(providerFQN); + printInfo("writing " + fo.toUri()); + outputStream = fo.openOutputStream(); + outputStream.write(byteCode); + + } finally { + if (outputStream != null) { + outputStream.close(); + } + } + } + + protected void writeProviderServiceDeclaration() throws IOException { + BufferedWriter w = null; + try { + FileObject fo = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", providerDeclarationLocation); + printInfo("writing " + fo.toUri()); + w = new BufferedWriter(fo.openWriter()); + w.append("# generated by ").append(getClass().getName()).append("\n").toString(); + w.append("#").append(new Date().toString()).append("\n").toString(); + w.append(providerFQN); + } finally { + if (w != null) { + w.close(); + } + } + } + + protected void writeActionMapping() throws IOException { + if (actions.isEmpty()) { + // nothing to write or overwrite + return; + } + + BufferedWriter w = null; + try { + Properties oldProps = loadOldActionMapping(); + if (oldProps != null) { + oldProps.putAll(actions); + actions = oldProps; + } + // ecriture de toutes les actions trouvees + FileObject fo = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", actionsFileLocation); + printInfo("writing " + fo.toUri()); + w = new BufferedWriter(fo.openWriter()); + actions.store(w, "generated by " + getClass().getName()); + } finally { + if (w != null) { + w.close(); + } + } + } + + protected Properties loadOldActionMapping() throws IOException { + // reprise sur une ancienne compilation + FileObject oldFo = processingEnv.getFiler().getResource(StandardLocation.SOURCE_OUTPUT, "", actionsFileLocation); + if (!new File(oldFo.toUri().toString()).exists()) { + return null; + } + Properties oldProps = new SortedProperties(); + InputStream inputStream = null; + try { + inputStream = oldFo.openInputStream(); + if (inputStream != null) { + oldProps.load(inputStream); + } + oldFo.delete(); + } finally { + if (inputStream != null) { + inputStream.close(); + } + } + + return oldProps; + } + + /** + * Obtain the array of names to be used by the annotation + * + * @param element the dictonnary of values found in a annotation + * @return thee array of names detected in the annotation + */ + @SuppressWarnings({"unchecked"}) + protected String[] getActionNames(AnnotationMirror element) { + String[] result = null; + for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : element.getElementValues().entrySet()) { + ExecutableElement type = entry.getKey(); + String name = type.getSimpleName().toString(); + + if ("actionCommands".equals(name)) { + List<String> stringList = (List<String>) entry.getValue().accept(getAnnotationValueExtractor(), null); + result = stringList.toArray(new String[stringList.size()]); + // a actionCommands field means + break; + } + if ("actionCommandProvider".equals(name)) { + TypeMirror t = (TypeMirror) entry.getValue().accept(getAnnotationValueExtractor(), null); + String classname = t.toString(); + printDebug("actionCommandProvider = " + classname); + if (classname.equals(ActionNameProvider.class.getName())) { + continue; + } + + // means there is a runtime names provider + result = new String[]{":" + classname}; + break; + } + if ("actionCommand".equals(name)) { + result = new String[]{(String) entry.getValue().accept(getAnnotationValueExtractor(), null)}; + } + } + + return result; + } + + protected AnnotationValueVisitor<Object, Void> getAnnotationValueExtractor() { + if (annotationValueExtractor == null) { + annotationValueExtractor = new SimpleAnnotationValueVisitor6<Object, Void>() { + + @Override + protected Object defaultAction(Object o, Void aVoid) { + return o; + } + + @Override + public Object visitArray(List<? extends AnnotationValue> vals, Void aVoid) { + List<Object> realVals = new ArrayList<Object>(); + for (AnnotationValue val : vals) { + realVals.add(val.accept(this, aVoid)); + } + return realVals; + } + + public Object visitType(TypeMirror t, Void aVoid) { + return t; + } + }; + } + return annotationValueExtractor; + } + + protected void printWarning(String msg) { + System.out.println("[WARN] " + getClass().getName() + " : " + msg); + } + + protected void printInfo(String msg) { + System.out.println("[INFO] " + getClass().getName() + " : " + msg); + } + + protected void printDebug(String msg) { + if (verbose) { + System.out.println("[DEBUG] " + getClass().getName() + " : " + msg); + } + } +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfig.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfig.java new file mode 100644 index 0000000..170e454 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfig.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import javax.swing.Action; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Pour enregister une action. + * <p/> + * Placer cette annotation sur la classe implantant l'action, + * <p/> + * les informations décrites seront utilisées pour instancier l'action + * + * @author tchemit <chemit@codelutin.com> + */ +@Retention(RetentionPolicy.RUNTIME) + +@Target(ElementType.TYPE) +@Inherited +public @interface ActionConfig { + + /** + * @return la clef de la commande (doit être unique) + * @see Action#ACTION_COMMAND_KEY + */ + String actionCommand(); + + /** @return array of names to be used in actions mapping */ + String[] actionCommands() default {}; + + /** + * @return the class to obtain at runtime the array of names to be used in actions mapping. + * <p/> + * <b>Note : the special value {@link ActionNameProvider} is used to says not to used + * œthis mecanism since we can not set a null value in a annotation</b> + */ + Class<? extends ActionNameProvider> actionCommandProvider() default ActionNameProvider.class; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#NAME + */ + String name() default ""; + + /** + * @return la clef i18n du tooltip de l'action, si vide ignoré + * @see Action#SHORT_DESCRIPTION + */ + String shortDescription() default ""; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#LONG_DESCRIPTION + */ + String longDescription() default ""; + + /** + * @return le nom de l'icone associé, si vide ignoré + * @see Action#SMALL_ICON + */ + String smallIcon() default ""; + + /** + * @return le nom du grande icone associé, si vide ignoré + * @see Action#LARGE_ICON_KEY + */ + String largeIcon() default ""; + + /** + * @return accelerator + * @see Action#ACCELERATOR_KEY + */ + String accelerator() default ""; + + /** + * @return mnemonic key + * @see Action#MNEMONIC_KEY + */ + int mnemonic() default '\0'; + + /** + * @return mnemonic key index + * @see Action#DISPLAYED_MNEMONIC_INDEX_KEY + */ + int displayedMnemonicIndex() default '\0'; + + /** + * @return la valeur par défaut pour les component selectable + * @see Action#SELECTED_KEY + */ + boolean selected() default false; + + /** + * @return enabled state + * @see Action#isEnabled() + */ + boolean enabled() default true; + + /** @return hideActionText state */ + boolean hideActionText() default false; + +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfigConfigurationResolver.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfigConfigurationResolver.java new file mode 100644 index 0000000..9213aab --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfigConfigurationResolver.java @@ -0,0 +1,80 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import org.nuiton.jaxx.util.UIHelper; + +import static org.nuiton.i18n.I18n._; + +import javax.swing.AbstractButton; +import javax.swing.Action; + +/** + * Implementation of configuration's resolver for annotation {@link ActionConfig} + * + * @author tchemit <chemit@codelutin.com> + */ +public class ActionConfigConfigurationResolver extends AbstractActionConfigurationResolver<ActionConfig, AbstractButton> { + + public ActionConfigConfigurationResolver() { + super(ActionConfig.class, AbstractButton.class); + } + + @Override + protected ActionConfig applyConfiguration0(AbstractButton component, MyAbstractAction action) { + ActionConfig anno = resolveConfiguration(action); + if (anno == null) { + return null; + } + // inject les données + if (!anno.name().isEmpty()) { + //System.out.println("found action with name : " + anno.name()); + action.putValue(Action.NAME, _(anno.name())); + } + //if (!anno.shortDescription().isEmpty()) { + action.putValue(Action.SHORT_DESCRIPTION, _(anno.shortDescription())); + //} + if (!anno.smallIcon().isEmpty()) { + action.putValue(Action.SMALL_ICON, UIHelper.createImageIcon(anno.smallIcon())); + } + if (anno.mnemonic() != '\0') { + action.putValue(Action.MNEMONIC_KEY, anno.mnemonic()); + } else if (component != null) { + action.putValue(Action.MNEMONIC_KEY, component.getMnemonic()); + } + //TODO Convert it from String action.putValue(Action.ACCELERATOR_KEY, anno.accelerator()); + + if (component == null) { + action.putValue("hideActionText", anno.hideActionText()); + } else { + boolean actionText = component.getHideActionText(); + action.putValue("hideActionText", anno.hideActionText() || actionText); + } + action.putValue(Action.SELECTED_KEY, anno.selected()); + action.setEnabled(anno.enabled()); + + return anno; + } +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfigurationResolver.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfigurationResolver.java new file mode 100644 index 0000000..b86c973 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionConfigurationResolver.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import javax.swing.JComponent; +import java.lang.annotation.Annotation; + +/** + * The contract to be realized to resolve an {@link MyAbstractAction} configuration. + * <p/> + * Configuration is done by a Annotation of type {@code A} placed on the action class. + * <p/> + * If the instanciated action box the real action, we should always search on the boxed action. + * <p/> + * Moreover, a action can only be fired by a certain type of component (for example a Button or a ComboBox), the class + * of the component type is given by the {@code C} class. + * + * @param <A> type of annotation for config + * @param <C> type of component + * @author tchemit <chemit@codelutin.com> + */ +public interface ActionConfigurationResolver<A extends Annotation, C extends JComponent> { + /** + * Search the annotation that configure the given action (or the boxed action). + * + * @param action current action + * @return the configuration of the action + */ + A resolveConfiguration(MyAbstractAction action); + + /** + * @param component widget that requires the action + * @param action given action + * @return the configuration of the action + */ + A applyConfiguration(JComponent component, MyAbstractAction action); + + /** @return the configuration annotation dealed by this resolver */ + Class<A> getAnnotationImpl(); + + /** @return the class of the component which can fired the action */ + Class<C> getComponentImpl(); +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionFactory.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionFactory.java new file mode 100644 index 0000000..50d1b94 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionFactory.java @@ -0,0 +1,160 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import jaxx.runtime.JAXXObject; + +import javax.swing.JComponent; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * Action factory using the <code>ActionConfig-like</code> annotations to configure actions. + * <p/> + * <p/> + * An {@code ActionFactory} builds actions always on a same type <code>A</code> and obtain them from some + * {@link ActionProvider} via methods {@link #newAction(String, JComponent)} and {@link #newAction(String)} . + * <p/> + * If the action coming from the provider is not on the same type <code>A</code>, then the action is boxed in a * + * action <code>A</code> and use the generic mecanism of delegation provided by {@link MyAbstractAction}. + * <p/> + * Use after the {@link #loadActions(JAXXObject)} to instanciate actions in ui with id equals a known + * action... + * <p/> + * All actions instanciated are stored in a cache that you can request via method {@link #getActionFromCache(String)}, + * {@link #cacheEntrySet()} and {@link #resetCache()}. + * <p/> + * You can also from this factory fires some action via the methods {@link #fireAction(String, Object, JComponent)} , + * {@link #fireAction(String, Object)} , {@link #fireAction0(String, Object, MyAbstractAction)}. + * <p/> + * Finally, a {@link #dispose()} method is there to shut down all instanciated action when you want to dispose all uis. + * + * @param <A> type of boxed action + * @author tchemit <chemit@codelutin.com> + * @see ActionProvider + * @see MyAbstractAction + */ +public interface ActionFactory<A extends MyAbstractAction> { + + /** + * Method to init the dictionary of knwon action implementations. + * + * @return the dictionary of known action implementations + */ + Map<String, Class<? extends MyAbstractAction>> init(); + + /** @return the class of the base action of the factory. */ + Class<A> getBaseClass(); + + /** @return the set of all the action's classes known by the factory. */ + Set<Entry<String, Class<? extends MyAbstractAction>>> implsEntrySet(); + + /** @return the array of names of all actions known by the factory */ + String[] getActionNames(); + + /** @return the set of all actions cached in factory indexed by their name */ + Set<Entry<String, A>> cacheEntrySet(); + + /** + * @param actionKey the action's key + * @return the action in cache or <code>null</code> if action is not in cache + */ + MyAbstractAction getActionFromCache(String actionKey); + + /** clear the cache of instanciated actions. */ + void resetCache(); + + /** + * @param actionKey the key of an action + * @return the action with this key from cache, or <code>null</code> if this action is not in cache + */ + + //A get(String actionKey); + + /** + * For a given ui, load all actions registred in factory. + * <p/> + * The id of the widget in ui is directly mapped to a action key. + * + * @param ui the ui to treate + */ + void loadActions(JAXXObject ui); + + /** + * Obtain an action instance given his key and widget + * + * @param actionKey the key of action + * @param component the component using the action + * @return the instanciated action (could come from cache if already instanciated {@link #getActionFromCache(String)} + */ + A newAction(String actionKey, JComponent component); + + /** + * Obtain an action instance given his key (should call {@link #newAction(String, JComponent)} + * <p/> + * This is a convinient method when you want to obtain an action with no attached widget. + * + * @param actionKey the key of action + * @return the instanciated action (could come from cache if already instanciated {@link #getActionFromCache(String)} + */ + A newAction(String actionKey); + + + /** + * Fire an action given his key, his source and tthe widget responsible of action + * + * @param actionKey the action's key + * @param source the object source of action + * @param component the component doing the action + */ + void fireAction(String actionKey, Object source, JComponent component); + + /** + * Fire an action given his key and his source, no widget are involved here + * + * @param actionKey the action's key + * @param source the object source of action + */ + void fireAction(String actionKey, Object source); + + /** + * Fire an action given his action's key, his source and the real action. + * <p/> + * This is a convinient method when you need to modified action before fire it. + * + * @param actionKey action's key + * @param source source of action + * @param action real action + */ + void fireAction0(String actionKey, Object source, A action); + + + /** + * dispose all actions in cache using {@link MyAbstractAction#disposeUI()} on each + * action, then {@link #resetCache()} + */ + void dispose(); +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionFactoryFromProvider.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionFactoryFromProvider.java new file mode 100644 index 0000000..99924b9 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionFactoryFromProvider.java @@ -0,0 +1,495 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* +* ##% 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.nuiton.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.nuiton.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.ArrayList; +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 ActionNameProvider} which gives us at + * runtime the names of each entry to put in cache for the givne action fqn. + * + * @param <A> the type of action + * @author tchemit <chemit@codelutin.com> + */ +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; + impls = init(); + cache = new TreeMap<String, A>(); + configurationResolvers = new ArrayList<AbstractActionConfigurationResolver>(); + + toggleActionConfigInitializer = registerInitializer(ToggleActionConfigConfigurationResolver.class); + actionConfigInitializer = registerInitializer(ActionConfigConfigurationResolver.class); + selectActionConfigInitializer = registerInitializer(SelectActionConfigConfigurationResolver.class); + } + + @Override + public Class<A> getBaseClass() { + return baseImpl; + } + + @Override + public void resetCache() { + cache.clear(); + } + + /*public A get(String actionKey) { + return cache.get(actionKey); + }*/ + + @Override + 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. + */ + @Override + 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; + } + + @Override + public A newAction(String actionKey) { + return newAction(actionKey, null); + } + + @Override + public String[] getActionNames() { + return impls.keySet().toArray(new String[impls.size()]); + } + + @Override + public Set<Entry<String, Class<? extends MyAbstractAction>>> implsEntrySet() { + return impls.entrySet(); + } + + @Override + public Set<Entry<String, A>> cacheEntrySet() { + return cache.entrySet(); + } + + @Override + public void fireAction(String actionKey, Object source, JComponent component) { + A action = newAction(actionKey, component); + fireAction0(actionKey, source, action); + } + + @Override + 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. + */ + @Override + 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; + } + + @Override + 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 diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionNameProvider.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionNameProvider.java new file mode 100644 index 0000000..b134e21 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionNameProvider.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +/** + * Contrat pour obtenir les noms d'une action de maniere dynamique. + * <p/> + * Cette méthode sera appelee par un {@link ActionProvider} lorsque la clef dans le + * fichier de mapping est <code>:fqn</code> (où fqn correspond à une implantation de ce contrat). + * <p/> + * Ainsi on peut associer à une action donnee plusieurs instances avec des noms différents mais de le meme comportement. + * <p/> + * Par exemple, une changement de locale ou seule la locale varie (et elle sera retrouvee a partir du nom de l'action). + * + * @author tchemit <chemit@codelutin.com> + */ +public interface ActionNameProvider { + + /** @return la liste des noms à utiliser par la classe d'action. */ + String[] getActionCommands(); + +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProvider.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProvider.java new file mode 100644 index 0000000..172e99d --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProvider.java @@ -0,0 +1,48 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import java.util.Map; + +/** + * Contract to be realized by a provider of Actions. + * <p/> + * A provider of actions is based on a certain type of {@link MyAbstractAction} (<code>A</code>) with an accessor + * {@link #getBaseClass()} and deliver some implementations of such actions indexed by their logical names via the + * method {#link #getClasses()}. + * + * @param <A> type of action boxed + * @author tchemit <chemit@codelutin.com> + * @see MyAbstractAction + */ +public interface ActionProvider<A extends MyAbstractAction> { + + /** @return the base classe of provided actions */ + Class<A> getBaseClass(); + + /** @return the provided actions classes */ + Map<String, Class<? extends A>> getClasses(); + +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProviderAnnotation.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProviderAnnotation.java new file mode 100644 index 0000000..aad0c34 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProviderAnnotation.java @@ -0,0 +1,44 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Pour enregister un provider d'action. + * <p/> + * Placer cette annotation sur la classe de base d'action, + * <p/> + * + * @author tchemit <chemit@codelutin.com> + */ +@Retention(RetentionPolicy.RUNTIME) + +@Target(ElementType.TYPE) +public @interface ActionProviderAnnotation { +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProviderFromProperties.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProviderFromProperties.java new file mode 100644 index 0000000..0f248df --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ActionProviderFromProperties.java @@ -0,0 +1,145 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import static org.nuiton.i18n.I18n._; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; + +/** @author tchemit <chemit@codelutin.com> */ +public class ActionProviderFromProperties<A extends MyAbstractAction> implements ActionProvider<A> { + + /** default prefix for an entryin mapping file. */ + protected static final String ACTION_KEY_PREFIX = "action."; + + protected static final String actionsFileLocation = "META-INF/jaxx-%1$s-actions.properties"; + + protected String propertiesPath; + + protected static Log log = LogFactory.getLog(ActionProviderFromProperties.class); + + protected Class<A> baseClass; + + protected Map<String, Class<? extends A>> actions; + + + protected ActionProviderFromProperties(Class<A> baseClass) { + + this.baseClass = baseClass; + propertiesPath = "/" + String.format(actionsFileLocation, baseClass.getSimpleName()); + actions = initCache(); + } + + public Class<A> getBaseClass() { + return baseClass; + } + + public Map<String, Class<? extends A>> getClasses() { + return actions; + } + + @Override + public String toString() { + return super.toString() + "<baseClass:" + baseClass.getSimpleName() + ">"; + } + + protected void clearCache() { + if (actions != null) { + actions.clear(); + actions = null; + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + clearCache(); + } + + @SuppressWarnings({"unchecked"}) + protected Map<String, Class<? extends A>> initCache() { + + InputStream inputStream = null; + + Properties properties = new Properties(); + + try { + inputStream = getClass().getResourceAsStream(propertiesPath); + if (inputStream == null) { + //throw new NullPointerException("could not find action file " + propertiesPath); + // actually, there is nothing to load, this is not an error + } else { + log.info("load " + propertiesPath); + properties.load(inputStream); + } + } catch (IOException e) { + String message = _("jaxx.error.load.actions.file", e.getMessage()); + log.warn(message); + throw new RuntimeException(message); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + log.warn(_("jaxx.error.close.actions.file", e.getMessage())); + //throw new RuntimeException(_("jaxx.error.load.actions.file", e.getMessage())); + } + } + } + + Map<String, Class<? extends A>> cache = new TreeMap<String, Class<? extends A>>(); + int prefix = ACTION_KEY_PREFIX.length(); + for (Map.Entry<Object, Object> entry : properties.entrySet()) { + String key = entry.getKey() + ""; + String qfn = entry.getValue() + ""; + try { + Class<? extends A> implCass; + implCass = (Class<? extends A>) Class.forName(qfn); + String actionKey = key.substring(prefix); + if (actionKey.startsWith(":")) { + // this is a RuntimeActionNameProvider + Class<ActionNameProvider> klazz = (Class<ActionNameProvider>) Class.forName(actionKey.substring(1)); + for (String s : klazz.newInstance().getActionCommands()) { + log.debug("found action <" + s + " : " + implCass + ">"); + cache.put(s, implCass); + } + continue; + } + log.debug("found action <" + actionKey + " : " + implCass + ">"); + cache.put(actionKey, implCass); + } catch (Exception e) { + throw new RuntimeException(_("jaxx.error.load.actions.class", key, qfn), e); + } + } + + return cache; + } +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/MyAbstractAction.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/MyAbstractAction.java new file mode 100644 index 0000000..5bc4ede --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/MyAbstractAction.java @@ -0,0 +1,270 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import jaxx.runtime.JAXXObject; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import static org.nuiton.i18n.I18n._; + +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; + +/** + * Action de base à utiliser pour encapsuler toutes les actions du système. + * <p/> + * Ces actions seront chargées par des {@link ActionProvider} et des {@link ActionFactory}. + * + * @author tchemit <chemit@codelutin.com> + */ +public abstract class MyAbstractAction extends AbstractAction { + + protected static Log log = LogFactory.getLog(MyAbstractAction.class); + + private static final long serialVersionUID = -810023044364620841L; + + protected ActionEvent e; + + protected MyAbstractAction delegate; + + protected abstract String getPrefix(); + + protected MyAbstractAction(String name) { + super(name); + } + + protected MyAbstractAction(MyAbstractAction delegate) { + super((String) delegate.getValue(NAME)); + this.delegate = delegate; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (hasDelegate()) { + // delegate to real action + delegate.actionPerformed(e); + return; + } + log.debug("------------------------------------------------------------"); + log.debug("event : " + e); + log.debug("source : " + e.getSource()); + this.e = e; + try { + boolean accepted = beforeAction(e); + log.debug("action : " + this); + if (accepted) { + log.info(getActionName() + " (treate:" + accepted + ") : " + this); + } else { + log.debug(getActionName() + " (treate:" + accepted + ") : " + this); + } + if (accepted) { + doAction(e); + setStatus(_("jaxx.action.done", getName())); + updateUI(); + } + } catch (Exception e1) { + showError(e1); + } finally { + this.e = null; + // always clear action after use : actions are staless + clear(); + } + } + + public String getI18nToolTipText() { + if (hasDelegate()) { + return delegate.getI18nToolTipText(); + } + return getPrefix() + ".action." + getActionName() + ".tooltip"; + } + + public void updateUI() { + if (hasDelegate()) { + delegate.updateUI(); + } + // nothing by default + } + + public void disposeUI() { + if (hasDelegate()) { + delegate.disposeUI(); + } + // nothing by default + } + + public MyAbstractAction getDelegate() { + return delegate; + } + + public boolean hasDelegate() { + return delegate != null; + } + + protected String getName() { + return (String) getValue(NAME); + } + + protected String getActionName() { + return (String) getValue(ACTION_COMMAND_KEY); + } + + protected void setStatus(String status) { + // do nothing from here + if (log.isDebugEnabled()) { + log.debug(status); + } + } + + protected boolean beforeAction(ActionEvent evt) throws Exception { + boolean canContinue = isEnabled(); + if (canContinue && hasDelegate()) { + return delegate.beforeAction(evt); + } + return canContinue; + } + + protected void doAction(ActionEvent evt) throws Exception { + if (hasDelegate()) { + delegate.doAction(evt); + } + // nothing by default + } + + protected JComponent getUIObject(String name, JAXXObject container) { + if (container == null) { + return null; + } + return (JComponent) container.getObjectById(name); + } + + protected void clear() { + if (hasDelegate()) { + delegate.clear(); + } + // nothing by default + } + + protected void showError(Exception e) { + log.error(e); + } + + // ----------------------------------------------------------------------------- + // --- super class delegate methods ------------------------------------------- + // ----------------------------------------------------------------------------- + + @Override + public Object getValue(String key) { + if (hasDelegate()) { + return delegate.getValue(key); + } + return super.getValue(key); + } + + @Override + public void putValue(String key, Object newValue) { + if (hasDelegate()) { + delegate.putValue(key, newValue); + } + super.putValue(key, newValue); + } + + @Override + public boolean isEnabled() { + if (hasDelegate()) { + return delegate.isEnabled(); + } + return super.isEnabled(); + } + + @Override + public void setEnabled(boolean newValue) { + if (hasDelegate()) { + delegate.setEnabled(newValue); + } + super.setEnabled(newValue); + } + + @Override + public Object[] getKeys() { + if (hasDelegate()) { + return getKeys(); + } + return super.getKeys(); + } + + @Override + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (hasDelegate()) { + delegate.firePropertyChange(propertyName, oldValue, newValue); + } + super.firePropertyChange(propertyName, oldValue, newValue); + } + + @Override + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + if (hasDelegate()) { + delegate.addPropertyChangeListener(listener); + } + super.addPropertyChangeListener(listener); + } + + @Override + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + if (hasDelegate()) { + delegate.removePropertyChangeListener(listener); + } + super.removePropertyChangeListener(listener); + } + + @Override + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + if (hasDelegate()) { + return delegate.getPropertyChangeListeners(); + } + return super.getPropertyChangeListeners(); + } + + @Override + protected Object clone() throws CloneNotSupportedException { + if (hasDelegate()) { + return clone(); + } + return super.clone(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(super.toString()); + if (hasDelegate()) { + sb.append("[delegate: ").append(delegate.toString()).append("]"); + } else { + sb.append("<key:").append(getActionName()).append(">"); + } + return sb.toString(); + } +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/SelectActionConfig.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/SelectActionConfig.java new file mode 100644 index 0000000..e3f53d7 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/SelectActionConfig.java @@ -0,0 +1,102 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import javax.swing.Action; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Pour enregister une action. + * <p/> + * Placer cette annotation sur la classe implantant l'action, + * <p/> + * les informations décrites seront utilisées pour instancier l'action + * + * @author tchemit <chemit@codelutin.com> + */ +@Retention(RetentionPolicy.RUNTIME) + +@Target(ElementType.TYPE) +@Inherited +public @interface SelectActionConfig { + + /** + * @return la clef de la commande (doit être unique) + * @see Action#ACTION_COMMAND_KEY + */ + String actionCommand(); + + /** @return array of names to be used in actions mapping */ + String[] actionCommands() default {}; + + /** + * @return the class to obtain at runtime the array of names to be used in actions mapping. + * <p/> + * <b>Note : the special value {@link ActionNameProvider} is used to says not to used + * œthis mecanism since we can not set a null value in a annotation</b> + */ + Class<? extends ActionNameProvider> actionCommandProvider() default ActionNameProvider.class; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#NAME + */ + String name() default ""; + + /** + * @return la clef i18n du tooltip de l'action, si vide ignoré + * @see Action#SHORT_DESCRIPTION + */ + String shortDescription() default ""; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#LONG_DESCRIPTION + */ + String longDescription() default ""; + + /** + * @return accelerator key + * @see Action#ACCELERATOR_KEY + */ + String accelerator() default ""; + + /** + * @return la valeur par défaut pour les component selectable + * @see Action#SELECTED_KEY + */ + int selectedIndex() default 0; + + /** + * @return enabled state + * @see Action#isEnabled() + */ + boolean enabled() default true; + +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/SelectActionConfigConfigurationResolver.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/SelectActionConfigConfigurationResolver.java new file mode 100644 index 0000000..7641cc3 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/SelectActionConfigConfigurationResolver.java @@ -0,0 +1,64 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import static org.nuiton.i18n.I18n._; + +import javax.swing.Action; +import javax.swing.JComboBox; + +/** + * Implementation of configuration's resolver for annotation {@link SelectActionConfig} + * + * @author tchemit <chemit@codelutin.com> + */ +public class SelectActionConfigConfigurationResolver extends AbstractActionConfigurationResolver<SelectActionConfig, JComboBox> { + + public SelectActionConfigConfigurationResolver() { + super(SelectActionConfig.class, JComboBox.class); + } + + @Override + protected SelectActionConfig applyConfiguration0(JComboBox component, MyAbstractAction action) { + SelectActionConfig anno = resolveConfiguration(action); + if (anno == null) { + return null; + } + // inject les données + if (!anno.name().isEmpty()) { + action.putValue(Action.NAME, _(anno.name())); + } + if (!anno.shortDescription().isEmpty()) { + action.putValue(Action.SHORT_DESCRIPTION, _(anno.shortDescription())); + } else { + action.putValue(Action.SHORT_DESCRIPTION, _(component.getToolTipText())); + } + action.putValue("selectedIndex", anno.selectedIndex()); + //TODO Convert it from String action.putValue(Action.ACCELERATOR_KEY, anno.accelerator()); + action.setEnabled(anno.enabled()); + + return anno; + } +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ToggleActionConfig.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ToggleActionConfig.java new file mode 100644 index 0000000..890a38a --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ToggleActionConfig.java @@ -0,0 +1,163 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import javax.swing.Action; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Pour enregister une action de type Toggle (ToggleButton). + * <p/> + * Placer cette annotation sur la classe implantant l'action, + * <p/> + * les informations décrites seront utilisées pour instancier l'action + * + * @author tchemit <chemit@codelutin.com> + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface ToggleActionConfig { + /** + * @return la clef de la commande (doit être unique) + * @see Action#ACTION_COMMAND_KEY + */ + String actionCommand(); + + /** @return array of names to be used in actions mapping */ + String[] actionCommands() default {}; + + /** + * @return the class to obtain at runtime the array of names to be used in actions mapping. + * <p/> + * <b>Note : the special value {@link ActionNameProvider} is used to says not to used + * œthis mecanism since we can not set a null value in a annotation</b> + */ + Class<? extends ActionNameProvider> actionCommandProvider() default ActionNameProvider.class; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#NAME + */ + String name() default ""; + + /** + * @return la clef i18n du tooltip de l'action, si vide ignoré + * @see Action#SHORT_DESCRIPTION + */ + String shortDescription() default ""; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#LONG_DESCRIPTION + */ + String longDescription() default ""; + + /** + * @return le nom de l'icone associé, si vide ignoré + * @see Action#SMALL_ICON + */ + String smallIcon() default ""; + + /** + * @return le nom du grande icone associé, si vide ignoré + * @see Action#LARGE_ICON_KEY + */ + String largeIcon() default ""; + + /** + * @return accelerator key of default state + * @see Action#ACCELERATOR_KEY + */ + String accelerator() default ""; + + /** + * @return mnemonic key of default state + * @see Action#MNEMONIC_KEY + */ + int mnemonic() default '\0'; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#NAME + */ + String name2() default ""; + + /** + * @return la clef i18n du tooltip de l'action, si vide ignoré + * @see Action#SHORT_DESCRIPTION + */ + String shortDescription2() default ""; + + /** + * @return la clef i18n du texte de l'action, si vide ignoré + * @see Action#LONG_DESCRIPTION + */ + String longDescription2() default ""; + + /** + * @return le nom de l'icone associé, si vide ignoré + * @see Action#SMALL_ICON + */ + String smallIcon2() default ""; + + /** + * @return le nom du grande icone associé, si vide ignoré + * @see Action#LARGE_ICON_KEY + */ + String largeIcon2() default ""; + + /** + * @return accelerator key of default state + * @see Action#ACCELERATOR_KEY + */ + String accelerator2() default ""; + + /** + * @return mnemonic key of second state + * @see Action#MNEMONIC_KEY + */ + int mnemonic2() default '\0'; + + /** + * @return la valeur par défaut pour les component selectable + * @see Action#SELECTED_KEY + */ + boolean selected() default false; + + /** + * @return enaled state + * @see Action#isEnabled() + */ + boolean enabled() default true; + + /** @return hideActionText state */ + boolean hideActionText() default false; + +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ToggleActionConfigConfigurationResolver.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ToggleActionConfigConfigurationResolver.java new file mode 100644 index 0000000..f06a4bf --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/action/ToggleActionConfigConfigurationResolver.java @@ -0,0 +1,92 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.action; + +import org.nuiton.jaxx.util.UIHelper; + +import static org.nuiton.i18n.I18n._; + +import javax.swing.AbstractButton; +import javax.swing.Action; + +/** + * Implementation of configuration's resolver for annotation {@link ToggleActionConfig} + * + * @author tchemit <chemit@codelutin.com> + */ +public class ToggleActionConfigConfigurationResolver extends AbstractActionConfigurationResolver<ToggleActionConfig, AbstractButton> { + + public ToggleActionConfigConfigurationResolver() { + super(ToggleActionConfig.class, AbstractButton.class); + } + + @Override + protected ToggleActionConfig applyConfiguration0(AbstractButton component, MyAbstractAction action) { + ToggleActionConfig anno = resolveConfiguration(action); + if (anno == null) { + return null; + } + // inject les données + if (!anno.name().isEmpty()) { + //System.out.println("found action with name : " + anno.name()); + action.putValue(Action.NAME, _(anno.name())); + } + if (!anno.name2().isEmpty()) { + //System.out.println("found action with name2 : " + anno.name2()); + action.putValue(Action.NAME + "2", _(anno.name2())); + } + + if (!anno.shortDescription().isEmpty()) { + action.putValue(Action.SHORT_DESCRIPTION, _(anno.shortDescription())); + } + if (!anno.shortDescription2().isEmpty()) { + action.putValue(Action.SHORT_DESCRIPTION + "2", _(anno.shortDescription2())); + } + + if (!anno.smallIcon().isEmpty()) { + action.putValue(Action.SMALL_ICON, UIHelper.createImageIcon(anno.smallIcon())); + } + if (!anno.smallIcon2().isEmpty()) { + action.putValue(Action.SMALL_ICON + "2", UIHelper.createImageIcon(anno.smallIcon2())); + } + + if (anno.mnemonic() != '\0') { + action.putValue(Action.MNEMONIC_KEY, anno.mnemonic()); + } else if (component != null) { + action.putValue(Action.MNEMONIC_KEY, component.getMnemonic()); + } + if (anno.mnemonic2() != '\0') { + action.putValue(Action.MNEMONIC_KEY + "2", anno.mnemonic2()); + } + //TODO Convert it from String action.putValue(Action.ACCELERATOR_KEY, anno.accelerator()); + + + action.putValue("hideActionText", anno.hideActionText()); + action.putValue(Action.SELECTED_KEY, anno.selected()); + action.setEnabled(anno.enabled()); + + return anno; + } +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabContentConfig.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabContentConfig.java new file mode 100644 index 0000000..24ca7c8 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabContentConfig.java @@ -0,0 +1,60 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.tab; + +import jaxx.runtime.swing.JAXXTab; + +import javax.swing.JTabbedPane; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Pour enregister un tab + * + * @author tchemit <chemit@codelutin.com> + */ +@Retention(RetentionPolicy.RUNTIME) + +@Target(ElementType.FIELD) + +public @interface TabContentConfig { + + Class<? extends TabModel> model(); + + Class<? extends JAXXTab> impl(); + + Class<? extends JTabbedPane> parentImpl(); + + boolean useToogle() default false; + + String name(); + + String shortDescription(); + + String[] dynamicFields() default {}; + +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabFactory.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabFactory.java new file mode 100644 index 0000000..eb506e0 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabFactory.java @@ -0,0 +1,243 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* +* \#\#% Copyright (C) 2002, 2003, 2004, 2005, 2006, 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.nuiton.jaxx.tab; + +import jaxx.runtime.JAXXObject; +import jaxx.runtime.swing.JAXXTab; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JTabbedPane; +import java.awt.Component; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +/** + * Une usine pour les Tabs, leur configs et leur modèles + * + * @author tchemit <chemit@codelutin.com> + * @see TabContentConfig + * @see TabModel + */ + +public abstract class TabFactory { + + /** Logger */ + protected static Log log = LogFactory.getLog(TabFactory.class); + + /** dictionary of configs */ + protected Map<String, TabContentConfig> configs; + + /** dictionary of instanciated actions */ + protected Map<String, JAXXTab> cache; + + /** dictionary of instanciated models */ + protected Map<String, TabModel> models; + + protected abstract Map<String, TabContentConfig> initFactory(); + + protected abstract void initTab(JAXXTab tab, String tabName, TabContentConfig config); + + protected JAXXTab newTab(String tabName) { + + checkRegistredConfig(tabName); + + // try in cache + if (cache.containsKey(tabName)) { + // use cached tab + return cache.get(tabName); + } + + TabContentConfig config = configs.get(tabName); + + JAXXTab instance; + try { + instance = config.impl().newInstance(); + if (log.isDebugEnabled()) { + log.debug("new tab : " + instance); + } + + cache.put(tabName, instance); + + initJAXXTab(config, instance); + initTab(instance, tabName, config); + + return instance; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Set<String> keySet() { + return cache.keySet(); + } + + public TabContentConfig getConfig(String tabName) { + checkRegistredConfig(tabName); + return configs.get(tabName); + } + + public JAXXTab getUI(String tabName) { + return cache.get(tabName); + } + + public TabModel getModel(String tabName, Object... params) { + + if (models.containsKey(tabName)) { + return models.get(tabName); + } + TabContentConfig config = getConfig(tabName); + TabModel tabModel; + try { + tabModel = initTabModel(config, params); + if (log.isDebugEnabled()) { + log.debug("new tab model : " + tabModel); + } + models.put(tabName, tabModel); + } catch (Exception e) { + throw new RuntimeException(e); + } + return tabModel; + } + + protected TabModel initTabModel(TabContentConfig config, Object... params) throws InstantiationException, IllegalAccessException { + TabModel tabModel; + tabModel = config.model().newInstance(); + return tabModel; + } + + public void showTab(final JTabbedPane container, String tabName) { + + TabContentConfig config = getConfig(tabName); + + JAXXTab comp = newTab(tabName); + + int index = getTabIndex(container, comp); + if (index == -1) { + registerTab(container, tabName, config, comp); + } + + container.setSelectedComponent(comp); + } + + public void closeTab(JTabbedPane container, String tabName) { + + TabContentConfig config = getConfig(tabName); + + final JComponent comp = cache.get(tabName); + + int index = getTabIndex(container, comp); + if (index != -1) { + container.removeTabAt(index); + if (log.isDebugEnabled()) { + log.debug(config + " index " + index); + } + } + } + + public int getTabIndex(final JTabbedPane container, JComponent comp) { + if (container != null && comp != null) { + for (int i = 0; i < container.getTabCount(); i++) { + Component o = container.getComponentAt(i); + if (o.equals(comp)) { + return i; + } + } + } + return -1; + } + + public void resetCache() { + cache.clear(); + models.clear(); + } + + + protected TabFactory() { + configs = initFactory(); + cache = new TreeMap<String, JAXXTab>(); + models = new TreeMap<String, TabModel>(); + } + + protected JComponent addTabHeader(final JTabbedPane container, final String tabName, final TabContentConfig config, final JAXXTab comp) { + // by default, no tab header + return null; + } + + protected void registerTab(final JTabbedPane container, final String tabName, final TabContentConfig config, final JAXXTab comp) { + + container.addTab(tabName, comp); + + JComponent header = addTabHeader(container, tabName, config, comp); + + if (header != null) { + + container.setTabComponentAt(container.getTabCount() - 1, header); + } + } + + @SuppressWarnings({"unchecked"}) + protected void initJAXXTab(TabContentConfig config, JAXXTab instance) throws NoSuchFieldException, IllegalAccessException { + if (instance instanceof JAXXObject) { + JAXXObject ui = (JAXXObject) instance; + for (String dynamicField : config.dynamicFields()) { + String dynamciName = dynamicField + '_' + config.name(); + Object obj = ui.getObjectById(dynamicField); + Field m = ui.getClass().getDeclaredField("$objectMap"); + m.setAccessible(true); + Map<Object, Object> map = (Map<Object, Object>) m.get(ui); + map.put(dynamciName, obj); + } + } + } + + protected void checkRegistredConfig(String tabName) { + if (!configs.containsKey(tabName)) { + throw new IllegalStateException("can not find a registered TabContentConfig for tab name " + tabName); + } + } + +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabModel.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabModel.java new file mode 100644 index 0000000..52bff41 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/tab/TabModel.java @@ -0,0 +1,54 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 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.nuiton.jaxx.tab; + +import java.io.Serializable; + +/** @author tchemit <chemit@codelutin.com> */ +public interface TabModel extends Serializable { + + String getName(); + + void setName(String name); + +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/AbstractUIAction.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/AbstractUIAction.java new file mode 100644 index 0000000..da36bc0 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/AbstractUIAction.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @param <H> type of handler + * @author tchemit <chemit@codelutin.com> */ +public abstract class AbstractUIAction<H extends DialogUIHandler<?, ?>> extends javax.swing.AbstractAction { + + protected static Log log = LogFactory.getLog(AbstractUIAction.class); + + protected transient DialogUI<? extends H> ui; + + private static final long serialVersionUID = 1L; + + protected AbstractUIAction(String name, javax.swing.Icon icon, DialogUI<? extends H> ui) { + super(name, icon); + this.ui = ui; + } + + protected H getHandler() { + checkInit(); + return ui.getHandler(); + } + + protected void setUi(DialogUI<? extends H> ui) { + this.ui = ui; + } + + public DialogUI<? extends H> getUi() { + return ui; + } + + protected void checkInit() throws IllegalStateException { + /*if (ui == null) { + throw new IllegalStateException("no handler, nor ui referenced in " + this); + } */ + } + +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUI.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUI.java new file mode 100644 index 0000000..e5fa346 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUI.java @@ -0,0 +1,147 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.lang.reflect.Constructor; + +/** + * A abstract dialog contract to be realised by a dialogUI (WindowEvent adapter) + * <p/> + * TODO : make jaxx authorized implementing interface for root tag :) + * + * @param <H> type of handler + * @author tchemit <chemit@codelutin.com> + */ +public abstract class DialogUI<H extends DialogUIHandler<?,?>> extends JDialog implements WindowListener { + + protected static final Log log = LogFactory.getLog(DialogUI.class); + + public AbstractAction newAction(Class<?> actionClass, Object... params) { + Constructor<?> constructor = null; + for (Constructor<?> cons : actionClass.getConstructors()) { + Class<?>[] prototype = cons.getParameterTypes(); + if (prototype.length > 0 && DialogUI.class.isAssignableFrom(prototype[0])) { + // use this constructor + constructor = cons; + break; + } + } + if (constructor == null) { + throw new IllegalStateException("could not find a matching constructor for " + actionClass); + } + + // wrap params + Object[] parameters = new Object[1 + params.length]; + parameters[0] = this; + System.arraycopy(params, 0, parameters, 1, params.length); + try { + AbstractAction action = (AbstractAction) constructor.newInstance(parameters); + if (log.isInfoEnabled()) { + log.info(action); + } + return action; + } catch (Exception e) { + throw new IllegalStateException("could not init the action " + actionClass + " for reason : " + e.getMessage()); + } + } + + private H handler; + + public abstract AbstractButton getHelp(); + + public abstract Object getObjectById(String s); + + protected DialogUI() { + UIHelper.setQuitAction(this); + addWindowListener(this); + //TODO will be handled by jaxx with javax.help... + //getHelp().setAction(newAction(HelpAction.class)); + } + + public H getHandler() { + return handler; + } + + public void setHandler(H handler) { + this.handler = handler; + } + + protected ImageIcon createActionIcon(String name) { + return UIHelper.createActionIcon(name); + } + + @Override + public void windowOpened(WindowEvent e) { + } + + @Override + public void windowClosed(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowActivated(WindowEvent e) { + } + + @Override + public void windowDeactivated(WindowEvent e) { + } + + @Override + public synchronized void addWindowListener(WindowListener l) { + super.addWindowListener(l); + if (log.isDebugEnabled()) { + log.debug("after added (" + getWindowListeners().length + ") : " + l); + } + } + + @Override + public synchronized void removeWindowListener(WindowListener l) { + super.removeWindowListener(l); + if (log.isDebugEnabled()) { + log.debug("after removed (" + getWindowListeners().length + ") : " + l); + } + } +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIDef.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIDef.java new file mode 100644 index 0000000..335e2a7 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIDef.java @@ -0,0 +1,248 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import static org.nuiton.i18n.I18n._; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.ImageIcon; +import java.lang.reflect.Constructor; + +/** + * Definition of an ui, with his model, handler and ui class definitions. + * <p/> + * The class contains also a shared instace of concrete ui. + * + * @param <M> type of model + * @param <U> type of ui + * @param <H> type of handler + * @author tchemit <chemit@codelutin.com> + */ +public class DialogUIDef<M extends DialogUIModel, U extends DialogUI<H>, H extends DialogUIHandler<M, U>> implements java.io.Serializable { + + static protected final Log log = LogFactory.getLog(DialogUIDef.class); + + public static <M extends DialogUIModel, U extends DialogUI<H>, H extends DialogUIHandler<M, U>> DialogUIDef<M, U, H> newDef(Class<H> handlerClass, Class<U> uiClass, Class<M> modelClass, String showActionLibelle, String showActionTip, String uiTitle) { + DialogUIDef<M, U, H> result; + result = new DialogUIDef<M, U, H>(handlerClass, uiClass, modelClass, showActionLibelle, showActionTip, uiTitle); + return result; + } + + /** + * model class + */ + private final Class<M> modelClass; + + /** + * handler class + */ + private final Class<H> handlerClass; + + /** + * abstract ui class + */ + private final Class<U> uiClass; + + /** + * concrete lookup ui class + */ + private Class<? extends U> uiImplClass; + + /** + * shared instance of ui + */ + protected U uiInstance; + + /** + * unique name of ui def + */ + protected final String name; + + protected final String uiTitle; + protected final String showActionLibelle; + protected final String showActionTip; + + protected ImageIcon showUIActionIcon; + + + private static final long serialVersionUID = 1L; + + private DialogUIDef(Class<H> handlerClass, Class<U> uiClass, Class<M> modelClass, + String showActionLibelle, String showActionTip, String uiTitle) { + this.handlerClass = handlerClass; + this.uiClass = uiClass; + this.modelClass = modelClass; + this.showActionLibelle = showActionLibelle; + this.name = uiClass.getSimpleName().toLowerCase(); + this.showActionTip = showActionTip; + this.uiTitle = uiTitle; + } + + public Class<U> getUiClass() { + return uiClass; + } + + public Class<H> getHandlerClass() { + return handlerClass; + } + + public Class<M> getModelClass() { + return modelClass; + } + + public Class<? extends U> getUiImplClass() { + return uiImplClass; + } + + public String getUiTitle() { + return _(uiTitle); + } + + public String getShowActionLibelle() { + return _(showActionLibelle); + } + + public String getShowActionTip() { + return _(showActionTip); + } + + public ImageIcon getShowUIActionIcon() { + if (showUIActionIcon == null) { + showUIActionIcon = UIHelper.createActionIcon("show-" + name); + } + return showUIActionIcon; + } + + @SuppressWarnings({"unchecked"}) + public void setUiImplClass(Class<?> uiImplClass) { + this.uiImplClass = (Class<? extends U>) uiImplClass; + } + + @Override + public boolean equals(Object o) { + return this == o || o instanceof DialogUIDef<?,?,?> && uiClass.equals(((DialogUIDef<?,?,?>) o).uiClass); + } + + @Override + public int hashCode() { + return uiClass.hashCode(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(super.toString()).append('<'); + sb.append(printClass("handler", handlerClass, true)); + sb.append(printClass("model", modelClass, true)); + sb.append(printClass("ui", uiClass, true)); + sb.append(printClass("uiImpl", uiImplClass, false)); + return sb.toString(); + } + + protected U getUiInstance() { + // no lazy instanciation, to control ui instanciation... + /*if (uiInstance == null) { + if (uiImplClass == null) { + throw new IllegalStateException("no concrete ui impl found in " + this); + } + synchronized (this) { + try { + uiInstance = uiImplClass.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("could not instanciate ui " + this,e); + } + } + }*/ + return uiInstance; + } + + protected void setUiInstance(U uiInstance) { + this.uiInstance = uiInstance; + } + + protected U newUI() { + if (uiImplClass == null) { + throw new IllegalStateException("no concrete ui impl found in " + this); + } + try { + U result = uiImplClass.newInstance(); + log.info(result); + return result; + } catch (Exception e) { + throw new IllegalStateException("could not instanciate ui " + this, e); + } + } + + protected M newModel() { + if (modelClass == null) { + throw new IllegalStateException("no model impl found in " + this); + } + try { + M model = modelClass.newInstance(); + log.info(model); + return model; + } catch (Exception e) { + throw new IllegalStateException("could not instanciate ui " + this, e); + } + } + + protected H newHandler(U ui, M model, Object... params) { + if (handlerClass == null) { + throw new IllegalStateException("no handler impl found in " + this); + } + try { + Class<?>[] prototype = getHandlerPrototype(params); + Object[] parameters = getHandlerParameters(ui, model, params); + H result = handlerClass.getConstructor(prototype).newInstance(parameters); + log.info(result); + return result; + } catch (Exception e) { + throw new IllegalStateException("could not instanciate ui " + this, e); + } + } + + protected Object[] getHandlerParameters(U ui, M model, Object[] params) { + Object[] result = new Object[2 + params.length]; + result[0] = ui; + result[1] = model; + System.arraycopy(params, 0, result, 2, params.length); + return result; + } + + protected Class<?>[] getHandlerPrototype(Object[] params) { + int length = params.length; + for (Constructor<?> constructor : handlerClass.getConstructors()) { + Class<?>[] prototype = constructor.getParameterTypes(); + if (prototype.length == 2 + length && prototype[0] == uiClass && prototype[1] == modelClass) { + return prototype; + } + } + throw new IllegalStateException("could not find a matching constructor in " + handlerClass); + } + + protected String printClass(String s, Class<?> aClass, boolean notLast) { + return s + ':' + (aClass == null ? null : aClass.getSimpleName()) + (notLast ? ", " : ">"); + } +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIHandler.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIHandler.java new file mode 100644 index 0000000..08d03b9 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIHandler.java @@ -0,0 +1,82 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.event.WindowListener; +import java.beans.PropertyChangeListener; + +/** + * DialogUI handler + * + * @param <M> type of model + * @param <U> type of ui + * @author tchemit <chemit@codelutin.com> + */ +public abstract class DialogUIHandler<M extends DialogUIModel, U extends DialogUI<? extends DialogUIHandler<?,?>>> implements PropertyChangeListener { + + protected static Log log = LogFactory.getLog(DialogUIHandler.class); + + /** ui handled */ + private U ui; + + /** model handled */ + private M model; + + protected DialogUIHandler(U ui, M model) { + this.ui = ui; + this.model = model; + } + + public U getUi() { + return ui; + } + + public M getModel() { + return model; + } + + public void init() { + if (model == null) { + throw new IllegalStateException("no model was defined for " + this); + } + model.addPropertyChangeListener(this); + } + + public void dispose() { + model.dispose(); + for (WindowListener windowListener : getUi().getWindowListeners()) { + getUi().removeWindowListener(windowListener); + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + dispose(); + } +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIModel.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIModel.java new file mode 100644 index 0000000..6bd0b44 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/DialogUIModel.java @@ -0,0 +1,107 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * Abstract ui model, with property change support. + * + * @author tchemit <chemit@codelutin.com> + */ +public abstract class DialogUIModel { + + static protected final Log log = LogFactory.getLog(DialogUIModel.class); + + /** support for change properties support */ + protected PropertyChangeSupport changeSupport; + + public synchronized void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + if (listener == null) { + return; + } + if (changeSupport == null) { + changeSupport = new PropertyChangeSupport(this); + } + changeSupport.addPropertyChangeListener(propertyName, listener); + } + + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + if (listener == null) { + return; + } + if (changeSupport == null) { + changeSupport = new PropertyChangeSupport(this); + } + changeSupport.addPropertyChangeListener(listener); + } + + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + if (listener == null || changeSupport == null) { + return; + } + changeSupport.removePropertyChangeListener(listener); + } + + public synchronized void removePropertyChangeListeners() { + if (changeSupport == null) { + return; + } + for (PropertyChangeListener listener : getPropertyChangeListeners()) { + changeSupport.removePropertyChangeListener(listener); + } + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + if (changeSupport == null) { + return new PropertyChangeListener[0]; + } + return changeSupport.getPropertyChangeListeners(); + } + + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + if (changeSupport == null || (oldValue == null && newValue == null) || + (oldValue != null && oldValue.equals(newValue))) { + return; + } + changeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + public void dispose() { + for (PropertyChangeListener listener : changeSupport.getPropertyChangeListeners()) { + changeSupport.removePropertyChangeListener(listener); + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + dispose(); + } +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/FactoryWindowListener.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/FactoryWindowListener.java new file mode 100644 index 0000000..5d08f96 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/FactoryWindowListener.java @@ -0,0 +1,94 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * A windowListenr for ui managed by {@link UIFactory}. + * <p/> + * To be used when all ui from factory are closed, via {@link #allWindowsClosed(WindowEvent)} method. + * + * @author tchemit <chemit@codelutin.com> + */ +public abstract class FactoryWindowListener extends WindowAdapter { + + /** + * method to be invoked when all ui registred in factory are really disposed. + * + * @param e event + */ + public abstract void allWindowsClosed(WindowEvent e); + + /** underlying factory of ui */ + private UIFactory factory; + + /** flag to make sure {@link #allWindowsClosed(WindowEvent)} is called only once. */ + private boolean wasClosed; + + @Override + public void windowClosed(WindowEvent e) { + if (UIFactory.log.isDebugEnabled()) { + UIFactory.log.debug(this + " : " + e); + } + if (e.getWindow().isVisible()) { + // only deal with real closed and none visible windows... + return; + } + for (DialogUIDef<?,?,?> def : factory.getDefs()) { + DialogUI<?> ui = def.uiInstance; + if (ui != null && ui.isVisible()) { + // at least one ui visible, do not close all + return; + } + } + + if (wasClosed) { + // make sure to process only once + return; + } + if (UIFactory.log.isInfoEnabled()) { + UIFactory.log.info("closing factory listener " + this); + } + + synchronized (this) { + try { + allWindowsClosed(e); + } finally { + wasClosed = true; + factory.removeFactoryWindowListener(this); + } + } + } + + protected UIFactory getFactory() { + return factory; + } + + protected void setFactory(UIFactory factory) { + this.factory = factory; + } +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/FormElement.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/FormElement.java new file mode 100644 index 0000000..b06819a --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/FormElement.java @@ -0,0 +1,41 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +/** + * @param <U> type of dialog + * @author tchemit <chemit@codelutin.com> */ +public interface FormElement<U extends DialogUI<?>> { + + String name(); + + int ordinal(); + + Object getValue(U ui); + + void setValue(U ui, String value); + + javax.swing.JLabel getLabel(U ui); +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/ShowUIAction.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/ShowUIAction.java new file mode 100644 index 0000000..4b16169 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/ShowUIAction.java @@ -0,0 +1,150 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.ActionEvent; + +/** + * @param <M> type of model + * @param <U> type of ui + * @param <H> type of handler + * @author tchemit <chemit@codelutin.com> */ +public abstract class ShowUIAction<M extends DialogUIModel, U extends DialogUI<H>, H extends DialogUIHandler<M, U>> extends javax.swing.AbstractAction { + + protected static Log log = LogFactory.getLog(AbstractUIAction.class); + + protected transient DialogUI<?> ui; + + private static final long serialVersionUID = 1L; + + protected DialogUIDef<M, U, H> uiDef; + + protected transient UIFactory factory; + + protected String position; + + protected boolean undecorated = true; + + protected U initUI(ActionEvent e) { + return getFactory().getUI(uiDef); + } + + public ShowUIAction(DialogUI<?> ui, DialogUIDef<M, U, H> uiDef, UIFactory factory, boolean showText) { + super(uiDef.getShowActionLibelle(), uiDef.getShowUIActionIcon()); + this.ui = ui; + this.uiDef = uiDef; + String name = (String) getValue(NAME); + putValue(DISPLAYED_MNEMONIC_INDEX_KEY, name.length() - 1); + putValue(ACCELERATOR_KEY, (int) name.charAt(name.length() - 1)); + if (!showText) { + putValue(NAME, null); + } + putValue(SHORT_DESCRIPTION, uiDef.getShowActionTip()); + this.factory = factory; + } + + public DialogUI<?> getUi() { + return ui; + } + + public DialogUIDef<M, U, H> getUiDef() { + return uiDef; + } + + public UIFactory getFactory() { + return factory; + } + + public void setUiDef(DialogUIDef<M, U, H> uiDef) { + this.uiDef = uiDef; + } + + public void setPosition(String position) { + this.position = position; + } + + public void setUndecorated(boolean undecorated) { + this.undecorated = undecorated; + } + + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + checkInit(); + U gui = initUI(e); + gui.setTitle(uiDef.getUiTitle()); + log.info(gui.getTitle()); + //TODO ui.setUndecorated(undecorated); + setPosition(this.getUi(), gui, position); + + gui.setVisible(true); + } + + protected void setPosition(javax.swing.JDialog parentUI, javax.swing.JDialog ui, String position) { + if (position == null || parentUI == null) { + return; + } + Point parentLocation = parentUI.getLocationOnScreen(); + Dimension parentSize = parentUI.getSize(); + + if (position.equals("bottom-left")) { + int top = (int) (parentLocation.getY() + parentSize.getHeight()); + int left = (int) (parentLocation.getX()); + Point newLocation = new Point(left, top); + newLocation.setLocation(left, top); + ui.setLocation(newLocation); + return; + } + if (position.equals("top-left")) { + int top = (int) (parentLocation.getY()); + int left = (int) (parentLocation.getX()); + Point newLocation = new Point(left, top); + newLocation.setLocation(left, top); + ui.setLocation(newLocation); + return; + } + if (position.equals("top-right")) { + int top = (int) (parentLocation.getY()); + int left = (int) (parentLocation.getX() + parentSize.getWidth()); + Point newLocation = new Point(left, top); + newLocation.setLocation(left, top); + ui.setLocation(newLocation); + return; + } + if (position.equals(("center"))) { + //TODO + } + } + + protected void checkInit() throws IllegalStateException { + if (factory == null) { + throw new IllegalStateException("no factory found in " + this); + } + } +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIFactory.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIFactory.java new file mode 100644 index 0000000..188710f --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIFactory.java @@ -0,0 +1,193 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.StringUtil; + +import javax.swing.event.EventListenerList; +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +/** + * Factory for UI, using a cache and a provider to find ui implementations. + * + * @author tchemit <chemit@codelutin.com> + */ +public class UIFactory { + + static protected final Log log = LogFactory.getLog(UIFactory.class); + + private final String applicationName; + + private final DialogUIDef<?,?,?>[] defs; + + private final EventListenerList listeners; + + public UIFactory(String applicationName, DialogUIDef<?,?,?>[] defs, FactoryWindowListener... listeners) { + this.applicationName = applicationName; + this.listeners = new EventListenerList(); + for (FactoryWindowListener listener : listeners) { + listener.setFactory(this); + addFactoryWindowListener(listener); + } + this.defs = defs; + long t0 = System.nanoTime(); + if (log.isDebugEnabled()) { + log.debug("start at " + new java.util.Date()); + } + try { + init(); + } catch (Exception e) { + log.error(e); + throw new RuntimeException(e); + } finally { + if (log.isDebugEnabled()) { + log.info("end in " + StringUtil.convertTime(t0, System.nanoTime())); + } + } + } + + public void addFactoryWindowListener(FactoryWindowListener l) { + listeners.add(FactoryWindowListener.class, l); + if (log.isDebugEnabled()) { + log.debug("after added (" + listeners.getListenerCount() + ") : " + l); + } + } + + public void removeFactoryWindowListener(FactoryWindowListener l) { + listeners.remove(FactoryWindowListener.class, l); + for (DialogUIDef<?,?,?> def : getDefs()) { + if (def.uiInstance != null) { + def.uiInstance.removeWindowListener(l); + } + } + if (log.isDebugEnabled()) { + log.debug(" after removed (" + listeners.getListenerCount() + ") : " + l); + } + if (listeners.getListenerCount(FactoryWindowListener.class) == 0) { + // close for real factory + close(); + } + } + + public void close() { + log.info(this + " at " + new java.util.Date()); + for (DialogUIDef<?, ?, ?> def : defs) { + DialogUI<?> ui = def.uiInstance; + if (ui != null) { + ui.getHandler().dispose(); + def.uiInstance = null; + } + } + if (listeners.getListenerCount(FactoryWindowListener.class) > 0) { + log.warn("some listeners where not properly removed, force deletion..."); + for (FactoryWindowListener listener : listeners.getListeners(FactoryWindowListener.class)) { + removeFactoryWindowListener(listener); + } + } + + } + + protected void init() { + + UIProvider[] providers = detectProviders(); + + for (DialogUIDef<?, ?, ?> def : defs) { + initDef(providers, def); + if (def.getUiImplClass() == null) { + throw new IllegalStateException("could not find implementation for ui def " + def); + } + } + } + + protected void initDef(UIProvider[] providers, DialogUIDef<?, ?, ?> def) { + for (UIProvider provider : providers) { + Class<?> uiImplClass = provider.findUIImplementation(def); + if (uiImplClass != null) { + if (log.isDebugEnabled()) { + log.debug("init done for " + def); + } + // ui implementation was found + break; + } + } + } + + protected UIProvider[] detectProviders() { + long t0 = System.nanoTime(); + List<UIProvider> providers = new ArrayList<UIProvider>(); + for (UIProvider provider : ServiceLoader.load(UIProvider.class)) { + if (applicationName.equals(provider.getApplicationName())) { + if (log.isDebugEnabled()) { + log.debug("provider detected [" + provider + ']'); + } + providers.add(provider); + } + } + log.info("found " + providers.size() + " ui provider(s) in " + StringUtil.convertTime(t0, System.nanoTime()) + " : " + providers); + return providers.toArray(new UIProvider[providers.size()]); + } + + protected DialogUIDef<?,?,?>[] getDefs() { + return defs; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + close(); + } + + public <M extends DialogUIModel, U extends DialogUI<H>, H extends DialogUIHandler<M, U>> U getUI(DialogUIDef<M, U, H> uiType, Object... params) { + U ui = uiType.uiInstance; + if (ui == null) { + try { + ui = uiType.newUI(); + M model = uiType.newModel(); + H handler = uiType.newHandler(ui, model, params); + registerUI(uiType, ui, handler); + } catch (Exception e) { + throw new IllegalStateException("could not instanciate ui handler " + uiType + " for reason : " + e.getMessage(), e); + } + } + return ui; + } + + protected <M extends DialogUIModel, U extends DialogUI<H>, H extends DialogUIHandler<M, U>> void registerUI(DialogUIDef<M, U, H> uiType, U ui, H handler) { + ui.setHandler(handler); + handler.init(); + uiType.setUiInstance(ui); + for (FactoryWindowListener listener : listeners.getListeners(FactoryWindowListener.class)) { + if (log.isDebugEnabled()) { + log.debug("----- addFactoryWindowListener " + listener + " to " + ui); + } + ui.addWindowListener(listener); + } + } + +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIHelper.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIHelper.java new file mode 100644 index 0000000..1522611 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIHelper.java @@ -0,0 +1,95 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 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.nuiton.jaxx.util; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; + +/** + * Ui helper class. + * + * @author tchemit <chemit@codelutin.com> + */ +public class UIHelper { + + public static ImageIcon createImageIcon(String path) { + java.net.URL imgURL = UIHelper.class.getResource("/icons/" + path); + if (imgURL != null) { + return new ImageIcon(imgURL); + } else { + throw new IllegalArgumentException("could not find icon " + path); + } + } + + /** + * Attach to <code>ui</code> an abort action,accessible by <code>ESC</code> key. + * + * @param ui ui + */ + public static void setQuitAction(final JDialog ui) { + JRootPane rootPane = ui.getRootPane(); + + Action quitAction = new AbstractAction("quit") { + private static final long serialVersionUID = -869095664995763057L; + + @Override + public void actionPerformed(ActionEvent e) { + ui.dispose(); + } + }; + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "quit"); + rootPane.getActionMap().put("quit", quitAction); + ui.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + } + + public static ImageIcon createActionIcon(String name) { + return createImageIcon("action-" + name + ".png"); + } + +} diff --git a/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIProvider.java b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIProvider.java new file mode 100644 index 0000000..6388abc --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/java/org/nuiton/jaxx/util/UIProvider.java @@ -0,0 +1,96 @@ +/* + * #%L + * JAXX :: Swing-Action + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.nuiton.jaxx.util; + +/** @author tchemit <chemit@codelutin.com> */ +public abstract class UIProvider { + + /** the name of application using this provider */ + protected String applicationName; + + /** the name of ui implementation used by this provider */ + protected String providerName; + + /** array of ui implementations */ + protected Class<?>[] implementations; + + protected UIProvider(String applicationName, String providerName, Class<?>... implementations) { + this.applicationName = applicationName; + this.providerName = providerName; + this.implementations = implementations; + } + + public String getProviderName() { + return providerName; + } + + public String getApplicationName() { + return applicationName; + } + + public Class<?>[] getImplementations() { + return implementations; + } + + public Class<?> findUIImplementation(DialogUIDef<?, ?, ?> def) { + Class<? extends DialogUI<?>> uiClass = def.getUiClass(); + for (Class<?> klass : implementations) { + if (uiClass.isAssignableFrom(klass)) { + def.setUiImplClass(klass); + return klass; + } + } + return null; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(super.toString()).append('<'); + sb.append(printClass("application", applicationName, true)); + sb.append(printClass("provider", providerName, true)); + sb.append(printClass("uis", implementations.length, false)); + return sb.toString(); + } + + protected String printClass(String s, Object aClass, boolean notLast) { + return s + ':' + (aClass == null ? null : aClass) + (notLast ? ", " : ">"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof UIProvider)) return false; + + UIProvider that = (UIProvider) o; + return applicationName.equals(that.applicationName) && providerName.equals(that.providerName); + + } + + @Override + public int hashCode() { + return (31 * applicationName.hashCode()) + providerName.hashCode(); + } + +} \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/trunk/jaxx-swing-action/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000..1b41cf0 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +org.nuiton.jaxx.action.ActionAnnotationProcessing \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/main/resources/i18n/jaxx-swing-action-en_GB.properties b/trunk/jaxx-swing-action/src/main/resources/i18n/jaxx-swing-action-en_GB.properties new file mode 100644 index 0000000..4c960a0 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/resources/i18n/jaxx-swing-action-en_GB.properties @@ -0,0 +1,10 @@ +jaxx.action.done=Action '%1$s' done. +jaxx.error.close.actions.file=Error while closing file of actions +jaxx.error.load.actions.class=Error while loading actions +jaxx.error.load.actions.file=Error while loading file of actions +lutinui.config.cancel=Cancel +lutinui.config.cancel.tooltip=Cancel and quit +lutinui.config.reset=Reset +lutinui.config.reset.tooltip=Reset configuration +lutinui.config.save=Save +lutinui.config.save.tooltip=Save configuration and quit diff --git a/trunk/jaxx-swing-action/src/main/resources/i18n/jaxx-swing-action-fr_FR.properties b/trunk/jaxx-swing-action/src/main/resources/i18n/jaxx-swing-action-fr_FR.properties new file mode 100644 index 0000000..fa697e6 --- /dev/null +++ b/trunk/jaxx-swing-action/src/main/resources/i18n/jaxx-swing-action-fr_FR.properties @@ -0,0 +1,10 @@ +jaxx.action.done=Action '%1$s' termin\u00E9e. +jaxx.error.close.actions.file=Erreur lors de la fermeture du fichier d'actions +jaxx.error.load.actions.class=Erreur lors du chargement des actions +jaxx.error.load.actions.file=Erreur lors du chargement du fchier d'actions +lutinui.config.cancel=Annuler +lutinui.config.cancel.tooltip=Annuler les modification et quitter +lutinui.config.reset=R\u00E9initialiser +lutinui.config.reset.tooltip=R\u00E9initialiser la configuration +lutinui.config.save=Sauver +lutinui.config.save.tooltip=Sauver la configuration et quitter diff --git a/trunk/jaxx-swing-action/src/site/rst/Todo.rst b/trunk/jaxx-swing-action/src/site/rst/Todo.rst new file mode 100644 index 0000000..eb4c977 --- /dev/null +++ b/trunk/jaxx-swing-action/src/site/rst/Todo.rst @@ -0,0 +1,30 @@ +==== +TODO +==== + +.. - +.. * #%L +.. * JAXX :: Swing-Action +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +a faire \ No newline at end of file diff --git a/trunk/jaxx-swing-action/src/site/rst/index.rst b/trunk/jaxx-swing-action/src/site/rst/index.rst new file mode 100644 index 0000000..f0c4978 --- /dev/null +++ b/trunk/jaxx-swing-action/src/site/rst/index.rst @@ -0,0 +1,37 @@ +jaxx-swing-action +================= + +.. contents:: + +.. - +.. * #%L +.. * JAXX :: Swing-Action +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +Présentation +------------ + +Framework de gestion des actions et onglets TODO + +**Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes +librairies.** diff --git a/trunk/jaxx-swing-action/src/site/site_fr.xml b/trunk/jaxx-swing-action/src/site/site_fr.xml new file mode 100644 index 0000000..923d9c1 --- /dev/null +++ b/trunk/jaxx-swing-action/src/site/site_fr.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Swing-Action + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <src>../jaxx.png</src> + <href>index.html</href> + </bannerLeft> + + <bannerRight> + <src>http://www.codelutin.com/images/lutinorange-codelutin.png</src> + <href>http://www.codelutin.com</href> + </bannerRight> + + <skin> + <groupId>org.apache.maven.skins</groupId> + <artifactId>maven-fluido-skin</artifactId> + <version>1.2.1</version> + </skin> + + <custom> + <fluidoSkin> + <topBarEnabled>true</topBarEnabled> + <googleSearch/> + <sideBarEnabled>false</sideBarEnabled> + <searchEnabled>true</searchEnabled> + <sourceLineNumbersEnabled>true</sourceLineNumbersEnabled> + </fluidoSkin> + </custom> + + <publishDate position="right" format="dd/MM/yyyy"/> + <version position="right"/> + + <body> + <links> + <item name="nuiton.org" href="http://www.nuiton.org"/> + <item name="CodeLutin" href="http://codelutin.com"/> + <item name="Libre-Entreprise" href="http://www.libre-entreprise.org/"/> + </links> + + <breadcrumbs> + <item name="${project.name}" href="index.html" /> + </breadcrumbs> + + <menu ref="parent"/> + + <menu name="Utilisateur"/> + + <menu ref="reports"/> + + <menu ref="modules"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> diff --git a/trunk/jaxx-validator/LICENSE.txt b/trunk/jaxx-validator/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/jaxx-validator/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/jaxx-validator/README.txt b/trunk/jaxx-validator/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/trunk/jaxx-validator/changelog.txt b/trunk/jaxx-validator/changelog.txt new file mode 100644 index 0000000..e69de29 diff --git a/trunk/jaxx-validator/pom.xml b/trunk/jaxx-validator/pom.xml new file mode 100644 index 0000000..16e504c --- /dev/null +++ b/trunk/jaxx-validator/pom.xml @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="UTF-8"?> + <!-- + #%L + JAXX :: Validator + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jaxx</artifactId> + <version>2.5.2</version> + </parent> + + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-validator</artifactId> + + <dependencies> + + <!-- sibiling dependencies --> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <groupId>javax.help</groupId> + <artifactId>javahelp</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JAXX :: Validator</name> + <description>JAXX Validator api</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <build> + <plugins> + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + </goals> + <configuration> + <treateDefaultEntry>false</treateDefaultEntry> + <entries> + <entry> + <basedir>src/main/java/jaxx/runtime/validator</basedir> + </entry> + </entries> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <id>attach-test</id> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </pluginManagement> + </build> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <profiles> + <!-- perform only on a release stage when using the maven-release-plugin --> + <profile> + <id>release-profile</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <build> + <plugins> + + <!-- always compute tests source jar --> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <executions> + <execution> + <id>attach-test-sources</id> + </execution> + </executions> + </plugin> + + </plugins> + </build> + </profile> + </profiles> + +</project> diff --git a/trunk/jaxx-validator/src/license/THIRD-PARTY.properties b/trunk/jaxx-validator/src/license/THIRD-PARTY.properties new file mode 100644 index 0000000..e2b356b --- /dev/null +++ b/trunk/jaxx-validator/src/license/THIRD-PARTY.properties @@ -0,0 +1,21 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - BSD License +# - BSD style +# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 +# - Common Public License Version 1.0 +# - Indiana University Extreme! Lab Software License, vesion 1.1.1 +# - Lesser General Public License (LGPL) +# - Lesser General Public License (LGPL) v 3.0 +# - Lesser General Public License (LPGL) +# - Lesser General Public License (LPGL) v 2.1 +# - MIT License +# - MPL 1.1 +# - The Apache Software License, Version 2.0 +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Fri Jun 29 10:35:13 CEST 2012 +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/JAXXValidator.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/JAXXValidator.java new file mode 100644 index 0000000..f218a0c --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/JAXXValidator.java @@ -0,0 +1,65 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime; + + +import org.nuiton.validator.bean.BeanValidator; +import jaxx.runtime.validator.swing.SwingValidator; + +import javax.swing.JComponent; +import java.util.List; + +/** + * The contract of a validator-able object. + * + * @author tchemit <chemit@codelutin.com> + */ +public interface JAXXValidator { + + /** + * Obtain a validator from his id + * + * @param validatorId validator id + * @return the associated validator, or <code>null</code> if not find + */ + BeanValidator<?> getValidator(String validatorId); + + /** @return the list of ids of all registred validator */ + List<String> getValidatorIds(); + + /** + * Init the fields representation. + * <p/> + * This method is generated and should be called each time the context name + * of a validator has changed, since when using method + * {@link SwingValidator#setFieldRepresentation(String, JComponent)} + * is invoked at init, if a field is not watched for the selected context, + * then after when changing context name, the field will not be notified of any changed... + * + * @since 2.2.1 + */ + void registerValidatorFields(); + +} \ No newline at end of file diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java new file mode 100644 index 0000000..4b98db3 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java @@ -0,0 +1,361 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI; +import jaxx.runtime.validator.swing.ui.IconValidationUI; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidatorFactory; +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.BeanValidator; + +import javax.swing.JComponent; +import java.awt.Container; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/** + * La surcharge de {@link BeanValidator} pour les ui swing + * <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> + * + * @param <B> le type de bean a valider + * @author poussin <poussin@codelutin.com> + * @author tchemit <chemit@codelutin.com> + * @version 1.0 + */ +public class SwingValidator<B> extends BeanValidator<B> { + + /** Logger */ + static private final Log log = LogFactory.getLog(SwingValidator.class); + + static private final Class<? extends AbstractBeanValidatorUI> + DEFAULT_UI_CLASS = IconValidationUI.class; + + /** + * permet de faire le lien en un champs du bean et l'objet qui permet de + * l'editer + */ + protected final Map<String, JComponent> fieldRepresentation; + + /** Object servant a contenir la liste des erreurs */ + protected SwingValidatorMessageListModel errorListModel; + + /** Object servant a contenir la liste des erreurs */ + protected SwingValidatorMessageTableModel errorTableModel; + + /** ui renderer class */ + protected Class<? extends AbstractBeanValidatorUI> uiClass; + + public SwingValidator(NuitonValidatorProvider provider, + Class<B> beanClass, + String contextName, + NuitonValidatorScope... filterScopes) { + super(provider, beanClass, contextName, filterScopes); + fieldRepresentation = new HashMap<String, JComponent>(); + } + + public SwingValidator(Class<B> beanClass, + String contextName, + NuitonValidatorScope... filterScopes) { + super(NuitonValidatorFactory.getDefaultProvider(), + beanClass, + contextName, + filterScopes + ); + fieldRepresentation = new HashMap<String, JComponent>(); + } + + public SwingValidator(Class<B> beanClass, String contextName) { + this(beanClass, contextName, NuitonValidatorScope.values()); + } + + /** + * To reload a bean in the validator. + * <p/> + * This method is used to reload ui, since some editors could not exist when + * validator is init, so some messages should not be attached to an editor. + */ + public void reloadBean() { + B b = getBean(); + if (log.isInfoEnabled()) { + log.info("Will reload bean : " + b); + } + if (b != null) { + setBean(null); + setBean(b); + } + } + + public JComponent getFieldRepresentation(String fieldname) { + return fieldRepresentation.get(fieldname); + } + + public Class<? extends AbstractBeanValidatorUI> getUiClass() { + return uiClass; + } + + public void setErrorListModel( + SwingValidatorMessageListModel errorListModel) { + this.errorListModel = errorListModel; + if (errorListModel != null) { + // register the validator in the model list + errorListModel.registerValidator(this); + } + } + + public void setErrorTableModel( + SwingValidatorMessageTableModel errorTableModel) { + this.errorTableModel = errorTableModel; + if (errorTableModel != null) { + // register the validator in the model table + errorTableModel.registerValidator(this); + } + } + + public void setUiClass(Class<? extends AbstractBeanValidatorUI> uiClass) { + this.uiClass = uiClass; + } + + @Override + public void setContext(String context) { + String oldContext = getContext(); + + super.setContext(context); + + if (context == null && oldContext == null || + context != null && context.equals(oldContext)) { + + // same context do nothing + return; + } + if (fieldRepresentation != null) { + + // must reinstall ui + installUIs(); + } + } + + /** + * 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) { + boolean fieldFound = getDelegate().getEffectiveFields().contains(fieldname); + + if (!fieldFound) { + // no field registred in the validator + if (log.isWarnEnabled()) { + log.warn("the field '" + fieldname + + "' is not defined in validator (no rules on it)"); + } + return; + } + if (log.isInfoEnabled()) { + log.info("register field [" + fieldname + "] with component : " + + c.getName() + ); + } + fieldRepresentation.put(fieldname, c); + } + + public void setFieldRepresentation( + Map<String, JComponent> fieldRepresentation) { + for (Map.Entry<String, JComponent> e : fieldRepresentation.entrySet()) { + setFieldRepresentation(e.getKey(), e.getValue()); + } + } + + @Override + public SwingValidator<?> getParentValidator() { + return (SwingValidator<?>) super.getParentValidator(); + } + + public void setParentValidator(SwingValidator<?> parentValidator) { + super.setParentValidator(parentValidator); + } + + /** install ui on required components */ + public void installUIs() { + if (fieldRepresentation == null) { + throw new NullPointerException( + "fieldRepresentation is null, must init before " + + "invoking installUIs method..."); + } + + if (uiClass == null) { + // use the default one + uiClass = DEFAULT_UI_CLASS; + } + for (Entry<String, JComponent> entry : + fieldRepresentation.entrySet()) { + try { + setMessageRepresentation( + entry.getKey(), + null, + entry.getValue(), + uiClass + ); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + protected void setMessageRepresentation( + String fieldname, + JComponent old, + JComponent c, + Class<? extends AbstractBeanValidatorUI> uiClass) + throws InvocationTargetException, + IllegalAccessException, + InstantiationException, + NoSuchMethodException { + if (old == c) { + // same component, nothing to do + return; + } + + boolean fieldFound = getDelegate().getEffectiveFields().contains(fieldname); + + if (!fieldFound) { + // this case should not appear since fieldName has already been + // check in method addFieldRepresentation + return; + } + if (old != null) { + // suppression du jxlayer sous l'ancien composant + Container container = old.getParent(); + if (container instanceof JXLayer<?>) { + JXLayer<?> jx = (JXLayer<?>) container; + Object ui = jx.getUI(); + if (ui != null && ui instanceof AbstractBeanValidatorUI) { + removeBeanValidatorListener((AbstractBeanValidatorUI) ui); + } + + jx.setUI(null); + } + } + if (c != null) { + // ajout du jxlayer sous ce composant + Container container = c.getParent(); + if (container instanceof JXLayer<?>) { + JXLayer jx = (JXLayer<?>) container; + Object oldUI = jx.getUI(); + if (oldUI != null && oldUI instanceof AbstractBeanValidatorUI) { + + // supression de l'ancien layer + removeBeanValidatorListener((AbstractBeanValidatorUI) oldUI); + } + Constructor<? extends AbstractBeanValidatorUI> cons = + uiClass.getConstructor(String.class); + AbstractBeanValidatorUI ui = cons.newInstance(fieldname); + +// ui.setEnabled(true); + addBeanValidatorListener(ui); + jx.setUI(ui); + } + } + } + +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessage.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessage.java new file mode 100644 index 0000000..1c59bde --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessage.java @@ -0,0 +1,116 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.BeanValidatorMessage; + +import javax.swing.JComponent; + +/** + * The object to box a validation message within an u. + * + * @author tchemit <chemit@codelutin.com> + * @see BeanValidatorMessage + * @since 1.3 + */ +public class SwingValidatorMessage extends BeanValidatorMessage<SwingValidatorMessage> { + + private static final long serialVersionUID = 1L; + + /** the optional field's editor */ + protected JComponent editor; + + public SwingValidatorMessage(SwingValidator<?> validator, + String fieldName, + String message, + NuitonValidatorScope scope, + JComponent editor) { + super(validator, fieldName, message, scope); + this.editor = editor; + } + + public JComponent getEditor() { + return editor; + } + + /** + * @return the field name + * @deprecated since 2.3, will not be replaced + */ + @Deprecated + public String getFieldName() { + return getField(); + } + +// @Override +// public int compareTo(SwingValidatorMessage o) { +// // sort on scope +// int result = getScope().compareTo(o.getScope()); +// if (result == 0) { +// // sort on field name +// result = fieldName.compareTo(o.getField()); +// if (result == 0) { +// // sort on message +// result = message.compareTo(o.getMessage()); +// } +// } +// return result; +// } + +// @Override +// public boolean equals(Object o) { +// if (this == o) { +// return true; +// } +// if (o == null || getClass() != o.getClass()) { +// return false; +// } +// +// SwingValidatorMessage that = (SwingValidatorMessage) o; +// +// return fieldName.equals(that.fieldName) && +// message.equals(that.message) && +// scope == that.scope; +// } + +// @Override +// public int hashCode() { +// int result = fieldName.hashCode(); +// result = 31 * result + message.hashCode(); +// result = 31 * result + scope.hashCode(); +// return result; +// } + + @Override + public String toString() { + String s = scope + " - " + + (field == null ? message : field + " - " + message); + if (editor == null) { + return s; + } + return editor.getName() + " : " + s; + } +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListModel.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListModel.java new file mode 100644 index 0000000..34fd432 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListModel.java @@ -0,0 +1,194 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.BeanValidatorEvent; +import org.nuiton.validator.bean.BeanValidatorListener; + +import javax.swing.AbstractListModel; +import javax.swing.JComponent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * The model of the list of validation's messages + * + * @author tchemit <chemit@codelutin.com> + */ +public class SwingValidatorMessageListModel + extends AbstractListModel + implements BeanValidatorListener { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static Log log = LogFactory.getLog(SwingValidatorMessageListModel.class); + + /** list of registred validators */ + protected transient List<SwingValidator<?>> validators; + + /** list of messages actual displayed */ + protected List<SwingValidatorMessage> data; + + public SwingValidatorMessageListModel() { + validators = new ArrayList<SwingValidator<?>>(); + data = new ArrayList<SwingValidatorMessage>(); + } + + public boolean isEmpty() { + return getSize() == 0; + } + + public void registerValidator(SwingValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException( + "the validator " + validator + " is already registred in " + + this); + } + validators.add(validator); + validator.addBeanValidatorListener(this); + } + + public void clear() { + int i = data.size(); + if (i > 0) { + data.clear(); + fireIntervalRemoved(this, 0, i - 1); + } + } + + @Override + public int getSize() { + return data.size(); + } + + @Override + public Object getElementAt(int index) { + ensureRowIndex(index); + return data.get(index); + } + + @Override + public void onFieldChanged(BeanValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getSize() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getSize() + ") toDelete " + mustDel); + } + + SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, field, scope, true, toAdd); + } + } + + protected void ensureRowIndex(int index) throws ArrayIndexOutOfBoundsException { + if (index < -1 || index >= getSize()) { + throw new ArrayIndexOutOfBoundsException( + "the rowIndex was " + index + ", but should be int [0," + + (getSize() - 1) + "]"); + } + } + + protected void addMessages(SwingValidator<?> validator, + String field, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + JComponent editor = validator.getFieldRepresentation(field); + // add new errors + for (String error : messages) { + SwingValidatorMessage row = new SwingValidatorMessage( + validator, + field, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireIntervalAdded(this, data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireContentsChanged(this, 0, getSize() - 1); + } + } + + protected void removeMessages(SwingValidator<?> validator, + String field, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getSize() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (error.getValidator().equals(validator) && + error.getScope() == scope && + error.getField().equals(field) && + messagesToDel.contains(error.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireIntervalRemoved(this, i, i); + } + } + } + } +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListMouseListener.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListMouseListener.java new file mode 100644 index 0000000..1e53090 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListMouseListener.java @@ -0,0 +1,93 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +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 + * SwingValidatorMessageListModel} 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 tchemit <chemit@codelutin.com> + */ +public class SwingValidatorMessageListMouseListener extends MouseAdapter { + + /** Logger */ + static private Log log = + LogFactory.getLog(SwingValidatorMessageListMouseListener.class); + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + SwingValidatorMessage entry = getSelectedMessage(e); + if (entry == null) { + // no entry found + return; + } + JComponent component = entry.getEditor(); + if (component != null) { + component.requestFocus(); + } + } + } + + protected SwingValidatorMessage getSelectedMessage(MouseEvent e) { + JList list = (JList) e.getSource(); + if (!(list.getModel() instanceof SwingValidatorMessageListModel)) { + if (log.isWarnEnabled()) { + log.warn("model must be a " + + SwingValidatorMessageListModel.class + ", but was " + + list.getModel()); + } + return null; + } + + SwingValidatorMessageListModel model = + (SwingValidatorMessageListModel) list.getModel(); + int index = list.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + SwingValidatorMessage entry = + (SwingValidatorMessage) model.getElementAt(index); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java new file mode 100644 index 0000000..dfa6ff6 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageListRenderer.java @@ -0,0 +1,134 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JList; +import java.awt.Component; + +import static org.nuiton.i18n.I18n._; + +/** + * A simple render of a table of validator's messages, says a table that use a + * {@link SwingValidatorMessageTableModel} model. + * + * @author tchemit <chemit@codelutin.com> + * @see SwingValidatorMessageTableModel + * @since 1.3 + */ +public class SwingValidatorMessageListRenderer extends DefaultListCellRenderer { + + private static final long serialVersionUID = 1L; + + protected String format = "%1$-20s - %2$s"; + + protected String formatTip = "%1$-20s - %2$-20s : %3$s"; + + public SwingValidatorMessageListRenderer() { + } + + public SwingValidatorMessageListRenderer(String format) { + this.format = format; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + @Override + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + + JLabel rendererComponent = (JLabel) + super.getListCellRendererComponent( + list, + value, + index, + isSelected, + cellHasFocus + ); + + SwingValidatorMessage model = (SwingValidatorMessage) value; + + // scope + ImageIcon icon = SwingValidatorUtil.getIcon(model.getScope()); + + // field name + String fieldName = getFieldName( + list, + model.getField(), + index + ); + + // message + String message = getMessage(model); + + // text to display + String text = String.format(format, fieldName, message); + + String label = _(model.getScope().getLabel()); + String tmp = _("validator.scope.tip", label); + String tmp2 = _("validator.field.tip", fieldName); + + String tooltTipText = String.format(formatTip, tmp, tmp2, message); + + + rendererComponent.setText(text); + rendererComponent.setToolTipText(tooltTipText); + rendererComponent.setIcon(icon); + + return rendererComponent; + } + + public ImageIcon getIcon(NuitonValidatorScope scope) { + ImageIcon icon = SwingValidatorUtil.getIcon(scope); + return icon; + } + + public String getMessage(SwingValidatorMessage model) { + String text = SwingValidatorUtil.getMessage(model); + return text; + } + + public String getFieldName(JList list, String value, int row) { + SwingValidatorMessageListModel tableModel = + (SwingValidatorMessageListModel) list.getModel(); + SwingValidatorMessage model = + (SwingValidatorMessage) tableModel.getElementAt(row); + String fieldName = SwingValidatorUtil.getFieldName(model, value); + return fieldName; + } +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableModel.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableModel.java new file mode 100644 index 0000000..e00045b --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableModel.java @@ -0,0 +1,380 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.BeanValidatorEvent; +import org.nuiton.validator.bean.BeanValidatorListener; + +import javax.swing.JComponent; +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * The model of the table of errors. + * <p/> + * The model listens validators messages and update his internal model from it. + * + * @author tchemit <chemit@codelutin.com> + * @since 1.3 + */ +public class SwingValidatorMessageTableModel + extends AbstractTableModel + implements BeanValidatorListener { + + private static final long serialVersionUID = 1L; + + /** Logger */ + private static Log log = + LogFactory.getLog(SwingValidatorMessageTableModel.class); + + public static final String[] columnNames = + {"validator.scope", "validator.field", "validator.message"}; + + public static final Class<?>[] columnClasses = + {NuitonValidatorScope.class, String.class, String.class}; + + /** list of registred validators */ + protected transient List<SwingValidator<?>> validators; + + /** list of messages actual displayed */ + protected List<SwingValidatorMessage> data; + + public SwingValidatorMessageTableModel() { + validators = new ArrayList<SwingValidator<?>>(); + data = new ArrayList<SwingValidatorMessage>(); + } + + /** + * Register a validator for this model. + * <p/> + * <p/> + * Note: a validator can not be register twice in the same model. + * + * @param validator the validator to register + */ + public void registerValidator(SwingValidator<?> validator) { + if (validators.contains(validator)) { + throw new IllegalArgumentException( + "the validator " + validator + " is already registred in " + + this); + } + validators.add(validator); + validator.addBeanValidatorListener(this); + } + + public void addMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + addMessages(validator, fieldName, scope, true, messages); + } + + public void addMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + addMessages(editor, fieldName, scope, true, messages); + } + + public void removeMessages(JComponent editor, NuitonValidatorScope scope) { + + if (editor == null) { + // no editor, so nothing to do + return; + } + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (editor.equals(error.getEditor()) && + (scope == null || error.getScope() == scope)) { + // remove the message + data.remove(i); + fireTableRowsDeleted(i, i); + } + } + } + + public void removeMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + String... messages) { + removeMessages(validator, fieldName, scope, true, messages); + } + + public void removeMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope) { + removeMessages(editor, fieldName, scope, true); + } + + public void clear() { + int i = data.size(); + if (i > 0) { + data.clear(); + fireTableRowsDeleted(0, i - 1); + } + } + + public void clearValidators() { + for (SwingValidator<?> v : validators) { + v.removeBeanValidatorListener(this); + } + validators.clear(); + } + + /** + * Obtain the message for a given row. + * + * @param rowIndex the row index + * @return the message for the given row index + */ + public SwingValidatorMessage getRow(int rowIndex) { + ensureRowIndex(rowIndex); + return data.get(rowIndex); + } + + @Override + public boolean isCellEditable(int row, int column) { + // cells are never editable in this model + return false; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + ensureColumnIndex(columnIndex); + return columnClasses[columnIndex]; + } + + @Override + public String getColumnName(int column) { + ensureColumnIndex(column); + return columnNames[column]; + } + + @Override + public void onFieldChanged(BeanValidatorEvent event) { + String[] toDelete = event.getMessagesToDelete(); + String[] toAdd = event.getMessagesToAdd(); + String field = event.getField(); + NuitonValidatorScope scope = event.getScope(); + boolean mustAdd = toAdd != null && toAdd.length > 0; + boolean mustDel = toDelete != null && toDelete.length > 0; + + if (log.isTraceEnabled()) { + log.trace("----------------------------------------------------------"); + log.trace(field + " - (" + getRowCount() + ") toAdd " + mustAdd); + log.trace(field + " - (" + getRowCount() + ") toDelete " + mustDel); + } + + SwingValidator<?> validator = (SwingValidator<?>) event.getSource(); + + if (mustDel) { + + // removes datas and notify if no messages to add + removeMessages(validator, field, scope, !mustAdd, toDelete); + } + + if (mustAdd) { + + // add new messages, sort datas and notify + addMessages(validator, field, scope, true, toAdd); + } + } + + @Override + public int getRowCount() { + return data.size(); + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + ensureColumnIndex(columnIndex); + ensureRowIndex(rowIndex); + + SwingValidatorMessage row = data.get(rowIndex); + if (columnIndex == 0) { + // the icon + return row.getScope(); + } + if (columnIndex == 1) { + // the field + return row.getField(); + } + if (columnIndex == 2) { + // the message + return row.getMessage(); + } + + // should never come here + return null; + } + + protected void ensureRowIndex(int rowIndex) + throws ArrayIndexOutOfBoundsException { + if (rowIndex < -1 || rowIndex >= getRowCount()) { + throw new ArrayIndexOutOfBoundsException( + "the rowIndex was " + rowIndex + ", but should be int [0," + + (getRowCount() - 1) + "]"); + } + } + + protected void ensureColumnIndex(int index) + throws ArrayIndexOutOfBoundsException { + if (index < -1 || index >= getColumnCount()) { + throw new ArrayIndexOutOfBoundsException( + "the columnIndex was " + index + ", but should be int [0," + + (getColumnCount() - 1) + "]"); + } + } + + protected void addMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + JComponent editor = validator == null ? + null : + validator.getFieldRepresentation(fieldName); + // add new errors + for (String error : messages) { + SwingValidatorMessage row = + new SwingValidatorMessage( + validator, + fieldName, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + + protected void addMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope, + boolean sort, + String... messages) { + + // add new errors + for (String error : messages) { + SwingValidatorMessage row = + new SwingValidatorMessage( + null, + fieldName, + error, + scope, + editor + ); + data.add(row); + if (!sort) { + fireTableRowsInserted(data.size() - 1, data.size() - 1); + } + } + + if (sort) { + + // resort datas + Collections.sort(data); + + // notify + fireTableDataChanged(); + } + } + + protected void removeMessages(SwingValidator<?> validator, + String fieldName, + NuitonValidatorScope scope, + boolean notify, + String... messages) { + + List<String> messagesToDel = + new ArrayList<String>(Arrays.asList(messages)); + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (validator.equals(error.getValidator()) && + error.getScope() == scope && + error.getField().equals(fieldName) && + messagesToDel.contains(error.getMessage())) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } + + protected void removeMessages(JComponent editor, + String fieldName, + NuitonValidatorScope scope, + boolean notify) { + + // do it in reverse mode (only one pass in that way since index + // will stay coherent while removing them) + + for (int i = getRowCount() - 1; i > -1; i--) { + SwingValidatorMessage error = data.get(i); + if (editor.equals(error.getEditor()) && + (scope == null || error.getScope() == scope) && + error.getField().equals(fieldName)) { + // remove the message + data.remove(i); + if (notify) { + fireTableRowsDeleted(i, i); + } + } + } + } +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableMouseListener.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableMouseListener.java new file mode 100644 index 0000000..80b717b --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableMouseListener.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JTable; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * A mouse listener to put on a {@link JList} with a {@link + * SwingValidatorMessageTableModel} 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 tchemit <chemit@codelutin.com> + */ +public class SwingValidatorMessageTableMouseListener extends MouseAdapter { + + /** Logger */ + private static Log log = + LogFactory.getLog(SwingValidatorMessageTableMouseListener.class); + + public static final String HIGHLIGHT_ERROR_PROPERTY = "highlightError"; + + /** delgate property change support */ + protected PropertyChangeSupport pcs; + + public SwingValidatorMessageTableMouseListener() { + pcs = new PropertyChangeSupport(this); + } + + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + if (e.getClickCount() == 2) { + + SwingValidatorMessage entry = getSelectedMessage(e); + if (entry == null) { + // no entry found + return; + } + JComponent component = entry.getEditor(); + if (component != null) { + pcs.firePropertyChange(HIGHLIGHT_ERROR_PROPERTY, null, entry); + if (component.isVisible()) { + component.requestFocus(); + } + } + } + } + + + protected SwingValidatorMessage getSelectedMessage(MouseEvent e) { + JTable table = (JTable) e.getSource(); + if (!(table.getModel() instanceof SwingValidatorMessageTableModel)) { + if (log.isWarnEnabled()) { + log.warn("model must be a " + + SwingValidatorMessageTableModel.class + + ", but was " + table.getModel()); + } + return null; + } + + SwingValidatorMessageTableModel model = + (SwingValidatorMessageTableModel) table.getModel(); + int index = table.getSelectionModel().getMinSelectionIndex(); + if (index == -1) { + // nothing is selected + return null; + } + if (table.getRowSorter() != null) { + index = table.getRowSorter().convertRowIndexToModel(index); + } + SwingValidatorMessage entry = model.getRow(index); + if (log.isDebugEnabled()) { + log.debug("selected index: " + index + " : error: " + entry); + } + return entry; + } + + 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); + } + +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java new file mode 100644 index 0000000..1714fe3 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorMessageTableRenderer.java @@ -0,0 +1,123 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.Component; + +import static org.nuiton.i18n.I18n._; + +/** + * A simple render of a table of validator's messages, says a table that use + * a {@link SwingValidatorMessageTableModel} model. + * + * @author tchemit <chemit@codelutin.com> + * @see SwingValidatorMessageTableModel + * @since 1.3 + */ +public class SwingValidatorMessageTableRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + + @Override + 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; + String toolTipText = null; + + column = table.convertColumnIndexToModel(column); + if (table.getRowSorter() != null) { + row = table.getRowSorter().convertRowIndexToModel(row); + } + + switch (column) { + case 0: + // scope + NuitonValidatorScope scope = (NuitonValidatorScope) value; + icon = SwingValidatorUtil.getIcon(scope); + String label = _(scope.getLabel()); + toolTipText = _("validator.scope.tip", label); + break; + + case 1: + // field name + text = getFieldName(table, (String) value, row); + toolTipText = _("validator.field.tip", text); + break; + + case 2: + // message + text = getMessage(table, (String) value, row); + toolTipText = _("validator.message.tip", text); + break; + } + + rendererComponent.setText(text); + rendererComponent.setToolTipText(toolTipText); + rendererComponent.setIcon(icon); + return rendererComponent; + } + + public ImageIcon getIcon(NuitonValidatorScope scope) { + ImageIcon icon = SwingValidatorUtil.getIcon(scope); + return icon; + } + + public String getMessage(JTable table, String value, int row) { + SwingValidatorMessageTableModel tableModel = + (SwingValidatorMessageTableModel) table.getModel(); + SwingValidatorMessage model = tableModel.getRow(row); + String text = SwingValidatorUtil.getMessage(model); + return text; + } + + public String getFieldName(JTable table, String value, int row) { + SwingValidatorMessageTableModel tableModel = + (SwingValidatorMessageTableModel) table.getModel(); + SwingValidatorMessage model = tableModel.getRow(row); + String fieldName = SwingValidatorUtil.getFieldName(model, value); + return fieldName; + } +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorUtil.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorUtil.java new file mode 100644 index 0000000..098d3f7 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/SwingValidatorUtil.java @@ -0,0 +1,564 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing; + +import jaxx.runtime.JAXXObject; +import jaxx.runtime.JAXXValidator; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.validator.swing.meta.Validator; +import jaxx.runtime.validator.swing.meta.ValidatorField; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ReflectUtil; +import org.nuiton.validator.NuitonValidatorProvider; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.BeanValidator; +import org.nuiton.validator.bean.BeanValidatorFactory; +import org.nuiton.validator.bean.BeanValidatorUtil; + +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JTable; +import javax.swing.RowSorter; +import javax.swing.SortOrder; +import java.awt.Color; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n.n_; + +/** + * The helper class for swing validation module. + * + * @author tchemit <chemit@codelutin.com> + */ +public class SwingValidatorUtil extends BeanValidatorUtil { + + /** Logger */ + static private final Log log = LogFactory.getLog(SwingValidatorUtil.class); + + protected static EnumMap<NuitonValidatorScope, ImageIcon> icons; + + protected static EnumMap<NuitonValidatorScope, Color> colors; + + public static EnumMap<NuitonValidatorScope, ImageIcon> getIcons() { + if (icons == null) { + icons = new EnumMap<NuitonValidatorScope, ImageIcon>(NuitonValidatorScope.class); + icons.put(NuitonValidatorScope.FATAL, SwingUtil.createImageIcon("fatal.png")); + icons.put(NuitonValidatorScope.ERROR, SwingUtil.createImageIcon("error.png")); + icons.put(NuitonValidatorScope.WARNING, SwingUtil.createImageIcon("warning.png")); + icons.put(NuitonValidatorScope.INFO, SwingUtil.createImageIcon("info.png")); + } + return icons; + } + + public static EnumMap<NuitonValidatorScope, Color> getColors() { + if (colors == null) { + colors = new EnumMap<NuitonValidatorScope, Color>(NuitonValidatorScope.class); + colors.put(NuitonValidatorScope.FATAL, Color.MAGENTA); + colors.put(NuitonValidatorScope.ERROR, Color.RED); + colors.put(NuitonValidatorScope.WARNING, Color.YELLOW); + colors.put(NuitonValidatorScope.INFO, Color.GREEN); + } + return colors; + } + + public static Color getColor(NuitonValidatorScope scope) { + Color c = scope == null ? null : getColors().get(scope); + return c; + } + + public static ImageIcon getIcon(NuitonValidatorScope scope) { + ImageIcon icon = scope == null ? null : getIcons().get(scope); + return icon; + } + + public static ImageIcon getFatalIcon() { + return getIcons().get(NuitonValidatorScope.FATAL); + } + + public static ImageIcon getErrorIcon() { + return getIcons().get(NuitonValidatorScope.ERROR); + } + + public static ImageIcon getWarningIcon() { + return getIcons().get(NuitonValidatorScope.WARNING); + } + + public static ImageIcon getInfoIcon() { + return getIcons().get(NuitonValidatorScope.INFO); + } + + protected SwingValidatorUtil() { + // no instance + } + + public static <O> SwingValidator<O> newValidator(Class<O> type, + String context) { + + if (BeanValidatorFactory.isDefaultCreator()) { + + // set the swing bean validator creator + BeanValidatorFactory.setCreator(new DefaultSwingValidatorCreator()); + } + SwingValidator<O> validator = + (SwingValidator<O>) BeanValidatorFactory.newBeanValidator( + type, context); + return validator; + } + + /** + * To install all the stuff for validation on a {@link JAXXValidator} ui. + * <p/> + * This method is called after validators has beeen detected in the ui (via + * the method {@link #detectValidators(JAXXValidator)}).. + * <p/> + * It will first find and register all validator field via the method + * {@link JAXXValidator#registerValidatorFields()}, then for each + * validators it will install ui for it (says connect validator to ui via layers) + * and will reload attached bean to make visible bean validation state on ui. + * <p/> + * This method is always inovked by a generated jaxx-validator file at the + * end of the {@code $completeSetup} method. + * + * @param ui the validator ui to init. + */ + public static void installUI(JAXXValidator ui) { + + // first install fields with validation + ui.registerValidatorFields(); + +// detectValidatorFields(ui); + + // for each validator install uis + reload bean + + List<String> validatorIds = ui.getValidatorIds(); + for (String validatorId : validatorIds) { + SwingValidator<?> validator = (SwingValidator<?>) + ui.getValidator(validatorId); + + // install uis + validator.installUIs(); + + // reload attached bean (to see validation on uis) + validator.reloadBean(); + } + } + + /** + * Given a {@link JAXXValidator} ui, detects on it all the validators it + * contains. + * <p/> + * A validator is detected from the annotation {@link Validator} placed on + * his field. + * <p/> + * This method is always inovked by a generated jaxx-validator file at the + * end of the {@code $completeSetup} method. + * + * @param ui the ui where to seek for validators. + * @return the list of ids of validators found on the given ui + */ + public static List<String> detectValidators(JAXXValidator ui) { + List<String> validatorIds = new ArrayList<String>(); + Map<Field, Validator> validators = ReflectUtil.getFieldAnnotation( + ui.getClass(), + Validator.class, + true + ); + + for (Map.Entry<Field, Validator> entry : validators.entrySet()) { + Field field = entry.getKey(); + Validator annotation = entry.getValue(); + String validatorId = annotation.validatorId(); + validatorIds.add(validatorId); + if (log.isInfoEnabled()) { + log.info("Detect validator [" + annotation.validatorId() + + "] on field " + field.getName()); + } + } + return Collections.unmodifiableList(validatorIds); + } + + /** + * Detects on a {@link JAXXValidator} ui all the validator fields it + * contains. + * <p/> + * A validator field is detected via the annotation placed on his field or + * his getter (in cas of inheritance). + * <p/> + * Each field found will be registred to his corresponding validator via + * the method {@link SwingValidator#setFieldRepresentation(String, JComponent)}. + * <p/> + * By default, this method is invoked in the generated method + * {@link JAXXValidator#registerValidatorFields()} by a generated + * jaxx-validator file. + * + * @param ui the ui to seek + */ + public static void detectValidatorFields(JAXXValidator ui) { + + Map<JComponent, ValidatorField> editors = getValidatorEditors(ui); + + try { + + for (String validatorId : ui.getValidatorIds()) { + SwingValidator<?> validator = + (SwingValidator<?>) ui.getValidator(validatorId); + + for (Map.Entry<JComponent, ValidatorField> entry : + editors.entrySet()) { + ValidatorField fieldAnnotation = entry.getValue(); + JComponent editor = entry.getKey(); + if (!validatorId.equals(fieldAnnotation.validatorId())) { + + // not good validator, skip this field + continue; + } + String propertyName = fieldAnnotation.propertyName(); + if (log.isInfoEnabled()) { + log.info("Detects for validator [" + validatorId + + "] property " + propertyName + + " for editor " + fieldAnnotation.editorName()); + } + validator.setFieldRepresentation(propertyName, editor); + } + } + + } finally { + + editors.clear(); + } + } + + /** + * Prepare the ui where to display the validators messages. + * + * @param errorTable the table where to display validators messages + * @param render renderer to use + */ + public static void installUI(JTable errorTable, + SwingValidatorMessageTableRenderer render) { + errorTable.setDefaultRenderer(Object.class, render); + errorTable.getRowSorter().setSortKeys( + Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); + SwingUtil.setI18nTableHeaderRenderer( + errorTable, + n_("validator.scope.header"), + n_("validator.scope.header.tip"), + n_("validator.field.header"), + n_("validator.field.header.tip"), + n_("validator.message.header"), + n_("validator.message.header.tip")); + // register a single 'goto widget error' mouse listener on errorTable + registerErrorTableMouseListener(errorTable); + SwingUtil.fixTableColumnWidth(errorTable, 0, 25); + } + + /** + * Register for a given validator list ui a validator mouse listener. + * <p/> + * Note: there is only one listener registred for a given list model, so + * invoking this method tiwce or more will have no effect. + * + * @param list the validation ui list + * @return the listener instanciate or found + * @see SwingValidatorMessageListMouseListener + */ + public static SwingValidatorMessageListMouseListener registerErrorListMouseListener(JList list) { + SwingValidatorMessageListMouseListener listener = + getErrorListMouseListener(list); + + if (listener != null) { + return listener; + } + listener = new SwingValidatorMessageListMouseListener(); + if (log.isDebugEnabled()) { + log.debug(listener.toString()); + } + list.addMouseListener(listener); + return listener; + } + + /** + * Register for a given validator table ui a validator mouse listener + * <p/> + * Note: there is onlt one listener registred for a givne table model, so + * invokin this method twice or more will have no effect. + * + * @param table the validator table ui + * @return the listener instanciate or found + * @see SwingValidatorMessageTableMouseListener + */ + public static SwingValidatorMessageTableMouseListener registerErrorTableMouseListener(JTable table) { + SwingValidatorMessageTableMouseListener listener = + getErrorTableMouseListener(table); + + if (listener != null) { + return listener; + } + listener = new SwingValidatorMessageTableMouseListener(); + if (log.isDebugEnabled()) { + log.debug(listener.toString()); + } + table.addMouseListener(listener); + return listener; + } + + /** + * @param list the validator list ui + * @return the validator list mouse listener, or <code>null</code> if not + * found + * @see SwingValidatorMessageListMouseListener + */ + public static SwingValidatorMessageListMouseListener getErrorListMouseListener(JList list) { + if (list != null) { + for (MouseListener listener : list.getMouseListeners()) { + if (listener instanceof SwingValidatorMessageListMouseListener) { + return (SwingValidatorMessageListMouseListener) listener; + } + } + } + return null; + } + + /** + * @param table the validator table ui + * @return the validator table mouse listener, or <code>null</code> if not + * found + * @see SwingValidatorMessageTableMouseListener + */ + public static SwingValidatorMessageTableMouseListener getErrorTableMouseListener(JTable table) { + if (table != null) { + for (MouseListener listener : table.getMouseListeners()) { + if (listener instanceof SwingValidatorMessageTableMouseListener) { + return (SwingValidatorMessageTableMouseListener) listener; + } + } + } + return null; + } + + public static String getMessage(SwingValidatorMessage model) { + String text = model.getMessage(); + if (model.getField() != null) { + text = model.getI18nError(text); + } + return text; + } + + public static String getFieldName(SwingValidatorMessage model, String value) { + String text = null; + JComponent editor = model.getEditor(); + if (editor != null) { + text = (String) editor.getClientProperty("validatorLabel"); + /*if (l != null) { + text = I18n._(l); + } else { + // TODO should try the text + }*/ + } + if (text == null) { + text = value; + } + return text; + } + + /** + * Method to listen the modification of the context name and at each time + * reload fields of the ui. + * + * @param validator validator to listen + * @param ui ui to refresh when context name has changed + * @since 2.2.1 + */ + public static void listenValidatorContextNameAndRefreshFields( + SwingValidator<?> validator, + final JAXXValidator ui) { + + PropertyChangeListener listener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + SwingValidator<?> validator = (SwingValidator<?>) evt.getSource(); + if (log.isInfoEnabled()) { + log.info("Context name changed to [" + evt.getNewValue() + + "] for validator " + validator.getType()); + } + ui.registerValidatorFields(); + } + }; + validator.addPropertyChangeListener( + SwingValidator.CONTEXT_PROPERTY, + listener + ); + } + + /** + * Default bean validator creator to use in the {@link BeanValidatorFactory}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.1 + */ + public static class DefaultSwingValidatorCreator implements BeanValidatorFactory.BeanValidatorCreator { + + @Override + public <O> BeanValidator<O> newBeanValidator(NuitonValidatorProvider provider, Class<O> type, String context, NuitonValidatorScope... scopes) { + BeanValidator<O> beanValidator = new SwingValidator<O>(provider, + type, + context, + scopes + ); + return beanValidator; + } + } + + /** + * 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) { + if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { + return; + } + JAXXValidator jaxxValidator = (JAXXValidator) ui; + List<String> validatorIds = jaxxValidator.getValidatorIds(); + if (excludeIds.length > 0) { + validatorIds = new ArrayList<String>(validatorIds); + for (String excludeId : excludeIds) { + validatorIds.remove(excludeId); + } + } + for (String validatorId : validatorIds) { + BeanValidator beanValidator = + jaxxValidator.getValidator(validatorId); + if (bean == null || beanValidator.getType().isAssignableFrom( + bean.getClass())) { + // touch validator, only if fits the bean type (or bean is null) + 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) { + if (!JAXXValidator.class.isAssignableFrom(ui.getClass())) { + return; + } + JAXXValidator jaxxValidator = (JAXXValidator) ui; + List<String> validatorIds = jaxxValidator.getValidatorIds(); + if (excludeIds.length > 0) { + validatorIds = new ArrayList<String>(validatorIds); + for (String excludeId : excludeIds) { + validatorIds.remove(excludeId); + } + } + for (String validatorId : validatorIds) { + BeanValidator<?> beanValidator = + jaxxValidator.getValidator(validatorId); + beanValidator.setChanged(newValue); + } + } + + protected static Map<JComponent, ValidatorField> getValidatorEditors(JAXXValidator ui) { + + + Map<JComponent, ValidatorField> editors = new HashMap<JComponent, ValidatorField>(); + + + Map<Field, ValidatorField> validatorFields = null; + Map<Method, ValidatorField> validatorMethods = null; + try { + + validatorFields = ReflectUtil.getFieldAnnotation( + ui.getClass(), + ValidatorField.class, + true + ); + + validatorMethods = ReflectUtil.getMethodAnnotation( + ui.getClass(), + ValidatorField.class, + true + ); + for (Map.Entry<Field, ValidatorField> fieldEntry : validatorFields.entrySet()) { + Field field = fieldEntry.getKey(); + field.setAccessible(true); + ValidatorField fieldAnnotation = fieldEntry.getValue(); + JComponent editor = (JComponent) field.get(ui); + editors.put(editor, fieldAnnotation); + } + + for (Map.Entry<Method, ValidatorField> fieldEntry : validatorMethods.entrySet()) { + Method method = fieldEntry.getKey(); + method.setAccessible(true); + ValidatorField fieldAnnotation = fieldEntry.getValue(); + JComponent editor = (JComponent) method.invoke(ui); + editors.put(editor, fieldAnnotation); + } + + } catch (Exception e) { + throw new IllegalStateException("Could not init validators on ui " + ui, e); + } finally { + if (validatorFields != null) { + validatorFields.clear(); + } + if (validatorMethods != null) { + validatorMethods.clear(); + } + } + return editors; + } + +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/Validator.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/Validator.java new file mode 100644 index 0000000..07b48b7 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/Validator.java @@ -0,0 +1,48 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing.meta; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to put on each field validator. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.3 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Validator { + + /** + * Obtain the id of the validator. + * + * @return the id of the validator. + */ + String validatorId(); +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/ValidatorField.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/ValidatorField.java new file mode 100644 index 0000000..4f87de7 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/meta/ValidatorField.java @@ -0,0 +1,63 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing.meta; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to put on each field or method linked to a validator. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.3 + */ +@Target(value = {ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidatorField { + /** + * Obtain the id of the validator used for the field. + * + * @return the id of the validator used for the field. + */ + String validatorId(); + + /** + * Obtain the name of the bean property to validate. + * + * @return the name of the property to validate + */ + String propertyName(); + + /** + * Obtain the name of the property editor. + * <p/> + * If empty, then use the {@link #propertyName()}. + * + * @return the name of the property editor + */ + String editorName() default ""; +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java new file mode 100644 index 0000000..e9796be --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java @@ -0,0 +1,83 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing.ui; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.jxlayer.plaf.AbstractLayerUI; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.BeanValidatorEvent; +import org.nuiton.validator.bean.BeanValidatorListener; + +import javax.swing.JComponent; + +/** + * Abstract renderer + * + * @author tchemit <chemit@codelutin.com> + */ +public abstract class AbstractBeanValidatorUI extends AbstractLayerUI<JComponent> implements BeanValidatorListener { + + /** Logger */ + private static final Log log = LogFactory.getLog(AbstractBeanValidatorUI.class); + + private static final long serialVersionUID = 1L; + + /** + * Actual scope to display in the layer. + * <p/> + * This field will be recomputed each time a new event arrived on this + * field. + */ + protected NuitonValidatorScope scope; + + /** Field name in validator. */ + protected final String field; + + public AbstractBeanValidatorUI(String field) { + this.field = field; + if (log.isDebugEnabled()) { + log.debug("install " + this + "<field:" + field + ">"); + } + } + + public NuitonValidatorScope getScope() { + return scope; + } + + @Override + public void onFieldChanged(BeanValidatorEvent event) { + if (field.equals(event.getField())) { + + scope = event.getSource().getHighestScope(field); + if (log.isDebugEnabled()) { + log.debug("set new scope : " + scope + " to field " + field); + } + // ask to repaint the layer + setDirty(true); + } + } + +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java new file mode 100644 index 0000000..83f1ec1 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java @@ -0,0 +1,105 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing.ui; + +import jaxx.runtime.validator.swing.SwingValidatorUtil; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.util.EnumMap; + + +/** + * An implementation of {@link AbstractBeanValidatorUI} which paints a icon on + * top right corner. + * + * @author tchemit <chemit@codelutin.com> + */ +public class IconValidationUI extends AbstractBeanValidatorUI { + + private static final long serialVersionUID = 1L; + + // The icon to be shown at the layer's corner + + protected EnumMap<NuitonValidatorScope, BufferedImage> icons; + + public IconValidationUI(String field) { + super(field); + icons = new EnumMap<NuitonValidatorScope, BufferedImage>(NuitonValidatorScope.class); + + for (NuitonValidatorScope scope : NuitonValidatorScope.values()) { + + BufferedImage image = prepareIcon(SwingValidatorUtil.getColor(scope)); + icons.put(scope, image); + } + } + + @Override + public void installUI(JComponent c) { + super.installUI(c); + c.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 3)); + } + + @Override + public void uninstallUI(JComponent c) { + super.uninstallUI(c); + c.setBorder(null); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + // There is no need to take insets into account for this painter + NuitonValidatorScope scope = getScope(); + if (scope != null) { + BufferedImage icon = icons.get(scope); + g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null); + } + } + + protected static BufferedImage prepareIcon(Color color) { + int width = 7; + int height = 8; + BufferedImage icon = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.setColor(color); + g2.fillRect(0, 0, width, height); + g2.setColor(Color.WHITE); + g2.drawLine(0, 0, width, height); + g2.drawLine(0, height, width, 0); + g2.dispose(); + return icon; + } + + +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java new file mode 100644 index 0000000..69556c4 --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java @@ -0,0 +1,94 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing.ui; + +import jaxx.runtime.validator.swing.SwingValidatorUtil; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JComponent; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.util.EnumMap; + + +/** + * An implementation of {@link AbstractBeanValidatorUI} which paints a icon on + * top right corner. + * + * @author tchemit <chemit@codelutin.com> + */ +public class ImageValidationUI extends AbstractBeanValidatorUI { + + private static final long serialVersionUID = 1L; + + protected EnumMap<NuitonValidatorScope, BufferedImage> icons; + + public ImageValidationUI(String field) { + super(field); + icons = new EnumMap<NuitonValidatorScope, BufferedImage>(NuitonValidatorScope.class); + + for (NuitonValidatorScope scope : NuitonValidatorScope.values()) { + + BufferedImage image = prepareIcon(SwingValidatorUtil.getIcon(scope)); + icons.put(scope, image); + } + } + + protected static BufferedImage prepareIcon(ImageIcon image) { + BufferedImage icon = new BufferedImage(image.getIconWidth(), image.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2 = (Graphics2D) icon.getGraphics(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + g2.drawImage(image.getImage(), 0, 0, null); + g2.dispose(); + return icon; + } + + @Override + public void installUI(JComponent c) { + super.installUI(c); + c.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 3)); + } + + @Override + public void uninstallUI(JComponent c) { + super.uninstallUI(c); + c.setBorder(null); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + super.paintLayer(g2, l); + NuitonValidatorScope scope = getScope(); + if (scope != null) { + BufferedImage icon = icons.get(scope); + g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null); + } + } +} diff --git a/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java new file mode 100644 index 0000000..ec233dc --- /dev/null +++ b/trunk/jaxx-validator/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java @@ -0,0 +1,76 @@ +/* + * #%L + * JAXX :: Validator + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.validator.swing.ui; + +import jaxx.runtime.validator.swing.SwingValidatorUtil; +import org.jdesktop.jxlayer.JXLayer; +import org.nuiton.validator.NuitonValidatorScope; + +import javax.swing.JComponent; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; + +/** + * An implementation of {@link AbstractBeanValidatorUI} which paints a + * translucent backgroud color (green for ok, red for error, yellow for + * warning). + * + * @author tchemit <chemit@codelutin.com> + */ +public class TranslucentValidationUI extends AbstractBeanValidatorUI { + + private static final long serialVersionUID = 1L; + + public TranslucentValidationUI(String field) { + super(field); + } + + @Override + protected void paintLayer(Graphics2D g2, JXLayer<? extends JComponent> l) { + // paints the layer as is + super.paintLayer(g2, l); + + // to be in sync with the view if the layer has a border + Insets layerInsets = l.getInsets(); + g2.translate(layerInsets.left, layerInsets.top); + + JComponent view = l.getView(); + // To prevent painting on view's border + Insets insets = view.getInsets(); + g2.clip(new Rectangle(insets.left, insets.top, + view.getWidth() - insets.left - insets.right, + view.getHeight() - insets.top - insets.bottom)); + + NuitonValidatorScope scope = getScope(); + + Color c = scope == null ? Color.WHITE : SwingValidatorUtil.getColor(scope); + g2.setColor(c); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f)); + g2.fillRect(0, 0, l.getWidth(), l.getHeight()); + } +} diff --git a/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_en_GB.properties b/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_en_GB.properties new file mode 100644 index 0000000..7e8199d --- /dev/null +++ b/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_en_GB.properties @@ -0,0 +1,9 @@ +validator.field.header=Field +validator.field.header.tip=The field involved +validator.field.tip=Property '%1$s' +validator.message.header=Message +validator.message.header.tip=Message +validator.message.tip=Message \: %1$s +validator.scope.header=... +validator.scope.header.tip=Severity of the message +validator.scope.tip=Message scope \: '%1$s' diff --git a/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_es_ES.properties b/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_es_ES.properties new file mode 100644 index 0000000..a7df1fd --- /dev/null +++ b/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_es_ES.properties @@ -0,0 +1,9 @@ +validator.field.header=Campo +validator.field.header.tip=El campo sobre el que interviene el mensaje +validator.field.tip=Propiedad '%1$s' +validator.message.header=Mensaje +validator.message.header.tip=El texto del mensaje +validator.message.tip=Mensaje \: %1$s +validator.scope.header=... +validator.scope.header.tip=El tipo de mensaje +validator.scope.tip=Type de message \: '%1$s' diff --git a/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_fr_FR.properties b/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_fr_FR.properties new file mode 100644 index 0000000..926c4d4 --- /dev/null +++ b/trunk/jaxx-validator/src/main/resources/i18n/jaxx-validator_fr_FR.properties @@ -0,0 +1,9 @@ +validator.field.header=Champ +validator.field.header.tip=Le champ surquel intervient le message +validator.field.tip=Propriété '%1$s' +validator.message.header=Message +validator.message.header.tip=Le texte du message +validator.message.tip=Message \: %1$s +validator.scope.header=... +validator.scope.header.tip=Le type de message +validator.scope.tip=Type de message \: '%1$s' diff --git a/trunk/jaxx-validator/src/site/rst/index.rst b/trunk/jaxx-validator/src/site/rst/index.rst new file mode 100644 index 0000000..7274df7 --- /dev/null +++ b/trunk/jaxx-validator/src/site/rst/index.rst @@ -0,0 +1,39 @@ +.. - +.. * #%L +.. * JAXX :: Validator +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============== +jaxx-validator +============== + +.. contents:: + + +Présentation +------------ + +Api du validator de JAXX. + +**Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes +librairies.** diff --git a/trunk/jaxx-validator/src/site/site_fr.xml b/trunk/jaxx-validator/src/site/site_fr.xml new file mode 100644 index 0000000..20fe1ed --- /dev/null +++ b/trunk/jaxx-validator/src/site/site_fr.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Validator + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <src>http://maven-site.chorem.org/public/images/logos/jaxx-logo.png</src> + <href>index.html</href> + </bannerLeft> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="index.html"/> + </breadcrumbs> + + <menu ref="parent"/> + + <menu name="Utilisateur"/> + + <menu ref="reports"/> + + <menu ref="modules"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> diff --git a/trunk/jaxx-validator/src/test/resources/log4j.properties b/trunk/jaxx-validator/src/test/resources/log4j.properties new file mode 100644 index 0000000..70cba54 --- /dev/null +++ b/trunk/jaxx-validator/src/test/resources/log4j.properties @@ -0,0 +1,32 @@ +### +# #%L +# JAXX :: Validator +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +# 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=INFO diff --git a/trunk/jaxx-validator/src/test/resources/validators.xml b/trunk/jaxx-validator/src/test/resources/validators.xml new file mode 100644 index 0000000..ef4d8cb --- /dev/null +++ b/trunk/jaxx-validator/src/test/resources/validators.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Validator + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin, Tony Chemit + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<!DOCTYPE validators PUBLIC + "-//Apache Struts//XWork Validator Config 1.0//EN" + "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd"> +<validators> + <!-- default validators from XWork framework --> + <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/> + <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/> + <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/> + <validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/> + <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/> + <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/> + <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/> + <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/> + <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/> + <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/> + <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/> + <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/> + <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/> + <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/> + <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/> + <validator name="conditionalvisitor" + class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/> + + <!-- jaxx validators --> + <validator name="collectionFieldExpression" + class="org.nuiton.validator.xwork2.field.CollectionFieldExpressionValidator"/> + <validator name="collectionUniqueKey" class="org.nuiton.validator.xwork2.field.CollectionUniqueKeyValidator"/> + <validator name="requiredFile" class="org.nuiton.validator.xwork2.field.RequiredFileFieldValidator"/> + <validator name="existingFile" class="org.nuiton.validator.xwork2.field.ExistingFileFieldValidator"/> + <validator name="notExistingFile" class="org.nuiton.validator.xwork2.field.NotExistingFileFieldValidator"/> + <validator name="existingDirectory" class="org.nuiton.validator.xwork2.field.ExistingDirectoryFieldValidator"/> + <validator name="notExistingDirectory" class="org.nuiton.validator.xwork2.field.NotExistingDirectoryFieldValidator"/> + <validator name="fieldexpressionwithparams" class="org.nuiton.validator.xwork2.field.FieldExpressionWithParamsValidator"/> + +</validators> \ No newline at end of file diff --git a/trunk/jaxx-widgets/LICENSE.txt b/trunk/jaxx-widgets/LICENSE.txt new file mode 100644 index 0000000..3f7b8b1 --- /dev/null +++ b/trunk/jaxx-widgets/LICENSE.txt @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + diff --git a/trunk/jaxx-widgets/README.txt b/trunk/jaxx-widgets/README.txt new file mode 100644 index 0000000..d2e50d3 --- /dev/null +++ b/trunk/jaxx-widgets/README.txt @@ -0,0 +1,2 @@ +To deploy new version of pom: mvn deploy +To install localy: mvn install diff --git a/trunk/jaxx-widgets/changelog.txt b/trunk/jaxx-widgets/changelog.txt new file mode 100644 index 0000000..1e285bd --- /dev/null +++ b/trunk/jaxx-widgets/changelog.txt @@ -0,0 +1,5 @@ +1.6.0 + * introduce StatusMessageBar and AboutPanel (fork from nuiton-widgets but in JAXX :)) + +1.5 + * 20090404 [chemit] - initial version diff --git a/trunk/jaxx-widgets/pom.xml b/trunk/jaxx-widgets/pom.xml new file mode 100644 index 0000000..7107042 --- /dev/null +++ b/trunk/jaxx-widgets/pom.xml @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jaxx</artifactId> + <version>2.5.2</version> + </parent> + + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-widgets</artifactId> + + <dependencies> + + <!-- sibiling dependencies --> + + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-core</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + + <dependency> + <groupId>commons-primitives</groupId> + <artifactId>commons-primitives</artifactId> + </dependency> + + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </dependency> + + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JAXX :: Widgets</name> + <description>Collection of swing widgets wrote with JAXX</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <properties> + <jaxx.addSourcesToClassPath>true</jaxx.addSourcesToClassPath> + <jaxx.autoImportCss>true</jaxx.autoImportCss> + <!--jaxx.useUIManagerForIcon>true</jaxx.useUIManagerForIcon--> + </properties> + + <build> + + <resources> + <resource> + <directory>src/main/resources</directory> + <includes> + <include>**/*</include> + </includes> + </resource> + </resources> + + <plugins> + + <plugin> + <groupId>${project.groupId}</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <version>${project.version}</version> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <configuration> + <entries> + <entry> + <basedir>${maven.gen.dir}/java</basedir> + </entry> + </entries> + </configuration> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>gen</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + +</project> diff --git a/trunk/jaxx-widgets/src/license/THIRD-PARTY.properties b/trunk/jaxx-widgets/src/license/THIRD-PARTY.properties new file mode 100644 index 0000000..81b2769 --- /dev/null +++ b/trunk/jaxx-widgets/src/license/THIRD-PARTY.properties @@ -0,0 +1,20 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - BSD License +# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 +# - Common Public License Version 1.0 +# - GNU General Public License - Version 2 with the class path exception +# - Indiana University Extreme! Lab Software License, vesion 1.1.1 +# - Lesser General Public License (LGPL) +# - Lesser General Public License (LGPL) v 3.0 +# - Lesser General Public License (LPGL) +# - Lesser General Public License (LPGL) v 2.1 +# - MIT License +# - The Apache Software License, Version 2.0 +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Thu Aug 18 07:10:57 CEST 2011 +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanel.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanel.jaxx new file mode 100644 index 0000000..d5c8743 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanel.jaxx @@ -0,0 +1,142 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<Table insets='1' + background='{getBackgroundColor()}' + border='{BorderFactory.createLineBorder(Color.BLACK, 1)}'> + + <import> + java.awt.Color + java.awt.Frame + javax.swing.BorderFactory + javax.swing.SwingConstants + </import> + + <AboutPanelHandler id='handler' constructorParams='this'/> + + <String id='title' javaBean='null'/> + + <String id='iconPath' javaBean='null'/> + + <String id='aboutText' javaBean='null'/> + + <String id='bottomText' javaBean='null'/> + + <String id='licenseText' javaBean='null'/> + + <String id='thirdpartyText' javaBean='null'/> + + <Color id='backgroundColor' javaBean='null'/> + + <script><![CDATA[ +public void setLicenseFile(String filename) { + handler.setLicenseFile(filename); +} + +public void setThirdpartyFile(String filename) { + handler.setThirdpartyFile(filename); +} + +public void buildTopPanel() { + handler.buildTopPanel(); +} + +public void init() { + handler.init(); +} + +public void showInDialog(Frame ui, boolean undecorated) { + handler.showInDialog(ui, undecorated); +} + +void $afterCompleteSetup() { + handler.$afterCompleteSetup(); +} + +]]> + </script> + <row> + <cell weightx='1' fill='both'> + <JPanel background='{Color.WHITE}' layout='{new BorderLayout()}'> + <JLabel text='{SwingUtil.getStringValue(getTitle())}' + visible='{getTitle() != null}' + font-size='12' + constraints='BorderLayout.CENTER'/> + </JPanel> + </cell> + </row> + <row> + <cell weightx='1' fill='both'> + <JPanel id='topPanel'/> + </cell> + </row> + <row> + <cell weighty='1' fill='both'> + <JTabbedPane id='tabs'> + <tab title="aboutframe.about"> + <JScrollPane id='aboutContent' border='{null}'> + <JEditorPane contentType='text/html' + editable='false' + border='{null}' + text='{SwingUtil.getStringValue(getAboutText())}' + onHyperlinkUpdate='SwingUtil.openLink(event)'/> + </JScrollPane> + </tab> + <tab title="aboutframe.license"> + <JScrollPane id='licenseContent' border='{null}'> + <JTextArea id='licenseTextArea' + editable='false' + font-size='11' + border='{null}' + text='{SwingUtil.getStringValue(getLicenseText())}'/> + </JScrollPane> + </tab> + <tab title="aboutframe.thirdparty"> + <JScrollPane id='thirdpartyContent' border='{null}'> + <JTextArea id='thirdpartyTextArea' + editable='false' + font-size='11' + border='{null}' + text='{SwingUtil.getStringValue(getThirdpartyText())}'/> + </JScrollPane> + </tab> + </JTabbedPane> + </cell> + </row> + <row> + <cell fill='both'> + <JPanel layout='{new BorderLayout()}'> + <JLabel id='bottomLabel' + constraints='BorderLayout.CENTER' + horizontalAlignment='{SwingConstants.CENTER}' + text='{SwingUtil.getStringValue(getBottomText())}' + visible='{getBottomText() != null}'/> + <JButton id='close' action='{handler.closeAction}' + constraints='BorderLayout.EAST'/> + </JPanel> + </cell> + </row> + +</Table> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanelHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanelHandler.java new file mode 100644 index 0000000..a46af1a --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/AboutPanelHandler.java @@ -0,0 +1,190 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.SwingUtil; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.Resource; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.io.InputStream; + +import static org.nuiton.i18n.I18n._; + +/** + * Handler of the ui {@link AboutPanel}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.4 + */ +public class AboutPanelHandler { + + private static final Log log = LogFactory.getLog(AboutPanelHandler.class); + + protected final AboutPanel ui; + + public AboutPanelHandler(AboutPanel ui) { + this.ui = ui; + } + + final protected Action closeAction = new AbstractAction("close") { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + JDialog container = ui.getParentContainer(JDialog.class); + if (container != null) { + container.dispose(); + } else { + ui.setVisible(false); + } + } + }; + + public void setLicenseFile(String filename) { + String load = load(filename); + ui.setLicenseText(load); + } + + public void setThirdpartyFile(String filename) { + String load = load(filename); + ui.setThirdpartyText(load); + } + + public void buildTopPanel() { + // image + JLabel labelIcon; + if (ui.iconPath != null) { + Icon logoIcon = Resource.getIcon(ui.iconPath); + labelIcon = new JLabel(logoIcon); + } else { + labelIcon = new JLabel(); + } + ui.topPanel.add(labelIcon); + } + + public void init() { + if (ui.getAboutText() == null) { + ui.tabs.remove(ui.aboutContent); + } + if (ui.getLicenseText() == null) { + ui.tabs.remove(ui.licenseContent); + } else { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + ui.licenseTextArea.setCaretPosition(0); + } + }); + + } + if (ui.getThirdpartyText() == null) { + ui.tabs.remove(ui.thirdpartyContent); + } else { + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + ui.thirdpartyTextArea.setCaretPosition(0); + } + }); + } + } + + public void showInDialog(Frame ui, boolean undecorated) { + JDialog f = new JDialog(ui, true); + f.add(this.ui); + if (this.ui.iconPath != null) { + f.setIconImage(SwingUtil.createIcon(this.ui.iconPath).getImage()); + } + f.setResizable(false); + f.setSize(550, 450); + f.setUndecorated(undecorated); + JRootPane rootPane = f.getRootPane(); + rootPane.setDefaultButton(this.ui.close); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "close"); + rootPane.getActionMap().put("close", closeAction); + f.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + Component ui = (Component) e.getSource(); + if (log.isInfoEnabled()) { + log.info("destroy ui " + ui); + } + JAXXUtil.destroy(ui); + JAXXUtil.destroy(AboutPanelHandler.this.ui); + } + }); + SwingUtil.center(ui, f); + f.setVisible(true); + } + + protected String load(String filename) { + InputStream licenseStream = getClass().getResourceAsStream("/" + filename); + String result = null; + try { + if (licenseStream != null) { + result = IOUtils.toString(licenseStream); + } + } catch (IOException ex) { + // ignore it + } finally { + if (licenseStream != null) { + try { + licenseStream.close(); + } catch (IOException ex) { + log.error("could not close file " + filename); + } + } + } + if (result == null) { + result = "resource " + filename + " not found"; + } + return result; + } + + void $afterCompleteSetup() { + buildTopPanel(); + ui.close.setText(_("aboutframe.ok")); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/BaseActionPanel.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/BaseActionPanel.java new file mode 100644 index 0000000..6ad5872 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/BaseActionPanel.java @@ -0,0 +1,78 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JPanel; + +/** + * TODO sletellier 15/06/2012 : find a better way to add onActionPerform on custom components + * + * @author sletellier <letellier@codelutin.com> + */ +public abstract class BaseActionPanel extends JPanel { + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. + * + * @see javax.swing.event.EventListenerList + */ + protected void fireActionEvent() { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "actionPerformed"); + + // 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 (Object listener : listeners) { + if (ActionListener.class.isInstance(listener)) { + ((ActionListener)listener).actionPerformed(e); + } + } + } + + /** + * Adds an <code>ActionListener</code>. + * <p> + * The <code>ActionListener</code> will receive an <code>ActionEvent</code> + * when a selection has been made. If the combo box is editable, then + * an <code>ActionEvent</code> will be fired when editing has stopped. + * + * @param l the <code>ActionListener</code> that is to be notified + * @see #setSelectedItem + */ + public void addActionListener(ActionListener l) { + listenerList.add(ActionListener.class,l); + } + + /** Removes an <code>ActionListener</code>. + * + * @param l the <code>ActionListener</code> to remove + */ + public void removeActionListener(ActionListener l) { + listenerList.remove(ActionListener.class, l); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ClockWidget.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ClockWidget.jaxx new file mode 100644 index 0000000..615d17a --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ClockWidget.jaxx @@ -0,0 +1,83 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JLabel implements='java.awt.event.ActionListener' + foreground='{Color.BLACK}' + background='{Color.WHITE}'> + + <Integer id='delay' javaBean='60000'/> + + <String id='pattern' javaBean='"HH:mm"'/> + + <javax.swing.Timer id='timer' delay='{delay}' constructorParams='delay,this'/> + + <import> + java.awt.Color + java.awt.event.ActionEvent + java.text.SimpleDateFormat + java.text.DateFormat + java.util.Date + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + </import> + <script><![CDATA[ + +protected void $afterCompleteSetup() { + + addPropertyChangeListener(PROPERTY_DELAY, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + timer = new Timer((Integer) evt.getNewValue(), ClockWidget.this); + } + }); +} + +@Override +public void actionPerformed(ActionEvent evt) { + update(); +} + +/** Adds a feature to the Notify attribute of the Clock object */ +@Override +public void addNotify() { + super.addNotify(); + update(); + timer.start(); +} + +@Override +public void removeNotify() { + timer.stop(); + super.removeNotify(); +} + +protected void update() { + DateFormat format = new SimpleDateFormat(pattern); + setText(format.format(new Date())); +} +]]> + </script> +</JLabel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ComboToListSelector.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ComboToListSelector.jaxx new file mode 100644 index 0000000..2934fef --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ComboToListSelector.jaxx @@ -0,0 +1,89 @@ +<!-- + #%L + JAXX :: Widgets + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<ListSelector genericType='B' superGenericType='B'> + + <import> + java.util.Set + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + </import> + + <ListSelectorModel id='model' + genericType='B' + javaBean='new ListSelectorModel()'/> + + <script><![CDATA[ + +protected void $afterCompleteSetup() { + + addPropertyChangeListener(PROPERTY_MODEL, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + + Set<String> bindings = $bindings.keySet(); + JAXXUtil.applyDataBinding(ComboToListSelector.this, bindings); + JAXXUtil.processDataBinding( + ComboToListSelector.this, bindings.toArray(new String[bindings.size()])); + } + }); +} +]]></script> + + <row> + <cell fill='horizontal' weightx='1' anchor="west"> + <JComboBox id='from' + model='{model.getFromModel()}' + renderer='{getRenderer()}'/> + </cell> + <cell anchor='east'> + <JToolBar id='actions' floatable='false'> + <JButton id="add" + toolTipText='{getAddToolTip()}' + actionIcon='add' + enabled='{model.isAddEnabled()}' + onActionPerformed='model.add()'/> + + <JButton id="remove" + toolTipText='{getRemoveToolTip()}' + actionIcon='remove' + enabled='{model.isRemoveEnabled()}' + onActionPerformed='model.remove()'/> + + </JToolBar> + </cell> + </row> + <row> + <cell columns='2' fill='both' weightx='1' weighty='1'> + <JScrollPane id='listPane'> + <JList id='to' + model='{model.getToModel()}' + selectionModel='{model.getToModel()}' + font-size='11' + onMouseClicked='if (event.getClickCount()==2) { model.remove(); }' + cellRenderer='{getRenderer()}'/> + </JScrollPane> + </cell> + </row> +</ListSelector> \ No newline at end of file diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUI.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUI.jaxx new file mode 100644 index 0000000..533ef64 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUI.jaxx @@ -0,0 +1,87 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JDialog title='errorUI.title' modal='true'> + + <import> + java.awt.Frame + </import> + + <ErrorDialogUIHandler id='handler' constructorParams='this'/> + + <script><![CDATA[ +protected static ErrorDialogUI instance; + +public static void init(Frame frame) { + ErrorDialogUIHandler.init(frame); +} + +public static void showError(Exception e) { + ErrorDialogUIHandler.showError(e); +} +public static void disposeUI() { + ErrorDialogUIHandler.disposeUI(); +} + +public ErrorDialogUI(Frame frame) { + super(frame); + if (frame != null) { + setContextValue(frame); + setContextValue(frame,"parent"); + } +} + +void $afterCompleteSetup() { + handler.$afterCompleteSetup(); +} + ]]></script> + <Table> + <row fill='both'> + <cell> + <JPanel> + <JLabel text='errorUI.message'/> + </JPanel> + </cell> + </row> + <row fill='both'> + <cell> + <JLabel id='errorMessage'/> + </cell> + </row> + <row fill='both' weightx='1' weighty='1'> + <cell> + <JScrollPane width='600' height='200'> + <JTextArea id='errorStack' editable='false' font-size='9'/> + </JScrollPane> + </cell> + </row> + <row fill='horizontal'> + <cell> + <JButton id='close' text='errorUI.action.close' + onActionPerformed='dispose()'/> + </cell> + </row> + </Table> +</JDialog> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUIHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUIHandler.java new file mode 100644 index 0000000..1688452 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ErrorDialogUIHandler.java @@ -0,0 +1,98 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.SwingUtil; + +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; +import java.awt.Dialog; +import java.awt.Frame; +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Handler of ui {@link ErrorDialogUI}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class ErrorDialogUIHandler { + + protected final ErrorDialogUI ui; + + public ErrorDialogUIHandler(ErrorDialogUI ui) { + this.ui = ui; + } + + public static void init(Frame frame) { + disposeUI(); + ErrorDialogUI.instance = new ErrorDialogUI(frame); + ErrorDialogUI.instance.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL); + } + + public static void showError(Exception e) { + ErrorDialogUI instance = ErrorDialogUI.instance; + if (instance == null) { + instance = new ErrorDialogUI(); + } + instance.getErrorMessage().setText(e.getMessage()); + StringWriter w = new StringWriter(); + PrintWriter writer = new PrintWriter(w); + try { + e.printStackTrace(writer); + instance.getErrorStack().setText(w.toString()); + } finally { + writer.close(); + } + instance.getErrorStack().setCaretPosition(0); + instance.pack(); + SwingUtil.center(instance.getContextValue(JFrame.class, "parent"), instance); + instance.setVisible(true); + } + + public static void disposeUI() { + ErrorDialogUI instance = ErrorDialogUI.instance; + if (instance != null) { + JAXXUtil.destroy(instance); + } + ErrorDialogUI.instance = null; + } + + void $afterCompleteSetup() { + JRootPane rootPane = ui.getRootPane(); + + JButton close = ui.close; + rootPane.setDefaultButton(close); + InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + inputMap.put(KeyStroke.getKeyStroke("ESCAPE"), "close"); + rootPane.getActionMap().put("close", close.getAction()); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizor.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizor.jaxx new file mode 100644 index 0000000..7c40c30 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizor.jaxx @@ -0,0 +1,90 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new BorderLayout()}'> + + <FontSizorHandler id='handler' constructorParams='this'/> + + <!-- default size of font --> + <Float id='defaultFontSize' javaBean='12f'/> + + <!-- size of font --> + <Float id='fontSize' javaBean='null'/> + + <Boolean id='showDefaultFontSize' javaBean='true'/> + + <Boolean id='showFontSize' javaBean='false'/> + + <script><![CDATA[ +public void init() { + handler.init(); +} + +boolean updateDefaultSizeEnabled(Float fontSize, Float defaultFontSize, boolean enabled) { + return handler.updateDefaultSizeEnabled( fontSize,defaultFontSize, enabled); +} + +public void setCallBack(Runnable action) { + handler.setCallBack(action); +} + +void $afterCompleteSetup() { + handler.$afterCompleteSetup(); +} + ]]> + </script> + <JToolBar floatable='false' + borderPainted='false' + opaque='{isOpaque()}' + constraints='BorderLayout.CENTER'> + + <JButton id='downSize' + actionIcon='font-size-down' + toolTipText='fontsize.action.down.tip' + focusable='false' + focusPainted='false' + enabled='{isEnabled()}' + onActionPerformed='setFontSize(fontSize - 1)'/> + + <JButton id='defaultSize' + actionIcon='font-size' + toolTipText='fontsize.action.default.tip' + focusable='false' + focusPainted='false' + visible='{isShowDefaultFontSize()}' + enabled='{updateDefaultSizeEnabled(getFontSize(), getDefaultFontSize(), isEnabled())}' + onActionPerformed='setFontSize(defaultFontSize)'/> + <JButton id='upSize' + actionIcon='font-size-up' + toolTipText='fontsize.action.up.tip' + focusable='false' + focusPainted='false' + enabled='{isEnabled()}' + onActionPerformed='setFontSize(fontSize + 1)'/> + + <JLabel visible='{isShowFontSize()}' + text='{SwingUtil.getStringValue(getFontSize())}'/> + </JToolBar> + +</JPanel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizorHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizorHandler.java new file mode 100644 index 0000000..88b9b87 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/FontSizorHandler.java @@ -0,0 +1,84 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import jaxx.runtime.binding.SimpleJAXXObjectBinding; + +/** + * Handler of ui {@link FontSizor}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class FontSizorHandler { + + protected final FontSizor ui; + + public FontSizorHandler(FontSizor ui) { + this.ui = ui; + } + + public static final String BINDING_FONT_SIZE_CALL_BACK = "fontSize.callBack"; + + public static final String BINDING_DEFAULT_FONT_SIZE_CALL_BACK = "defaultFontSize.callBack"; + + public void init() { + if (ui.fontSize == null) { + ui.setFontSize(ui.defaultFontSize); + } + } + + boolean updateDefaultSizeEnabled(Float fontSize, + Float defaultFontSize, + boolean enabled) { + if (fontSize == null || defaultFontSize == null) { + return false; + } + return !fontSize.equals(defaultFontSize) && enabled; + } + + public void setCallBack(final Runnable action) { + ui.removeDataBinding(BINDING_FONT_SIZE_CALL_BACK); + ui.registerDataBinding(new SimpleJAXXObjectBinding(ui, BINDING_FONT_SIZE_CALL_BACK, true, "fontSize") { + + @Override + public void processDataBinding() { + action.run(); + } + }); + ui.applyDataBinding(BINDING_FONT_SIZE_CALL_BACK); + } + + void $afterCompleteSetup() { + ui.registerDataBinding(new SimpleJAXXObjectBinding(ui, BINDING_DEFAULT_FONT_SIZE_CALL_BACK, true, "defaultFontSize") { + + @Override + public void processDataBinding() { + ui.setFontSize(ui.defaultFontSize); + } + }); + //applyDataBinding(BINDING_DEFAULT_FONT_SIZE_CALL_BACK); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButton.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButton.jaxx new file mode 100644 index 0000000..84745e5 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButton.jaxx @@ -0,0 +1,77 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JToggleButton id='hidor' + text='{myHandler.updateText(isTargetVisible())}' + toolTipText='{myHandler.updateToolTipText(isTargetVisible())}' + icon="{myHandler.updateIcon(isTargetVisible())}" + _hideIcon='{SwingUtil.createActionIcon("collapse")}' + _showIcon='{SwingUtil.createActionIcon("expand")}' + onActionPerformed='setTargetVisible(!targetVisible)'> + + <import> + javax.swing.Icon + javax.swing.JComponent + </import> + + <HidorButtonHandler id='myHandler' constructorParams='this'/> + + <Boolean id='targetVisible' javaBean='null'/> + + <String id='hideText' javaBean='""'/> + + <String id='showText' javaBean='""'/> + + <String id='hideTip' javaBean='_("hidor.hideTip")'/> + + <String id='showTip' javaBean='_("hidor.showTip")'/> + + <script><![CDATA[ + +protected JComponent target; + +public JComponent getTarget() { + return target; +} + +void $afterCompleteSetup() { + myHandler.$afterCompleteSetup(); +} + +public void setTarget(JComponent target) { + JComponent oldValue = this.target; + this.target = target; + firePropertyChange("target", oldValue, target); +} + +public void setExpandIcon(Icon icon) { + putClientProperty("expandIcon", icon); +} + +public void setHideIcon(Icon icon) { + putClientProperty("hideIcon", icon); +} +]]> + </script> +</JToggleButton> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButtonHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButtonHandler.java new file mode 100644 index 0000000..c4fced2 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/HidorButtonHandler.java @@ -0,0 +1,97 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.Icon; +import javax.swing.JComponent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Handler of ui {@link HidorButton}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class HidorButtonHandler { + + private static final Log log = + LogFactory.getLog(HidorButtonHandler.class); + + protected final HidorButton ui; + + public HidorButtonHandler(HidorButton ui) { + this.ui = ui; + } + + void $afterCompleteSetup() { + + ui.addPropertyChangeListener("targetVisible", new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("target visible changed <" + evt.getOldValue() + ":" + evt.getNewValue() + ">"); + } + boolean newValue = (Boolean) evt.getNewValue(); + if (ui.target != null) { + ui.target.setVisible(newValue); + } + } + }); + } + + public void setTarget(JComponent target) { + JComponent oldValue = ui.target; + ui.target = target; + ui.firePropertyChange("target", oldValue, target); + } + + public void setExpandIcon(Icon icon) { + ui.putClientProperty("expandIcon", icon); + } + + public void setHideIcon(Icon icon) { + ui.putClientProperty("hideIcon", icon); + } + + protected String updateToolTipText(boolean c) { + String i = c ? ui.hideTip : ui.showTip; + return i; + } + + protected String updateText(boolean c) { + String i = c ? ui.hideText : ui.showText; + return i; + } + + protected Icon updateIcon(boolean c) { + String key = c ? "hideIcon" : "showIcon"; + return (Icon) ui.getClientProperty(key); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXDatePicker.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXDatePicker.jaxx new file mode 100644 index 0000000..9cc69a8 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXDatePicker.jaxx @@ -0,0 +1,61 @@ +<!-- + #%L + JAXX :: Widgets + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<org.jdesktop.swingx.JXDatePicker> + + <import> + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + org.jdesktop.swingx.plaf.basic.ExtendedBasicDatePickerUI + java.text.SimpleDateFormat + </import> + + <Boolean id='showPopupButton' javaBean='Boolean.TRUE'/> + + <String id='patternLayout' javaBean='"dd/MM/yyyy"'/> + + <ExtendedBasicDatePickerUI id='extendedUI' showPopupButton='{showPopupButton}'/> + + <script><![CDATA[ + protected void $afterCompleteSetup() { + + setUI(extendedUI); + + addPropertyChangeListener(PROPERTY_SHOW_POPUP_BUTTON, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + extendedUI.setShowPopupButton((Boolean) evt.getNewValue()); + } + }); + + addPropertyChangeListener(PROPERTY_PATTERN_LAYOUT, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + setFormats(new SimpleDateFormat((String) evt.getNewValue())); + } + }); + } + ]]></script> +</org.jdesktop.swingx.JXDatePicker> \ No newline at end of file diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXWidgetUtil.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXWidgetUtil.java new file mode 100644 index 0000000..d40f2e7 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/JAXXWidgetUtil.java @@ -0,0 +1,63 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import jaxx.runtime.SwingUtil; +import jaxx.runtime.swing.editor.cell.DateCellEditor; +import jaxx.runtime.swing.editor.cell.FileCellEditor; +import jaxx.runtime.swing.editor.cell.KeyStrokeCellEditor; +import jaxx.runtime.swing.editor.cell.NumberCellEditor; +import jaxx.runtime.swing.renderer.DateCellRenderer; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class JAXXWidgetUtil extends SwingUtil { + + public static TableCellRenderer newDateTableCellRenderer(TableCellRenderer renderer) { + return newDateTableCellRenderer(renderer, null); + } + + public static TableCellRenderer newDateTableCellRenderer(TableCellRenderer renderer, String datePattern) { + return new DateCellRenderer(renderer, datePattern); + } + + public static TableCellEditor newDateTableCellEditor() { + return new DateCellEditor(); + } + + public static TableCellEditor newFileTableCellEditor() { + return new FileCellEditor(); + } + + public static TableCellEditor newKeyStrokeTableCellEditor() { + return new KeyStrokeCellEditor(); + } + + public static <E extends Number> NumberCellEditor<E> newNumberTableCellEditor(Class<E> type, boolean useSign) { + return new NumberCellEditor<E>(type, useSign); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelector.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelector.jaxx new file mode 100644 index 0000000..34e8204 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelector.jaxx @@ -0,0 +1,80 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<Table insets='0' genericType='B' abstract='true'> + + <import> + com.google.common.collect.Lists + java.util.List + javax.swing.DefaultComboBoxModel + javax.swing.DefaultListModel + javax.swing.DefaultListCellRenderer + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + javax.swing.event.ListDataListener + jaxx.runtime.swing.model.GenericListModel + jaxx.runtime.swing.model.GenericListListener + java.util.Collection + java.util.Set + </import> + + <String id='addToolTip' javaBean='"+"'/> + + <String id='removeToolTip' javaBean='"-"'/> + + <ListSelectorModel id='model' + genericType='B' + javaBean='null'/> + + <ListCellRenderer id='renderer' javaBean='new DefaultListCellRenderer()'/> + + <script><![CDATA[ + +public void setValues(Collection<B> values) { + model.setValues(values); +} + +public Collection<B> getValues() { + return model.getValues(); +} + +public void setSelectedValues(Collection<B> selectedValues) { + model.setSelectedValues(selectedValues); +} + +public Collection<B> getSelectedValues() { + return model.getSelectedValues(); +} + +public void addGenericListListener(GenericListListener l) { + model.addGenericListListener(l); +} + +public void removeGenericListListener(GenericListListener l) { + model.removeGenericListListener(l); +} +]]> + </script> + +</Table> \ No newline at end of file diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelectorModel.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelectorModel.java new file mode 100644 index 0000000..fda3ed0 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListSelectorModel.java @@ -0,0 +1,187 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import com.google.common.collect.Lists; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Collection; +import jaxx.runtime.swing.model.GenericListListener; +import jaxx.runtime.swing.model.GenericListModel; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class ListSelectorModel<B> { + + protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public static final String PROPERTY_ADD_ENABLED = "addEnabled"; + public static final String PROPERTY_REMOVE_ENABLED = "removeEnabled"; + + public static final String PROPERTY_SELECTED_VALUES = "selectedValues"; + public static final String PROPERTY_VALUES = "values"; + + protected boolean addEnabled; + protected boolean removeEnabled; + + protected GenericListModel<B> fromModel; + protected GenericListModel<B> toModel; + + protected ListSelectorModel() { + + fromModel = new GenericListModel<B>(); + fromModel.addPropertyChangeListener(GenericListModel.PROPERTY_SELECTED_VALUE, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + setAddEnabled(fromModel.hasSelectedIndex()); + } + }); + + toModel = new GenericListModel<B>(); + toModel.addPropertyChangeListener(GenericListModel.PROPERTY_SELECTED_VALUE, new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + setRemoveEnabled(toModel.hasSelectedIndex()); + } + }); + } + + public boolean isAddEnabled() { + return addEnabled; + } + + public void setAddEnabled(boolean addEnabled) { + boolean oldValue = isAddEnabled(); + this.addEnabled = addEnabled; + firePropertyChange(PROPERTY_ADD_ENABLED, oldValue, addEnabled); + } + + public boolean isRemoveEnabled() { + return removeEnabled; + } + + public void setRemoveEnabled(boolean removeEnabled) { + boolean oldValue = isRemoveEnabled(); + this.removeEnabled = removeEnabled; + firePropertyChange(PROPERTY_REMOVE_ENABLED, oldValue, removeEnabled); + } + + public GenericListModel<B> getFromModel() { + return fromModel; + } + + public GenericListModel<B> getToModel() { + return toModel; + } + + public Collection<B> getValues() { + return fromModel.getElements(); + } + + public void setValues(Collection<B> values) { + Collection<B> oldValues = getValues(); + toModel.clearElements(); + fromModel.setElements(values); + firePropertyChange(PROPERTY_VALUES, oldValues, values); + } + + public void addValues(Collection<B> values) { + Collection<B> oldValues = getValues(); + toModel.removeElements(values); + fromModel.removeElements(values); + fromModel.addElements(values); + firePropertyChange(PROPERTY_VALUES, oldValues, values); + } + + public void removeValues(Collection<B> values) { + Collection<B> oldValues = getValues(); + toModel.removeElements(values); + fromModel.removeElements(values); + firePropertyChange(PROPERTY_VALUES, oldValues, values); + } + + public Collection<B> getSelectedValues() { + return toModel.getElements(); + } + + public void setSelectedValues(Collection<B> selectedValues) { + Collection<B> oldValue = getSelectedValues(); + fromModel.removeElements(selectedValues); + toModel.removeElements(selectedValues); + toModel.setElements(selectedValues); + firePropertyChange(PROPERTY_SELECTED_VALUES, oldValue, selectedValues); + } + + public void add() { + Collection<B> oldValues = getValues(); + Collection<B> oldSelectedValue = getSelectedValues(); + moveSelect(fromModel, toModel); + firePropertyChange(PROPERTY_VALUES, oldValues, getValues()); + firePropertyChange(PROPERTY_SELECTED_VALUES, oldSelectedValue, getSelectedValues()); + } + + public void remove() { + moveSelect(toModel, fromModel); + } + + protected void moveSelect(GenericListModel<B> from, GenericListModel<B> to) { + Collection<B> selectedValues = Lists.newArrayList(from.getSelectedValues()); + from.removeElements(selectedValues); + to.addElements(selectedValues); + } + + public void addGenericListListener(GenericListListener l) { + toModel.addGenericListListener(l); + } + + public void removeGenericListListener(GenericListListener l) { + toModel.removeGenericListListener(l); + } + + 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); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) { + pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListToListSelector.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListToListSelector.jaxx new file mode 100644 index 0000000..f893848 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/ListToListSelector.jaxx @@ -0,0 +1,90 @@ +<!-- + #%L + JAXX :: Widgets + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<ListSelector genericType='B' superGenericType='B'> + <import> + javax.swing.SwingConstants + java.util.Set + java.beans.PropertyChangeEvent + java.beans.PropertyChangeListener + </import> + + <script><![CDATA[ + +protected void $afterCompleteSetup() { + + addPropertyChangeListener(PROPERTY_MODEL, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + + Set<String> bindings = $bindings.keySet(); + JAXXUtil.applyDataBinding(ListToListSelector.this, bindings); + JAXXUtil.processDataBinding( + ListToListSelector.this, bindings.toArray(new String[bindings.size()])); + } + }); +} +]]></script> + + <ListSelectorModel id='model' + genericType='B' + initializer='new ListSelectorModel()'/> + <row> + <cell fill='both' weightx='1' weighty='1' rows="2"> + <JScrollPane id='fromScrollpane'> + <JList id='from' + model='{model.getFromModel()}' + selectionModel='{model.getFromModel()}' + onMouseClicked='if (event.getClickCount()==2) { model.add(); }' + cellRenderer='{getRenderer()}'/> + </JScrollPane> + </cell> + <cell anchor='north'> + <JButton id="add" + toolTipText='{getAddToolTip()}' + actionIcon='select' + enabled='{model.isAddEnabled()}' + onActionPerformed='model.add()'/> + </cell> + + <cell fill='both' weightx='1' weighty='1' rows="2"> + <JScrollPane id='toScrollpane'> + <JList id='to' + model='{model.getToModel()}' + selectionModel='{model.getToModel()}' + onMouseClicked='if (event.getClickCount()==2) { model.remove(); }' + cellRenderer='{getRenderer()}'/> + </JScrollPane> + </cell> + </row> + <row> + <cell anchor='north'> + <JButton id="remove" + toolTipText='{getRemoveToolTip()}' + actionIcon='unselect' + enabled='{model.isRemoveEnabled()}' + onActionPerformed='model.remove()'/> + </cell> + </row> +</ListSelector> \ No newline at end of file diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidget.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidget.jaxx new file mode 100644 index 0000000..7d9c1c8 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidget.jaxx @@ -0,0 +1,81 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<JComponent implements='java.awt.event.ActionListener' + foreground='{Color.BLACK}' + background='{Color.WHITE}'> + + <import> + java.awt.Color + java.awt.Graphics + java.awt.event.ActionEvent + javax.swing.Timer + </import> + + <MemoryStatusWidgetHandler id='handler' constructorParams='this'/> + + <javax.swing.Timer id='timer' javaBean='null'/> + + <Color id='progressBackground' javaBean='Color.decode("#666699a")'/> + <Color id='progressForeground' javaBean='Color.decode("#cccccc")'/> + + <script><![CDATA[ + + +@Override +public void actionPerformed(ActionEvent evt) { + repaint(); +} + +/** Adds a feature to the Notify attribute of the MemoryStatus object */ +@Override +public void addNotify() { + super.addNotify(); + setTimer(new Timer(2000, this)); + timer.start(); +} + +@Override +public void removeNotify() { + if (timer != null) { + timer.stop(); + timer = null; + } + super.removeNotify(); +} + +@Override +public void paintComponent(Graphics g) { + handler.paintComponent(g); +} + + +void $afterCompleteSetup() { + handler.$afterCompleteSetup(); +} +]]> + </script> +</JComponent> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidgetHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidgetHandler.java new file mode 100644 index 0000000..1f6e0f5 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/MemoryStatusWidgetHandler.java @@ -0,0 +1,101 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing; + +import javax.swing.JLabel; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.geom.Rectangle2D; + +import static org.nuiton.i18n.I18n._; + +/** + * Handler of ui {@link MemoryStatusWidget}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class MemoryStatusWidgetHandler { + + private final static String memoryTestStr = "99999/99999Mb"; + + private FontRenderContext frc = new FontRenderContext(null, false, false); + + private LineMetrics lm = new JLabel().getFont().getLineMetrics(memoryTestStr, frc); + + protected final MemoryStatusWidget ui; + + public MemoryStatusWidgetHandler(MemoryStatusWidget ui) { + this.ui = ui; + } + + public void paintComponent(Graphics g) { + Insets insets = new Insets(0, 0, 0, 0); + Runtime runtime = Runtime.getRuntime(); + int freeMemory = (int) (runtime.freeMemory() / 1024L); + int totalMemory = (int) (runtime.totalMemory() / 1024L); + int usedMemory = totalMemory - freeMemory; + int width = ui.getWidth() - insets.left - insets.right; + int height = ui.getHeight() - insets.top - insets.bottom - 1; + float fraction = (float) usedMemory / (float) totalMemory; + g.setColor(ui.progressBackground); + g.fillRect(insets.left, insets.top, (int) ((float) width * fraction), height); + // No i18n string was : + // String str = usedMemory / 1024 + "/" + totalMemory / 1024 + "Mb"; + String str = _("memorywidget.memory", usedMemory / 1024, totalMemory / 1024); + //FontRenderContext frc = new FontRenderContext(null, false, false); + Rectangle2D bounds = g.getFont().getStringBounds(str, frc); + Graphics g2 = g.create(); + g2.setClip(insets.left, insets.top, + (int) ((float) width * fraction), height); + g2.setColor(ui.progressForeground); + g2.drawString(str, insets.left + + (int) ((double) width - bounds.getWidth()) / 2, + (int) ((float) insets.top + lm.getAscent())); + g2.dispose(); + g2 = g.create(); + g2.setClip(insets.left + (int) ((float) width * fraction), + insets.top, ui.getWidth() - insets.left + - (int) ((float) width * fraction), height); + g2.setColor(ui.getForeground()); + g2.drawString(str, insets.left + + (int) ((double) width - bounds.getWidth()) / 2, + (int) ((float) insets.top + lm.getAscent())); + g2.dispose(); + } + + + void $afterCompleteSetup() { + ui.setFont(new JLabel().getFont()); + Rectangle2D bounds = ui.getFont().getStringBounds(memoryTestStr, frc); + Dimension dim = new Dimension((int) bounds.getWidth(), (int) bounds.getHeight()); + ui.setPreferredSize(dim); + ui.setMaximumSize(dim); + } + +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanel.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanel.jaxx new file mode 100644 index 0000000..9c4424d --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanel.jaxx @@ -0,0 +1,143 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<Table border='{BorderFactory.createBevelBorder(BevelBorder.LOWERED)}' + insets='0' + implements='java.awt.event.ActionListener'> + + <import> + java.awt.Component + java.awt.event.ActionEvent + javax.swing.BorderFactory + javax.swing.border.BevelBorder + </import> + + <script><![CDATA[ + +// To ensure status bar constant height, no matter what font are in use... +protected final static String EMPTY_STATUS = " "; + +public void clearStatus() { + handler.clearStatus(); +} + +public void startProgress() { + startProgress(null); +} + +public void startProgress(String status) { + setBusy(true); + setStatus(status); +} + +public void stopProgress() { + stopProgress(null); +} + +public void stopProgress(String finalStatus) { + setBusy(false); + setStatus(finalStatus); +} + +public void setStatus(String status) { + handler.setStatus(status); +} + +@Override +public void actionPerformed(ActionEvent evt) { + handler.fadeStatus(this); +} + +public <U extends Component> U getWidget(Class<U> clazz) { + for (Component component : box.getComponents()) { + if (clazz == component.getClass()) { + return (U) component; + } + } + return null; +} + +public void addWidget(Component w) { + box.add(w); +} + +public void addWidget(Component w, int index) { + box.add(w, index); +} + +public void init() { + handler.init(); +} + +void $afterCompleteSetup() { + handler.$afterCompleteSetup(); +} +]]> + </script> + + <Boolean id='showMemoryStatus' javaBean='Boolean.TRUE'/> + <Boolean id='showClock' javaBean='Boolean.TRUE'/> + <Boolean id='showI18n' javaBean='Boolean.FALSE'/> + <Boolean id='showBusy' javaBean='Boolean.FALSE'/> + <Boolean id='busy' javaBean='Boolean.FALSE'/> + + <StatusMessagePanelHandler id='handler' constructorParams='this'/> + + <row> + <cell anchor='west' fill='both' weightx='1'> + <Box constructorParams='0'> + <JProgressBar id='busyWidget' + visible='{isShowBusy()}' + enabled='{isBusy()}' + indeterminate='{isBusy()}' + stringPainted='false' + borderPainted='true'/> + <!--visible='{isBusy() && isShowBusy()}'--> + + <JLabel id='statusLabel'/> + + </Box> + + </cell> + <cell anchor='east'> + <Box id='box' constructorParams='0'> + + <!--JProgressBar id='busyWidget' + visible='{isBusy() && isShowBusy()}' + indeterminate='{isBusy()}' + stringPainted='false' + borderPainted='true'/--> + <!-- +minimumSize='{new Dimension(30,1)}' + maximumSize='{new Dimension(30,30)}' + preferredSize='{new Dimension(30,30)}' + --> + <MemoryStatusWidget/> + <ClockWidget/> + </Box> + </cell> + </row> +</Table> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanelHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanelHandler.java new file mode 100644 index 0000000..8b70e38 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/StatusMessagePanelHandler.java @@ -0,0 +1,127 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing; + +import javax.swing.Timer; +import java.awt.Color; +import java.awt.Dimension; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.6.0 + */ +public class StatusMessagePanelHandler { + + protected final StatusMessagePanel ui; + + protected Color statusForeground; + + protected String statusReferenceContent; + + protected Timer timer; + + public StatusMessagePanelHandler(StatusMessagePanel ui) { + this.ui = ui; + } + + void $afterCompleteSetup() { + init(); + } + + public void init() { + if (ui.isShowBusy()) { + Dimension dim = new Dimension(30, 15); + //Dimension dim = new Dimension(30, (int) statusLabel.getPreferredSize().getHeight()); + //log.info("dimension of busy = "+ dim); + //busyWidget.setPreferredSize(dim); + ui.busyWidget.setMaximumSize(dim); + ui.busyWidget.setMinimumSize(dim); + } + } + + public void clearStatus() { + stopStatusFader(ui); + ui.getStatusLabel().setText(StatusMessagePanel.EMPTY_STATUS); + //getStatusLabel().setString(EMPTY_STATUS); + } + + public void setStatus(String status) { + if (status != null) { + stopStatusFader(ui); + ui.getStatusLabel().setText(status); + //getStatusLabel().setString(status); + } + + if (!ui.isBusy()) { + startStatusFader(ui); + } + } + + protected void fadeStatus(StatusMessagePanel ui) { + for (int i = 0; i < 8; i++) { + // synchronized (this) { + if (!statusReferenceContent.equals(ui.getStatusLabel().getText())) { +// if (!statusReferenceContent.equals(ui.getStatusLabel().getString())) { + return; + } + Color currentForeground = ui.getStatusLabel().getForeground(); + Color newColor = new Color(currentForeground.getRed(), + currentForeground.getGreen(), + currentForeground.getBlue(), + currentForeground.getAlpha() - 25); + ui.getStatusLabel().setForeground(newColor); + ui.getStatusLabel().repaint(); + // } + // TC-2000311 je comprends pas a quoi ca sert, a part frizzer les ui ? + // si on utilise un Timer, pourquoi utiliser ça ? + /*try { + Thread.sleep(200); + } catch (InterruptedException eee) { + eee.printStackTrace(); + }*/ + } + } + + protected void startStatusFader(StatusMessagePanel ui) { + statusReferenceContent = ui.getStatusLabel().getText(); +// statusReferenceContent = ui.getStatusLabel().getString(); + + int millisecondsPerMinute = 5000; + timer = new Timer(millisecondsPerMinute, ui); + timer.setRepeats(false); + timer.setInitialDelay((int) ((long) millisecondsPerMinute - + System.currentTimeMillis() % + (long) millisecondsPerMinute) + 500); + timer.start(); + } + + protected void stopStatusFader(StatusMessagePanel ui) { + if (timer != null) { + timer.stop(); + ui.getStatusLabel().setForeground(statusForeground); + } + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditor.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditor.jaxx new file mode 100644 index 0000000..21d67ce --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditor.jaxx @@ -0,0 +1,80 @@ +<!-- + #%L + JAXX :: Widgets + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<BaseActionPanel layout='{new BorderLayout()}'> + <import> + java.io.File + jaxx.runtime.swing.BaseActionPanel + org.apache.commons.lang3.StringUtils + </import> + + <FileEditorHandler id='handler' constructorParams='this'/> + + <Boolean id='acceptAllFileFilterUsed' javaBean='Boolean.TRUE'/> + + <Boolean id='directoryEnabled' javaBean='Boolean.TRUE'/> + + <Boolean id='fileEnabled' javaBean='Boolean.TRUE'/> + + <String id='startPath' javaBean='null'/> + + <String id='title' javaBean='null'/> + + <String id='exts' javaBean='null'/> + + <String id='extsDescription' javaBean='null'/> + + <script><![CDATA[ + protected File selectedFile; + + public void setSelectedFile(File selectedFile) { + this.selectedFile = selectedFile; + if (selectedFile != null) { + setStartPath(selectedFile.getAbsolutePath()); + fireActionEvent(); + } + } + + public File getSelectedFile() { + if (selectedFile == null) { + if (StringUtils.isNotEmpty(startPath)) { + selectedFile = new File(startPath); + } + } + return selectedFile; + } + + ]]></script> + + <JTextField id='pathField' + constraints='BorderLayout.CENTER' + enabled='{isEnabled()}' + text='{getStartPath()}' + onKeyReleased='setSelectedFile(null);setStartPath(pathField.getText())'/> + + <JButton id='boutonXslLocation' + constraints='BorderLayout.EAST' + enabled='{isEnabled()}' + actionIcon='open' + onActionPerformed='handler.openLocation()'/> +</BaseActionPanel> \ No newline at end of file diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditorHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditorHandler.java new file mode 100644 index 0000000..f4e56a6 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/FileEditorHandler.java @@ -0,0 +1,169 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor; + +import com.google.common.io.Files; +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import org.apache.commons.lang3.StringUtils; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class FileEditorHandler { + + public static final String SEPARATOR_REGEX = "\\s*,\\s*"; + public static File lastSelectedPath; + + protected FileEditor view; + + public FileEditorHandler(FileEditor view) { + this.view = view; + if (lastSelectedPath == null) { + lastSelectedPath = new File(System.getProperty("user.home")); + } + } + + public void openLocation() { + + // use last selected file + File startFile = view.getSelectedFile(); + String startPath = view.getStartPath(); + if (startFile == null && StringUtils.isNotEmpty(startPath)) { + + // else filed start path + startFile = new File(startPath); + } else if (startFile == null) { + + // else start with user home + startFile = lastSelectedPath; + } + JFileChooser fc = new JFileChooser(startFile); + + fc.setDialogTitle(view.getTitle()); + fc.setAcceptAllFileFilterUsed(view.getAcceptAllFileFilterUsed()); + + // TODO sletellier 14/06/2012 : activate multi selection +// boolean multiSelectionEnabled = view.isMultiSelectionEnabled(); +// fc.setMultiSelectionEnabled(multiSelectionEnabled); + + // used to enable directory selection + boolean directoryEnabled = view.isDirectoryEnabled(); + if (directoryEnabled) { + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + } + + // used to enable file selection + boolean fileEnabled = view.isFileEnabled(); + if (fileEnabled) { + + if (directoryEnabled) { + + // both + fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + } else { + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + } + String extsAsString = view.getExts(); + if (extsAsString != null) { + + // extentions can be separted by comma + String[] exts = extsAsString.split(SEPARATOR_REGEX); + String extsDescription = view.getExtsDescription(); + + String[] descs = new String[0]; + if (extsDescription != null) { + descs = extsDescription.split(SEPARATOR_REGEX); + } + for (int i = 0;i<exts.length;i++) { + + // use ext if no desc found + String ext = exts[i]; + String desc = ext; + if (descs.length > i) { + desc = descs[i]; + } + + fc.addChoosableFileFilter(new ExtentionFileFiler(ext, desc)); + } + } + } + + // directory or/and file must be enabled + if (!directoryEnabled && !fileEnabled) { + throw new IllegalArgumentException("You must enable at least file or directory to open dialog"); + } + + // show dialog + int returnVal = fc.showOpenDialog(view); + if (returnVal == JFileChooser.APPROVE_OPTION) { + + // get selected to display in ui + File file = fc.getSelectedFile(); + + setSelectedFile(file); + } + } + + public void setSelectedFile(String path) { + setSelectedFile(new File(path)); + } + + public void setSelectedFile(File file) { + view.setSelectedFile(file); + view.setStartPath(file.getPath()); + File dir = file; + if (dir.exists()) { + if (!dir.isDirectory()) { + dir = dir.getParentFile(); + } + lastSelectedPath = dir; + } + } + + public static class ExtentionFileFiler extends FileFilter { + protected String ext; + protected String desciption; + + public ExtentionFileFiler(String ext, String desciption) { + this.ext = ext; + this.desciption = desciption; + } + + @Override + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } + String fileExtension = Files.getFileExtension(file.getName()); + return ext.equals(fileExtension); + } + + @Override + public String getDescription() { + return desciption; + } + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditor.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditor.jaxx new file mode 100644 index 0000000..b705451 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditor.jaxx @@ -0,0 +1,147 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<JPanel implements='PropertyChangeListener, ActionListener' + id='content' + layout='{new BorderLayout()}' + onFocusGained='button.requestFocus()' + onFocusLost='setPopupVisible(false)'> + + <import> + + jaxx.runtime.SwingUtil + + java.awt.BorderLayout + java.awt.event.ItemEvent + java.awt.event.ActionEvent + java.awt.event.ActionListener + javax.swing.border.TitledBorder + + java.beans.PropertyChangeListener + java.beans.PropertyChangeEvent + java.util.Locale + + jaxx.runtime.swing.renderer.LocaleListCellRenderer + + static org.nuiton.i18n.I18n.n_ + </import> + + <I18nEditorHandler id='handler' constructorParams='this'/> + + <String id='selectedToolTipText' javaBean='null'/> + <String id='notSelectedToolTipText' javaBean='null'/> + + <Border id='popupBorder' + javaBean='new TitledBorder(_("i18neditor.popup.title"))'/> + + <Boolean id='showText' javaBean='Boolean.TRUE'/> + <Boolean id='showIcon' javaBean='Boolean.TRUE'/> + <Boolean id='showPopupText' javaBean='Boolean.TRUE'/> + <Boolean id='showPopupIcon' javaBean='Boolean.TRUE'/> + <Boolean id='popupVisible' javaBean='Boolean.FALSE'/> + + <java.util.List id='locales' javaBean='null' genericType='Locale'/> + + <Locale id='selectedLocale' javaBean='Locale.getDefault()'/> + + <LocaleListCellRenderer id='renderer' + showIcon='{isShowIcon()}' + showText='{isShowText()}' + javaBean='new LocaleListCellRenderer(showIcon , showText)'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + border='{getPopupBorder()}' + onPopupMenuWillBecomeInvisible='button.setSelected(false)' + onPopupMenuCanceled='button.setSelected(false)'> + <JLabel id='popupLabel' enabled='false' text='i18neditor.empty.locales'/> + </JPopupMenu> + + <JToggleButton + id='button' + text='{SwingUtil.getStringValue(renderer.getText(getSelectedLocale()))}' + toolTipText='{getTip(getSelectedLocale())}' + icon='{renderer.getIcon(getSelectedLocale())}' + constraints='BorderLayout.CENTER' + selected='{popup.isVisible()}' + focusable='true' + focusPainted='false' + onItemStateChanged='if (event.getStateChange() == ItemEvent.SELECTED) { setPopupVisible(true); } else { popupVisible = false; }'/> + + <ButtonGroup id='indexes' + onStateChanged='log.info(indexes.getSelectedValue())'/> + + <script><![CDATA[ +public static final String DEFAULT_SELECTED_TOOLTIP = n_("i18neditor.selected"); +public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n_("i18neditor.unselected"); + +public static final String LOCALES_PROPERTY = "locales"; +public static final String SELECTED_LOCALE_PROPERTY = "selectedLocale"; +public static final String SHOW_ICON_PROPERTY = "showIcon"; +public static final String SHOW_TEXT_PROPERTY = "showText"; +public static final String SHOW_POPUP_ICON_PROPERTY = "showPopupIcon"; +public static final String SHOW_POPUP_TEXT_PROPERTY = "showPopupText"; +public static final String POPUP_BORDER_PROPERTY = "popupBorder"; +public static final String POPUP_VISIBLE_PROPERTY = "popupVisible"; + + + +void $afterCompleteSetup() { + handler.$afterCompleteSetup(); +} + +@Override +public void propertyChange(PropertyChangeEvent evt) { + handler.propertyChange(evt); +} + +@Override +public void actionPerformed(ActionEvent event) { + handler.actionPerformed(event); +} + +public void loadI18nBundles() { + handler.loadI18nBundles(); +} + +protected void rebuildPopup() { + handler.rebuildPopup(); +} + +protected String getTip(Locale l) { + return handler.getTip(l); +} + +protected String getSelectedTip(Locale l) { + return handler.getSelectedTip(l); +} + +protected String getNotSelectedTip(Locale l) { + return handler.getNotSelectedTip(l); +} +]]> + </script> +</JPanel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditorHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditorHandler.java new file mode 100644 index 0000000..5ebed5a --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/I18nEditorHandler.java @@ -0,0 +1,250 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2011 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor; + +import jaxx.runtime.swing.JAXXButtonGroup; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.i18n.I18n; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JToggleButton; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; + +/** + * Handler of ui {@link I18nEditor}. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class I18nEditorHandler implements PropertyChangeListener, ActionListener { + + private static final Log log = LogFactory.getLog(I18nEditorHandler.class); + + protected final I18nEditor ui; + + public I18nEditorHandler(I18nEditor ui) { + this.ui = ui; + } + + public static final String DEFAULT_SELECTED_TOOLTIP = n_("i18neditor.selected"); + + public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n_("i18neditor.unselected"); + + public static final String LOCALES_PROPERTY = "locales"; + + public static final String SELECTED_LOCALE_PROPERTY = "selectedLocale"; + + public static final String SHOW_ICON_PROPERTY = "showIcon"; + + public static final String SHOW_TEXT_PROPERTY = "showText"; + + public static final String SHOW_POPUP_ICON_PROPERTY = "showPopupIcon"; + + public static final String SHOW_POPUP_TEXT_PROPERTY = "showPopupText"; + + public static final String POPUP_BORDER_PROPERTY = "popupBorder"; + + public static final String POPUP_VISIBLE_PROPERTY = "popupVisible"; + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String name = evt.getPropertyName(); + if (log.isDebugEnabled()) { + log.debug(name + " <old:" + evt.getOldValue() + " - new:" + evt.getNewValue() + ">"); + } + log.info(name + " <old:" + evt.getOldValue() + " - new:" + evt.getNewValue() + ">"); + if (LOCALES_PROPERTY.equals(name)) { + Collection<?> newLocales = (Collection<?>) evt.getNewValue(); + // mise a jour de la popup + boolean oldShowText = ui.renderer.isShowText(); + try { + ui.renderer.setShowText(true); + ui.popup.removeAll(); + for (Object o : newLocales) { + Locale l = (Locale) o; + boolean selected = l.equals(ui.selectedLocale); + String text = ui.isShowPopupText() ? ui.renderer.getText(l) : null; + Icon icon = ui.isShowPopupIcon() ? ui.renderer.getIcon(l) : null; + JRadioButtonMenuItem b = new JRadioButtonMenuItem(text, icon, selected); + ui.popup.add(b); + b.addActionListener(ui); + b.putClientProperty("locale", l); + b.setToolTipText(getTip(l)); + b.putClientProperty(JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY, ui.getIndexes()); + b.putClientProperty(JAXXButtonGroup.VALUE_CLIENT_PROPERTY, l); + } + } finally { + ui.renderer.setShowText(oldShowText); + ui.popup.invalidate(); + } + return; + } + if (SHOW_ICON_PROPERTY.equals(name)) { + ui.renderer.setShowIcon((Boolean) evt.getNewValue()); + ui.processDataBinding("button.icon"); + return; + } + if (SHOW_TEXT_PROPERTY.equals(name)) { + ui.renderer.setShowText((Boolean) evt.getNewValue()); + ui.processDataBinding("button.text"); + return; + } + if (SHOW_POPUP_ICON_PROPERTY.equals(name)) { + rebuildPopup(); + return; + } + if (SHOW_POPUP_TEXT_PROPERTY.equals(name)) { + rebuildPopup(); + return; + } + if (POPUP_BORDER_PROPERTY.equals(name)) { + ui.popup.setBorder((Border) evt.getNewValue()); + return; + } + if (POPUP_VISIBLE_PROPERTY.equals(name)) { + Boolean newValue = (Boolean) evt.getNewValue(); + if (newValue == null || !newValue) { + if (ui.getPopup() != null && ui.getPopup().isVisible()) { + ui.getPopup().setVisible(false); + } + return; + } + if (!ui.getPopup().isVisible()) { + SwingUtilities.invokeLater(showPopupRunnable); + } + return; + } + if (SELECTED_LOCALE_PROPERTY.equals(name)) { + Locale newLocale = (Locale) evt.getNewValue(); + // mise a jour de la popup + try { + for (Component c : ui.popup.getComponents()) { + if (c instanceof JRadioButtonMenuItem) { + JRadioButtonMenuItem b = (JRadioButtonMenuItem) c; + Locale l = (Locale) b.getClientProperty("locale"); + b.setSelected(newLocale.equals(l)); + } + } + } finally { + ui.popup.invalidate(); + } + } + } + + @Override + public void actionPerformed(ActionEvent event) { + Locale value = (Locale) + ((JComponent) event.getSource()).getClientProperty("locale"); + if (log.isDebugEnabled()) { + log.debug("new locale : " + value); + } + ui.setSelectedLocale(value); + } + + public void loadI18nBundles() { + Locale[] locales = I18n.getStore().getLocales(); + ui.setLocales(Arrays.asList(locales)); + } + + protected void rebuildPopup() { + log.debug("start rebuild"); + try { + for (Component c : ui.popup.getComponents()) { + if (c instanceof JRadioButtonMenuItem) { + JRadioButtonMenuItem b = (JRadioButtonMenuItem) c; + Locale l = (Locale) b.getClientProperty("locale"); + String text = ui.isShowPopupText() ? ui.renderer.getSafeText(l) : null; + Icon icon = ui.isShowPopupIcon() ? ui.renderer.getSafeIcon(l) : null; + b.setIcon(icon); + b.setText(text); + log.debug("text=" + text); + log.debug("icon=" + icon); + } + } + } finally { + ui.popup.invalidate(); + } + } + + protected String getTip(Locale l) { + boolean selected = l.equals(ui.selectedLocale); + String tip = selected ? getSelectedTip(l) : getNotSelectedTip(l); + return tip; + } + + protected String getSelectedTip(Locale l) { + String selectedTip = ui.getSelectedToolTipText(); + if (selectedTip == null) { + // use default selected tip text + selectedTip = DEFAULT_SELECTED_TOOLTIP; + } + String tip = ui.renderer.getToolTipText(l); + tip = _(selectedTip, tip); + return tip; + } + + protected String getNotSelectedTip(Locale l) { + String selectedTip = ui.getNotSelectedToolTipText(); + if (selectedTip == null) { + // use default not selected tip text + selectedTip = DEFAULT_NOT_SELECTED_TOOLTIP; + } + String tip = ui.renderer.getToolTipText(l); + tip = _(selectedTip, tip); + return tip; + } + + protected Runnable showPopupRunnable = new Runnable() { + @Override + public void run() { + ui.getPopup().pack(); + JToggleButton invoker = ui.getButton(); + Dimension dim = ui.getPopup().getPreferredSize(); + Dimension invokerDim = invoker.getSize(); + ui.getPopup().show(invoker, (int) (invokerDim.getWidth() - dim.getWidth()), invoker.getHeight()); +// getPopup().setVisible(true); + } + }; + + void $afterCompleteSetup() { + ui.addPropertyChangeListener(this); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/KeyStrokeEditor.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/KeyStrokeEditor.java new file mode 100644 index 0000000..b32c9df --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/KeyStrokeEditor.java @@ -0,0 +1,82 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor; + +import java.awt.event.KeyEvent; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Custom text field to disable default key events + * + * @author sletellier <letellier@codelutin.com> + */ +public class KeyStrokeEditor extends JTextField { + + private static final Log log = LogFactory.getLog(KeyStrokeEditor.class); + + protected KeyStroke keyStroke; + + public KeyStrokeEditor() { + enableEvents(KeyEvent.KEY_EVENT_MASK); + setFocusTraversalKeysEnabled(false); + } + + @Override + protected void processKeyEvent(KeyEvent e) { + if (e.getID() == KeyEvent.KEY_PRESSED) { + int keyCode = e.getKeyCode(); + if (keyCode == KeyEvent.VK_SHIFT || + keyCode == KeyEvent.VK_ALT || + keyCode == KeyEvent.VK_CONTROL || + keyCode == KeyEvent.VK_ALT_GRAPH || + keyCode == KeyEvent.VK_META) { + + return; + } + + setKeyStroke(KeyStroke.getKeyStroke(keyCode, e.getModifiers())); + } + } + + public KeyStroke getKeyStroke() { + return keyStroke; + } + + public void setKeyStroke(KeyStroke keyStroke) { + KeyStroke oldValue = getKeyStroke(); + this.keyStroke = keyStroke; + firePropertyChange("keyStroke", oldValue, keyStroke); + fireActionPerformed(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + setText(getKeyStroke().toString()); + } + }); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditor.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditor.jaxx new file mode 100644 index 0000000..76366f8 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditor.jaxx @@ -0,0 +1,199 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<JPanel layout='{new BorderLayout()}' + onFocusGained='textField.requestFocus()' + onFocusLost='setPopupVisible(false);popup.setVisible(false);' + onMouseExited='setPopupVisible(false);popup.setVisible(false);'> + + <import> + java.awt.Color + java.awt.BorderLayout + java.awt.GridLayout + java.awt.Dimension + + javax.swing.BorderFactory + + </import> + <!-- onFocusGained='if (autoPopup) setPopupVisible(true); textField.requestFocus();'--> + + <!-- bean property associated with the editing value --> + <String id='property' javaBean='""'/> + + <!-- bean property --> + <Object id='bean' javaBean='null'/> + + <!-- editor model --> + <Number id="model" javaBean='null'/> + + <!-- editor model type (specify it when you want to use a special type other than Integer or Float)--> + <Class id="modelType" genericType='?' javaBean='null'/> + + <!-- useFloat property --> + <Boolean id='useFloat' javaBean='false'/> + + <!-- useSign property --> + <Boolean id='useSign' javaBean='false'/> + + <!-- autoPopup property --> + <Boolean id='autoPopup' javaBean='false'/> + + <!-- showPopupButton property --> + <Boolean id='showPopupButton' javaBean='false'/> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <!-- show reset property --> + <String id="numberPattern" javaBean='null'/> + + <!-- internal editor model as text --> + <String id="modelText" javaBean='""'/> + + <!-- internal state --> + <Boolean id='popupVisible' javaBean='false'/> + + <!-- ui handler --> + <NumberEditorHandler id='handler' constructorParams='this'/> + + <!-- popup digital number editor --> + <JPopupMenu id='popup' + onPopupMenuWillBecomeVisible='showPopUpButton.setSelected(true)' + onPopupMenuWillBecomeInvisible='showPopUpButton.setSelected(false)' + onPopupMenuCanceled='showPopUpButton.setSelected(false)'> + <style source='NumberEditorPopup.css'/> + <JPanel layout='{new GridLayout(4,4)}' + border='{BorderFactory.createEmptyBorder(4, 4, 4, 4)}' + background='{Color.WHITE}'> + <JButton text='numbereditor.7' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.8' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.9' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.clearAll' onActionPerformed='setModel(null)' + styleClass='clear' enabled='{!getModelText().isEmpty()}'/> + + + <JButton text='numbereditor.4' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.5' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.6' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.clearOne' + onActionPerformed='getHandler().removeChar()' styleClass='clear' + enabled='{!(getModelText().isEmpty() || textField.getCaretPosition() ==0 )}'/> + + <JButton text='numbereditor.1' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.2' onActionPerformed='addChar(event)' + styleClass='digit'/> + <JButton text='numbereditor.3' onActionPerformed='addChar(event)' + styleClass='digit'/> + + <JButton enabled="false"/> + + <JButton text='numbereditor.0' onActionPerformed='addChar(event)' + styleClass='digit' + enabled='{!getEditor().getModelText().equals("0")}'/> + + <JButton id='toggleSign' text='numbereditor.toggleSign' + styleClass='operator' + onActionPerformed='getHandler().toggleSign()' + enabled='{isUseSign() && !getEditor().getModelText().isEmpty()}'/> + + <JButton id='dot' text='numbereditor..' styleClass='operator' + onActionPerformed='addChar(event)' + enabled='{isUseFloat() && getEditor().getModelText().indexOf(".") == -1 }'/> + + <JButton actionIcon='numbereditor-validate' + onActionPerformed="getHandler().validate()"/> + </JPanel> + </JPopupMenu> + <script><![CDATA[ +public void init() { + handler.init(); +} + +public NumberEditor getEditor() { + return this; +} + +public void addChar(ActionEvent event) { + getHandler().addChar(((JButton)event.getSource()).getText()); +} + +void showPopup() { + if ( popupVisible || autoPopup ) { + if (!popupVisible) { + setPopupVisible(true); + } else if (!getPopup().isVisible()) { + getHandler().setPopupVisible(true); + } + } +} + +]]> + </script> + + <JToolBar id='toolbar' + floatable='false' + borderPainted='false' + visible='{isShowReset()}' + constraints='BorderLayout.WEST'> + <JButton id='resetButton' + actionIcon='numbereditor-reset' + toolTipText='numbereditor.action.reset.tip' + focusable='false' + focusPainted='false' + enabled='{isEnabled()}' + onActionPerformed='setModel(null)'/> + </JToolBar> + + <JTextField id='textField' + constraints='BorderLayout.CENTER' + text='{getModelText()}' + enabled='{isEnabled()}' + onKeyReleased='getHandler().setModel(textField.getText())' + onFocusGained='showPopup()'/> + + <JToolBar constraints='BorderLayout.EAST' + floatable='false' + opaque='false' + borderPainted='false' + visible='{isShowPopupButton()}' + maximumSize='{new Dimension(24,24)}'> + <JToggleButton id='showPopUpButton' + focusable='false' + focusPainted='false' + actionIcon='numbereditor-calculator' + toolTipText='numbereditor.action.show.tip' + enabled='{isEnabled()}' + onActionPerformed='getHandler().setPopupVisible(!popup.isVisible())'/> + </JToolBar> + +</JPanel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorHandler.java new file mode 100644 index 0000000..d22db70 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorHandler.java @@ -0,0 +1,642 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor; + +import java.awt.Dimension; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.swing.JComponent; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import static jaxx.runtime.swing.editor.NumberEditor.PROPERTY_MODEL; +import static jaxx.runtime.swing.editor.NumberEditor.PROPERTY_POPUP_VISIBLE; + +/** + * Le handler de l'éditeur graphique de nombres. + * <p/> + * Note: Ce handler n'est pas staless, et chaque ui possède le sien. + * + * @author tchemit <chemit@codelutin.com> + * @see NumberEditor + */ +public class NumberEditorHandler { + /** Logger */ + public static final Log log = LogFactory.getLog(NumberEditorHandler.class); + + public static final String VALIDATE_PROPERTY = "validate"; + + /** editor ui */ + protected NumberEditor editor; + + /** the mutator method on the property of boxed bean in the editor */ + protected Method mutator; + + /** the getter method on the property */ + protected Method getter; + + /** a flag to known if mutator accept null value */ + protected Boolean acceptNull; + + protected Class<?> modelType; + + protected Pattern numberPattern; + + public NumberEditorHandler(NumberEditor ui) { + editor = ui; + } + + /** initialise l'ui et les listeners d'évènements. */ + public void init() { + try { +// if (editor.getBean() == null) { +// throw new NullPointerException("can not have a null bean in ui " + editor); +// } + + editor.addPropertyChangeListener(NumberEditor.PROPERTY_NUMBER_PATTERN, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String newPattern = (String) evt.getNewValue(); + if (log.isInfoEnabled()) { + log.info("set new numberPattern" + newPattern); + } + if (StringUtils.isEmpty(newPattern)) { + numberPattern = null; + } else { + numberPattern = Pattern.compile(newPattern); + } + } + }); + + editor.addPropertyChangeListener(NumberEditor.PROPERTY_SHOW_POPUP_BUTTON, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("set showPopupButton" + evt.getNewValue() + " for " + editor.getProperty()); + } + if (editor.getPopup().isVisible()) { + setPopupVisible(false); + } + } + }); + + editor.addPropertyChangeListener(NumberEditor.PROPERTY_AUTO_POPUP, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("set auto popup " + evt.getNewValue() + " for " + editor.getProperty()); + } + if (editor.getPopup().isVisible()) { + setPopupVisible(false); + } + } + }); + + editor.addPropertyChangeListener(PROPERTY_MODEL, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (log.isDebugEnabled()) { + log.debug("set new model " + evt.getNewValue() + " for " + editor.getProperty()); + } + setModel((Number) evt.getOldValue(), (Number) evt.getNewValue()); + } + }); + editor.addPropertyChangeListener(PROPERTY_POPUP_VISIBLE, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + setPopupVisible((Boolean) evt.getNewValue()); + } + }); + editor.getTextField().addMouseListener(new PopupListener()); + + // Initialise le number pattern + if (StringUtils.isNotEmpty(editor.getNumberPattern())) { + numberPattern = Pattern.compile(editor.getNumberPattern()); + } + + // Determine si c'est un float + Class<?> type = editor.getModelType(); + if (editor.getModelType() == null) { + if (editor.getBean() != null) { + type = getGetter().getReturnType(); + } + } + modelType = type; + if (log.isDebugEnabled()) { + log.debug("model type to use = " + modelType); + } + //FIXME le test n'est pas assez fort (on peut avoir un long, short,...) + editor.setUseFloat(!type.equals(Integer.class) && !type.equals(int.class)); + + // Initialise le model + if (editor.getModel() == null) { + if (editor.getBean() != null) { + Number num = (Number) getGetter().invoke(editor.getBean()); + editor.setModel(num); + } + } + + /*if (editor.getResetButton().getIcon() == null) { + editor.getResetButton().setIcon(SwingUtil.createActionIcon("numbereditor-reset")); + } + if (editor.getButton().getIcon() == null) { + editor.getButton().setIcon(SwingUtil.createActionIcon("numbereditor-calculator")); + }*/ + } catch (IllegalAccessException ex) { + log.error(ex); + } catch (IllegalArgumentException ex) { + log.error(ex); + } catch (InvocationTargetException ex) { + log.error(ex); + } + } + + /** + * Affiche ou cache la popup. + * + * @param newValue la nouvelle valeur de visibilité de la popup. + */ + public void setPopupVisible(Boolean newValue) { + + if (log.isTraceEnabled()) { + log.trace(newValue); + } + + if (newValue == null || !newValue) { + editor.getPopup().setVisible(false); + return; + } + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + JComponent invoker = + editor.isShowPopupButton() ? + editor.getShowPopUpButton() : + editor; + Dimension dim = editor.getPopup().getPreferredSize(); + int x = (int) (invoker.getPreferredSize().getWidth() - dim.getWidth()); + editor.getPopup().show(invoker, + x, invoker.getHeight()); + editor.getTextField().requestFocus(); + } + }); + } + + protected String lastValidText; + + /** + * Modifie le modèle de la donnée à éditer à partir d'un evenement clavier + * <p/> + * TODO utiliser une filtre sur les donnes en entrees pour ne pas a avoir + * faire les tests ici. + * + * @param s la nouvelle valeur du modèle + */ + public void setModel(String s) { + + String text = editor.getModelText(); + if (text.equals(s)) { + // le modeèle n'a pas changé, rien a faire sur le modèle + if (log.isDebugEnabled()) { + log.debug("modelText is the same, skip !"); + } + return; + } + + if (StringUtils.isNotEmpty(s) && numberPattern != null) { + + // use given number pattern + Matcher matcher = numberPattern.matcher(s); + if (!matcher.matches()) { + + // the current text is not accepted... + if (log.isInfoEnabled()) { + log.info("Does not accept the new number " + s + + ", will reapply lastValidText : " + lastValidText); + } + + String oldText; + if (lastValidText != null) { + + // push back last valid text + oldText = lastValidText; + } else { + oldText = ""; + } + editor.getTextField().setText(oldText); + return; + } + } + + boolean canApply = false; + + boolean endWithDot = false; + + boolean isLess = false; + + Number newValue = null; + + // allow using ',' char + s = s.replaceAll(",", "."); + + if (s.trim().isEmpty()) { + // le champ est vide donc c'est la valeur null a reaffecter + s = null; + canApply = true; + } else if (s.endsWith(".")) { + s += "0"; + endWithDot = true; + } else if (editor.isUseSign() && s.length() == 1 && s.startsWith("-")) { + s = "0"; + isLess = true; + } + + if (s != null && NumberUtils.isNumber(s)) { + + // on a un nombre valide + + try { + Float f = Float.parseFloat(s); + if (!editor.isUseSign() && s.startsWith("-")) { + if (log.isDebugEnabled()) { + log.debug("will skip since can not allow sign on this editor but was " + f); + } + } else { + + if (!editor.isUseFloat() && s.contains(".")) { + if (log.isDebugEnabled()) { + log.debug("will skip since can not allow float on this editor but was " + f); + } + } else { + // ok on peut utilise ce modele + newValue = getRealValue(f); +// if (editor.isUseFloat()) { +// if (getMutator().getParameterTypes()[0] == BigDecimal.class) { +// newValue = BigDecimal.valueOf(f); +// } else { +// newValue = f; +// } +// } else { +// newValue = f.intValue(); +// } + canApply = true; + } + } + + } catch (NumberFormatException e) { + // rien a faire + log.debug(e); + } + } + JTextField field = editor.getTextField(); + + int oldPosition = field.getCaretPosition(); + + if (canApply) { + + if (log.isDebugEnabled()) { + log.debug("can apply new model value : " + newValue); + } + if (isLess) { + editor.setModelText("-"); + return; + } + // on peut mettre a jour le model + editor.setModel(newValue); + if (endWithDot) { + editor.setModelText(s.substring(0, s.length() - 1)); + field.setCaretPosition(oldPosition); + } + + lastValidText = editor.getModelText(); + return; + } + + // on ne peut pas appliquer, on repositionne l'ancien texte + // dans l'éditeur + + if (log.isDebugEnabled()) { + log.debug("invalid text " + s + " reput old text " + text); + } + + if (oldPosition > 0) { + oldPosition--; + } + field.setText(text); + + lastValidText = text; + try { + field.setCaretPosition(oldPosition); + } catch (IllegalArgumentException ex) { + log.debug("CaretPosition is invalid for position : " + oldPosition, ex); + } + } + + private Number getRealValue(Float f) { + if (modelType == Integer.class) { + return f.intValue(); + } + if (modelType == Float.class) { + return f; + } + if (modelType == Double.class) { + return f; + } + if (modelType == Long.class) { + return f.longValue(); + } + if (modelType == BigInteger.class) { + return new BigInteger(f.longValue() + ""); + } + if (modelType == BigDecimal.class) { + return new BigDecimal(f + ""); + } + if (editor.isUseFloat()) { + // use default float value + return f; + } + return f.intValue(); + } + + /** + * Ajoute le caractère donné à l'endroit où est le curseur dans la zone de + * saisie et met à jour le modèle. + * + * @param s le caractère à ajouter. + */ + public void addChar(String s) { + char c = s.charAt(0); + try { + editor.getTextField().getDocument().insertString(editor.getTextField().getCaretPosition(), c + "", null); + setModel(editor.getTextField().getText()); + //setModel(editor.getModelText() + c); + + } catch (BadLocationException e) { + log.warn(e); + } + } + + /** + * Supprime le caractère juste avant le curseur du modèle (textuel) et + * met à jour la zone de saisie. + */ + public void removeChar() { + String s = editor.getModelText(); + int position = editor.getTextField().getCaretPosition(); + if (position < 1 || s.isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("cannot remove when caret on first position or text empty"); + } + // on est au debut du doc, donc rien a faire + return; + } + try { + editor.getTextField().getDocument().remove(position - 1, 1); + } catch (BadLocationException ex) { + // ne devrait jamais arrive vu qu'on a fait le controle... + log.debug(ex); + return; + } + String newText = editor.getTextField().getText(); + if (log.isDebugEnabled()) { + log.debug("text updated : " + newText); + } + position--; + editor.getTextField().setCaretPosition(position); + setModel(newText); + } + + /** + * Permute le signe dans la zone de saisie et + * dans le modèle. + */ + public void toggleSign() { + String newValue = editor.getModelText(); + + if (newValue.startsWith("-")) { + setModel(newValue.substring(1)); + } else { + setModel("-" + newValue); + } + } + + /** @return l'éditeur au quel est rattaché le handler. */ + public NumberEditor getEditor() { + return editor; + } + + protected void setModel(Number oldValue, Number newValue) { + if (editor.getBean() == null) { + return; + } + + if (log.isDebugEnabled()) { + log.debug(editor.getProperty() + " on " + editor.getBean().getClass() + " :: " + oldValue + " to " + newValue); + } + + try { + Method mutator = getMutator(); + if (newValue == null && !getAcceptNull()) { + // valeur nulle sur une propriete primitive + // on ne peut pas utiliser la valeur null, mais 0 à la place + newValue = getRealValue(0.0f); +// if (editor.isUseFloat()) { +// if (log.isInfoEnabled()) { +// log.info("use float, check mutator default type = " + mutator.getParameterTypes()[0]); +// } +// if (mutator.getParameterTypes()[0] == BigDecimal.class) { +// newValue = BigDecimal.valueOf(0); +// } else { +// newValue = 0.0f; +//// mutator.invoke(editor.getBean(), 0.0f); +// } +// } else { +// newValue = 0; +//// mutator.invoke(editor.getBean(), 0); +// } + + } //else { +// mutator.invoke(editor.getBean(), newValue); +// } + mutator.invoke(editor.getBean(), newValue); + String strValue; + if (newValue == null) { + strValue = ""; + } else { + strValue = newValue + ""; + if (editor.isUseFloat()) { + Float n = Float.parseFloat(strValue); + if ((float) n.intValue() == n) { + strValue = n.intValue() + ""; + } + } + } + + lastValidText = strValue; + editor.setModelText(strValue); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected void validate() { + + setPopupVisible(false); + // fire validate property (to be able to notify listeners) + editor.firePropertyChange(VALIDATE_PROPERTY, null, true); + } + + protected class PopupListener extends MouseAdapter { + + @Override + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + + protected void maybeShowPopup(MouseEvent e) { + if (!e.isPopupTrigger()) { + return; + } + if (editor.isAutoPopup()) { + if (editor.isPopupVisible()) { + if (!editor.getPopup().isVisible()) { + setPopupVisible(true); + } + // popup already visible + + } else { + // set popup auto + editor.setPopupVisible(true); + + } + } else { + if (editor.isPopupVisible()) { + setPopupVisible(true); + } + } + } + } + + protected Method getMutator() { + if (mutator == null) { + Object bean = editor.getBean(); + if (bean == null) { + throw new NullPointerException("could not find bean in " + editor); + } + String property = editor.getProperty(); + if (property == null) { + throw new NullPointerException("could not find property in " + editor); + } + if (log.isDebugEnabled()) { + log.debug("searching mutator for property " + property + " on bean of type " + bean.getClass()); + } + if (log.isTraceEnabled()) { + PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(bean); + for (PropertyDescriptor p : descriptors) { + log.trace("property discover " + p.getName() + " writer = " + p.getWriteMethod()); + } + } + try { + PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, property); + mutator = descriptor.getWriteMethod(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return mutator; + } + + protected Method getGetter() { + if (getter == null) { + Object bean = editor.getBean(); + if (bean == null) { + throw new NullPointerException("could not find bean in " + editor); + } + String property = editor.getProperty(); + if (property == null) { + throw new NullPointerException("could not find property in " + editor); + } + if (log.isDebugEnabled()) { + log.debug("searching accessor for property " + property + " on bean of type " + bean.getClass()); + } + if (log.isTraceEnabled()) { + PropertyDescriptor[] descriptors = PropertyUtils.getPropertyDescriptors(bean); + for (PropertyDescriptor p : descriptors) { + log.trace("property discover " + p.getName() + " reader = " + p.getWriteMethod()); + } + } + try { + PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, property); + getter = descriptor.getReadMethod(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return getter; + } + + public Boolean getAcceptNull() { + if (acceptNull == null) { + Method m = getMutator(); + if (m == null) { + // should never happens + throw new IllegalStateException("could not find the mutator"); + } + Class<?> returnType = m.getParameterTypes()[0]; + acceptNull = !returnType.isPrimitive(); + if (log.isDebugEnabled()) { + log.debug(acceptNull + " for mutator " + m.getName() + " type : " + returnType); + } + } + return acceptNull; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorPopup.css b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorPopup.css new file mode 100644 index 0000000..54901fe --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/NumberEditorPopup.css @@ -0,0 +1,50 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +JButton { + font-size: 14; + focusPainted: false; + focusable: false; +} + +JButton.digit { + foreground: blue; +} + +JButton.operator { + foreground: #009900; +} + +JButton.clear { + foreground: red; +} + +JButton:mouseover { + font-weight: bold; +} + +JButton.operator:mouseover { + font-weight: normal; +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.css b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.css new file mode 100644 index 0000000..d8df5c6 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.css @@ -0,0 +1,61 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +#title { + text:{getLabel()}; + horizontalAlignment:center; +} + +#hour { + value:{getTimeModel() / 60}; + enabled:{isEnabled()}; + model:{new SpinnerNumberModel(0, 0, 23, 1)}; +} + +#labelH { + text:"timeeditor.H"; + horizontalAlignment:center; +} + +#minuteModel { + calendarField:{java.util.Calendar.MINUTE}; + value:{getHandler().setMinuteModel(getDate())}; +} + +#minute { + enabled:{isEnabled()}; + model:{minuteModel}; +} + +#slider { + font-size: 11; + paintTicks:true; + paintLabels:true; + majorTickSpacing:60; + minorTickSpacing:30; + value:{getTimeModel()}; + enabled:{isEnabled()}; + model:{new DefaultBoundedRangeModel(0, 1, 0, 60 * 24)}; +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.jaxx new file mode 100644 index 0000000..bb82438 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditor.jaxx @@ -0,0 +1,90 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + + +<JPanel layout='{new BorderLayout()}'> + + <import> + java.util.Date + java.awt.BorderLayout + javax.swing.SpinnerNumberModel + javax.swing.DefaultBoundedRangeModel + </import> + + <!-- bean property --> + <String id='property' javaBean='""'/> + + <!-- title --> + <String id='label' javaBean='""'/> + + <!-- bean --> + <Object id='bean' javaBean='null'/> + + <!-- time model --> + <Integer id="timeModel" javaBean='0'/> + + <!-- the real date --> + <java.util.Date id="date" javaBean='null'/> + + <!-- spinner minute editor --> + <SpinnerDateModel id="minuteModel"/> + + <!-- ui handler --> + <TimeEditorHandler id='handler' constructorParams='this'/> + + <script><![CDATA[ +public void init() { + minute.setEditor(new JSpinner.DateEditor(minute, "mm")); + handler.init(); +} +]]> + </script> + + <Table constraints='BorderLayout.NORTH' fill='horizontal' insets='0'> + <row> + <cell> + <JLabel id='title'/> + </cell> + <cell weightx='1'> + <JLabel/> + </cell> + <cell> + <JSpinner id='hour' + onStateChanged='setTimeModel((Integer)hour.getValue() * 60 + getHandler().getMinute())'/> + </cell> + <cell> + <JLabel id='labelH'/> + </cell> + <cell> + <JSpinner id='minute' + onStateChanged='getHandler().updateTimeModelFromMinuteModel(minuteModel.getDate())'/> + </cell> + </row> + </Table> + + <JSlider id='slider' constraints='BorderLayout.SOUTH' + onStateChanged='if (!slider.getValueIsAdjusting()) setTimeModel(slider.getValue());'/> + +</JPanel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditorHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditorHandler.java new file mode 100644 index 0000000..41c762c --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/TimeEditorHandler.java @@ -0,0 +1,347 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.plaf.basic.BasicSliderUI; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.util.Calendar; +import java.util.Date; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Map; + +/** @author tchemit <chemit@codelutin.com> */ +public class TimeEditorHandler { + + public static final Log log = LogFactory.getLog(TimeEditorHandler.class); + + public static final String BEAN_PROPERTY = "bean"; + + public static final String PROPERTY_PROPERTY = "property"; + + public static final String DATE_PROPERTY = "date"; + + public static final String TIME_MODEL_PROPERTY = "timeModel"; + + /** editor ui */ + protected TimeEditor editor; + + /** the mutator method on the property of boxed bean in the editor */ + protected Method mutator; + + protected Calendar calendar; + + protected Calendar calendarMinute; + + public TimeEditorHandler(TimeEditor ui) { + editor = ui; + calendar = Calendar.getInstance(); + calendarMinute = Calendar.getInstance(); + } + + public void init() { + + if (editor.getBean() == null) { + throw new NullPointerException("can not have a null bean in ui " + editor); + } + + // create slider labels + Map<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>(); + for (int i = 0; i < 25; i += 2) { + labelTable.put(i * 60, new JLabel(i + "")); + } + JSlider slider = editor.getSlider(); + slider.setLabelTable((Dictionary<?, ?>) labelTable); + + MouseAdapter m = new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + // set the value + int value = getSliderValue(e); + JSlider slider = (JSlider) e.getComponent(); + slider.setValueIsAdjusting(true); + slider.setValue(value); + slider.setValueIsAdjusting(false); + showToolTip(e); + e.consume(); + } + + @Override + public void mouseDragged(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseMoved(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + showToolTip(e); + } + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + JSlider slider = (JSlider) e.getComponent(); + + // compute new value + int nb = e.getWheelRotation(); + int value = slider.getValue() - nb; + + // set the value + slider.setValueIsAdjusting(true); + slider.setValue(value); + slider.setValueIsAdjusting(false); + e.consume(); + } + + int getSliderValue(MouseEvent e) { + JSlider slider = (JSlider) e.getSource(); + int value = -1; + if (slider.getUI() instanceof BasicSliderUI) { + BasicSliderUI ui = (BasicSliderUI) slider.getUI(); + value = slider.getOrientation() == JSlider.HORIZONTAL + ? ui.valueForXPosition(e.getX()) + : ui.valueForYPosition(e.getY()); + } + return value; + } + + void showToolTip(MouseEvent e) { + + int value = getSliderValue(e); + if (value == -1) { + return; + } + int h = value / 60; + int m = value % 60; + + String text = ""; + if (h < 10) { + text = "0"; + } + text += h + " : "; + if (m < 10) { + text += "0"; + } + text += m; + + JSlider slider = (JSlider) e.getSource(); + slider.setToolTipText(text); + + } + }; + slider.addMouseListener(m); + slider.addMouseMotionListener(m); + slider.addMouseWheelListener(m); + + // listen when date changes (should come from outside) + editor.addPropertyChangeListener(DATE_PROPERTY, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Date date = (Date) evt.getNewValue(); + + if (date == null) { + return; + } + calendar.setTime(date); + int hours = calendar.get(Calendar.HOUR_OF_DAY); + int minutes = calendar.get(Calendar.MINUTE); + if (log.isDebugEnabled()) { + log.debug("date changed : new value " + hours + ":" + minutes); + } + getEditor().setTimeModel(hours * 60 + minutes); + } + }); + + // listen when time model changes (should come from editor) + editor.addPropertyChangeListener(TIME_MODEL_PROPERTY, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + Integer time = (Integer) evt.getNewValue(); + int hours = time / 60; + int minutes = time % 60; + calendar.set(Calendar.HOUR_OF_DAY, hours); + calendar.set(Calendar.MINUTE, minutes); + setDate(null, calendar.getTime()); + } + }); + } + + public TimeEditor getEditor() { + return editor; + } + + protected Date setMinuteModel(Date incomingDate) { + if (incomingDate == null) { + incomingDate = new Date(); + } + calendarMinute.setTime(incomingDate); + calendarMinute.set(Calendar.HOUR_OF_DAY, 0); + incomingDate = calendarMinute.getTime(); + return incomingDate; + } + + public int getMinute() { + return getEditor().getTimeModel() % 60; + } + + public int getHour() { + return getEditor().getTimeModel() / 60; + } + + public void updateTimeModelFromMinuteModel(Date minuteDate) { + + calendarMinute.setTime(minuteDate); + int newHour = calendarMinute.get(Calendar.HOUR_OF_DAY); + int newMinute = calendarMinute.get(Calendar.MINUTE); + + int oldHour = getHour(); + int oldMinute = getMinute(); + + if (oldHour == newHour && oldMinute == newMinute) { + + // do nothing, same data + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on same time = " + oldHour + ":" + oldMinute); + } + return; + } + + // by default stay on same hour + int hour = oldHour; + + // by default, use the new minute data + int minute = newMinute; + + if (log.isDebugEnabled()) { + log.debug("hh:mm (old from dateModel) = " + oldHour + ":" + oldMinute); + log.debug("hh:mm (new from minuteModel) = " + newHour + ":" + newMinute); + } + + if (newMinute == 0) { + + // minute pass to zero (check if a new hour is required) + if (newHour == 1) { + + if (oldHour == 23) { + + // can't pass from 23:59 to 0:00, stay on 23:59 + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); + } + getEditor().getMinuteModel().setValue(getEditor().getMinuteModel().getPreviousValue()); + return; + } + hour = (oldHour + 1) % 24; + } + } else if (newMinute == 59) { + + // minute pass to 59 (check if a new hour is required) + + if (newHour == 23) { + + if (oldHour == 0) { + + // can't pass from 0:00 to 23:59, stay on 0:00 + if (log.isDebugEnabled()) { + log.debug("Do not update time model , stay on hh:mm = " + oldHour + ":" + oldMinute); + } + getEditor().getMinuteModel().setValue(getEditor().getMinuteModel().getNextValue()); + return; + } + + // decrease hour + hour = (oldHour - 1) % 24; + } + } + + // date has changed + if (log.isDebugEnabled()) { + log.debug("Update time model to hh:mm = " + hour + ":" + minute); + } + getEditor().setTimeModel(hour * 60 + minute); + } + + protected void setDate(Date oldValue, Date newValue) { + if (editor.getBean() == null) { + return; + } + + if (log.isDebugEnabled()) { + log.debug(editor.getProperty() + " on " + editor.getBean().getClass() + " :: " + oldValue + " to " + newValue); + } + + try { + getMutator().invoke(editor.getBean(), newValue); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + protected Method getMutator() { + if (mutator == null) { + Object bean = editor.getBean(); + if (bean == null) { + throw new NullPointerException("could not find bean in " + editor); + } + String property = editor.getProperty(); + if (property == null) { + throw new NullPointerException("could not find property in " + editor); + } + + try { + PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, property); + mutator = descriptor.getWriteMethod(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return mutator; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx new file mode 100644 index 0000000..4aa3d65 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBox.jaxx @@ -0,0 +1,153 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<Table fill='both' insets='0' genericType='O' + onFocusGained='combobox.requestFocus()' + onFocusLost='hidePopup()'> + + <import> + org.nuiton.util.decorator.JXPathDecorator + javax.swing.border.TitledBorder + </import> + + <!-- auto complete property --> + <Boolean id='autoComplete' javaBean='false'/> + + <!-- flag to reverse the sort --> + <Boolean id='reverseSort' javaBean='false'/> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <!-- show decorator property --> + <Boolean id='showDecorator' javaBean='true'/> + + <!-- editable combo property --> + <Boolean id='editable' javaBean='true'/> + + <!-- bean property linked state --> + <String id='property' javaBean='""'/> + + <!-- bean property --> + <Object id='bean' javaBean='null'/> + + <!-- selectedItem property --> + <Object id='selectedItem' javaBean='null'/> + + <!-- sort index property --> + <Integer id='index' javaBean='0'/> + + <!-- datas of the combo-box --> + <java.util.List id='data' genericType='O' javaBean='null'/> + + <!-- model of sorted property --> + <ButtonGroup id='indexes' useToolTipText='true' + onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> + + <ButtonGroup id='sortGroup' useToolTipText='true' + selectedValue='{isReverseSort()}' + onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> + + <!-- ui handler --> + <BeanComboBoxHandler id='handler' genericType='O' constructorParams='this'/> + + <String id='selectedToolTipText' javaBean='null'/> + + <String id='notSelectedToolTipText' javaBean='null'/> + + <String id='popupTitleText' javaBean='null'/> + + <String id='i18nPrefix' javaBean='"entitycombobox.common."'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + border='{new TitledBorder(_("beancombobox.popup.title"))}' + onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' + onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> + <JLabel id='popupSortLabel' actionIcon="bean-sort" text="bean.sort.label"/> + + <JRadioButtonMenuItem id='sortUp' buttonGroup="sortGroup" value='{false}' + actionIcon="bean-sort-up" text='bean.sort.up' + selected='{!isReverseSort()}'/> + + <JRadioButtonMenuItem id='sortDown' buttonGroup="sortGroup" value='{true}' + actionIcon="bean-sort-down" text='bean.sort.down' + selected='{isReverseSort()}'/> + + <JSeparator/> + <JLabel id='popupLabel'/> + <JSeparator/> + </JPopupMenu> + + <script><![CDATA[ +public void init(JXPathDecorator<O> decorator, List<O> data) { + handler.init(decorator, data); +} + +protected void hidePopup() { + if (popup.isVisible()) { + popup.setVisible(false); + } +} +]]> + </script> + <row> + <cell anchor='west'> + <!-- le boutton pour reinitialiser la valeur sélectionnée --> + <JToolBar floatable='false' borderPainted='false' + visible='{isShowReset()}'> + <JButton actionIcon='combobox-reset' + toolTipText='beancombobox.action.reset.tip' + focusable='false' + focusPainted='false' + enabled='{isEditable() && isEnabled()}' + onActionPerformed='setSelectedItem(null)'/> + </JToolBar> + + </cell> + <cell weightx='1'> + <!-- la liste déroulante --> + <JComboBox id='combobox' + selectedItem='{getSelectedItem()}' + enabled='{isEnabled()}' + editable='{isEditable()}' + focusable='{isEnabled() && isEditable()}' + onFocusGained='hidePopup()' + onItemStateChanged='setSelectedItem(combobox.getSelectedItem())'/> + </cell> + <cell anchor='east' fill='both' insets='0'> + <!-- le boutton pour changer le tri --> + <JToolBar floatable='false' borderPainted='false' + visible='{isShowDecorator()}'> + <JToggleButton id='changeDecorator' + actionIcon='combobox-sort' + toolTipText='beancombobox.action.sort.tip' + focusable='false' + focusPainted='false' + onActionPerformed='getHandler().togglePopup()'/> + </JToolBar> + </cell> + </row> +</Table> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java new file mode 100644 index 0000000..6ec3cc6 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanComboBoxHandler.java @@ -0,0 +1,389 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.bean; + +import jaxx.runtime.SwingUtil; +import org.nuiton.util.decorator.DecoratorUtil; +import org.nuiton.util.decorator.JXPathDecorator; +import org.nuiton.util.decorator.MultiJXPathDecorator; +import jaxx.runtime.swing.JAXXButtonGroup; +import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; + +import javax.swing.JComponent; +import javax.swing.JPopupMenu; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.util.List; + +/** + * Le handler d'un {@link BeanComboBox}. + * <p/> + * Note: ce handler n'est pas stateless et n'est donc pas partageable entre plusieurs ui. + * + * @author tchemit <chemit@codelutin.com> + * @param <O> le type des objet contenus dans le modèle du composant. + * @see BeanComboBox + */ +public class BeanComboBoxHandler<O> implements PropertyChangeListener { + + public static final Log log = LogFactory.getLog(BeanComboBoxHandler.class); + + /** ui if the handler */ + protected BeanComboBox<O> ui; + + /** the mutator method on the property of boxed bean in the ui */ + protected Method mutator; + + /** the original document of the combbo box editor (keep it to make possible undecorate) */ + protected Document originalDocument; + + /** the convertor used to auto-complete */ + protected ObjectToStringConverter convertor; + + /** the decorator of data */ + protected MultiJXPathDecorator<O> decorator; + + protected boolean init; + + public BeanComboBoxHandler(BeanComboBox<O> ui) { + this.ui = ui; + } + + protected final FocusListener EDITOR_TEXT_COMP0NENT_FOCUSLISTENER = new FocusListener() { + + @Override + public void focusGained(FocusEvent e) { + if (log.isDebugEnabled()) { + log.debug("close popup from " + e); + } + ui.getPopup().setVisible(false); + } + + @Override + public void focusLost(FocusEvent e) { + } + }; + + private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { + + @Override + public JPopupMenu getPopup() { + return ui.getPopup(); + } + + @Override + public JComponent getInvoker() { + return ui.getChangeDecorator(); + } + }; + + /** + * Initialise le handler de l'ui + * + * @param decorator le decorateur a utiliser + * @param data la liste des données a gérer + */ + public void init(JXPathDecorator<O> decorator, List<O> data) { + + if (init) { + throw new IllegalStateException("can not init the handler twice"); + } + init = true; + + JAXXButtonGroup indexes = ui.getIndexes(); + + this.decorator = BeanUIUtil.createDecorator(decorator); + + // init combobox renderer base on given decorator + ui.getCombobox().setRenderer(new DecoratorListCellRenderer(this.decorator)); + + convertor = BeanUIUtil.newDecoratedObjectToStringConverter(this.decorator); + + // keep a trace of original document (to make possible reverse autom-complete) + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + originalDocument = editorComponent.getDocument(); + + // build popup + popupHandler.preparePopup(ui.getSelectedToolTipText(), + ui.getNotSelectedToolTipText(), + ui.getI18nPrefix(), + ui.getPopupTitleText(), + indexes, + ui.getPopupLabel(), + ui.getSortUp(), + ui.getSortDown(), + this.decorator); + + ui.autoComplete = true; + + ui.addPropertyChangeListener(this); + + // set datas + ui.setData(data); + + // select sort button + indexes.setSelectedButton(ui.getIndex()); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + popupHandler.togglePopup(); + } + + /** + * Modifie l'état autoComplete de l'ui. + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setAutoComplete(Boolean oldValue, Boolean newValue) { + oldValue = oldValue != null && oldValue; + newValue = newValue != null && newValue; + if (oldValue.equals(newValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("autocomplete state : <" + oldValue + " to " + newValue + ">"); + } + if (!newValue) { + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.removeFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); + BeanUIUtil.undecorate(ui.getCombobox(), originalDocument); + } else { + BeanUIUtil.decorate(ui.getCombobox(), convertor); + JTextComponent editorComponent = (JTextComponent) ui.getCombobox().getEditor().getEditorComponent(); + editorComponent.addFocusListener(EDITOR_TEXT_COMP0NENT_FOCUSLISTENER); + } + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setIndex(Integer oldValue, Integer newValue) { + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + updateUI(newValue, ui.isReverseSort()); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + + protected void setSortOrder(Boolean oldValue, Boolean newValue) { + + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + + updateUI(ui.getIndex(), newValue); + } + + @SuppressWarnings({"unchecked"}) + protected void updateUI(int index, boolean reversesort) { + + // change decorator context + decorator.setContextIndex(index); + + // keep selected item + Object previousSelectedItem = ui.getSelectedItem(); + Boolean wasAutoComplete = ui.isAutoComplete(); + + if (wasAutoComplete) { + ui.setAutoComplete(false); + } + + // remove autocomplete + if (previousSelectedItem != null) { + ui.getCombobox().setSelectedItem(null); + ui.selectedItem = null; + } + + List<O> data = ui.getData(); + try { + // Sort data with the decorator jxpath tokens. + DecoratorUtil.sort(decorator, + data, + index, + reversesort + ); + + } catch (Exception eee) { + log.warn(eee.getMessage(), eee); + } + + // reload the model + SwingUtil.fillComboBox(ui.getCombobox(), data, null); + + if (wasAutoComplete) { + ui.setAutoComplete(true); + } + + if (previousSelectedItem != null) { + ui.setSelectedItem(previousSelectedItem); + } + + ui.getCombobox().requestFocus(); + } + + /** + * Modifie la valeur sélectionnée dans la liste déroulante. + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setSelectedItem(O oldValue, O newValue) { + if (ui.getBean() == null) { + return; + } + + if (newValue == null) { + if (ui.getCombobox().getSelectedItem() == null) { + return; + } + ui.getCombobox().setSelectedItem(null); + + if (ui.isAutoComplete()) { + ui.setAutoComplete(false); + ui.setAutoComplete(true); + } + + if (oldValue == null) { + return; + } + } + if (log.isDebugEnabled()) { + log.debug(ui.getProperty() + " on " + ui.getBean().getClass() + " :: " + oldValue + " to " + newValue); + } + + try { + Method mut = getMutator(); + if (mut != null) { + mut.invoke(ui.getBean(), newValue); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** @return le document de l'éditeur avant complétion. */ + public Document getOriginalDocument() { + return originalDocument; + } + + public MultiJXPathDecorator<O> getDecorator() { + return decorator; + } + + public Class<?> getTargetClass() { + Method m = getMutator(); + return m == null ? null : m.getParameterTypes()[0]; + } + + /** @return le mutateur a utiliser pour modifier le bean associé. */ + protected Method getMutator() { + if (mutator == null) { + Object bean = ui.getBean(); + if (bean == null) { + throw new NullPointerException("could not find bean in " + ui); + } + String property = ui.getProperty(); + if (property == null) { + throw new NullPointerException("could not find property in " + ui); + } + + try { + PropertyDescriptor descriptor = PropertyUtils.getPropertyDescriptor(bean, property); + if (descriptor != null) { + mutator = descriptor.getWriteMethod(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return mutator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + + if (BeanComboBox.PROPERTY_SELECTED_ITEM.equals(propertyName)) { + setSelectedItem((O)evt.getOldValue(), (O)evt.getNewValue()); + return; + } + + if (BeanComboBox.PROPERTY_AUTO_COMPLETE.equals(propertyName)) { + + setAutoComplete((Boolean) evt.getOldValue(), (Boolean) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { + + // decorator index has changed, force reload of data in ui + setIndex((Integer) evt.getOldValue(), + (Integer) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_REVERSE_SORT.equals(propertyName)) { + + // sort order has changed, force reload of data in ui + setSortOrder((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_DATA.equals(propertyName)) { + + // list has changed, force reload of index + setIndex(-1, ui.getIndex()); + } + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx new file mode 100644 index 0000000..ba4f156 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeader.jaxx @@ -0,0 +1,139 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<JPanel id='top' layout='{new BorderLayout()}' genericType='O'> + + <import> + org.nuiton.util.decorator.JXPathDecorator + javax.swing.border.TitledBorder + </import> + + <!-- show reset property --> + <Boolean id='showReset' javaBean='false'/> + + <!-- show decorator property --> + <Boolean id='showDecorator' javaBean='true'/> + + <!-- flag to reverse the sort --> + <Boolean id='reverseSort' javaBean='false'/> + + <!-- editable combo property --> + <Boolean id='editable' javaBean='true'/> + + <!-- bean property --> + <Class genericType='O' id='beanType' javaBean='null'/> + + <!-- label --> + <String id='labelText' javaBean='null'/> + + <!-- sort index property --> + <Integer id='index' javaBean='0'/> + + <!-- datas of the combo-box --> + <java.util.List id='data' genericType='O' javaBean='null'/> + + <!-- model of sorted property --> + <ButtonGroup id='indexes' useToolTipText='true' + onStateChanged='setIndex((Integer)indexes.getSelectedValue())'/> + + <ButtonGroup id='sortGroup' useToolTipText='true' + selectedValue='{isReverseSort()}' + onStateChanged='setReverseSort((Boolean)sortGroup.getSelectedValue())'/> + + <!-- ui handler --> + <BeanListHeaderHandler id='handler' genericType='O' constructorParams='this'/> + + <String id='selectedToolTipText' javaBean='null'/> + + <String id='notSelectedToolTipText' javaBean='null'/> + + <String id='popupTitleText' javaBean='null'/> + + <String id='i18nPrefix' javaBean='"beanlist.common."'/> + + <!-- popup to change sorted property--> + <JPopupMenu id='popup' + border='{new TitledBorder(_("beanlist.popup.title"))}' + onPopupMenuWillBecomeInvisible='getChangeDecorator().setSelected(false)' + onPopupMenuCanceled='getChangeDecorator().setSelected(false)'> + + <JLabel id='popupSortLabel' actionIcon="bean-sort" text="bean.sort.label"/> + + <JRadioButtonMenuItem id='sortUp' buttonGroup="sortGroup" value='{false}' + actionIcon="bean-sort-up" text='bean.sort.up' + selected='{!isReverseSort()}'/> + + <JRadioButtonMenuItem id='sortDown' buttonGroup="sortGroup" value='{true}' + actionIcon="bean-sort-down" text='bean.sort.down' + selected='{isReverseSort()}'/> + + <JSeparator/> + + <JLabel id='popupLabel'/> + + </JPopupMenu> + + <JList id='list' javaBean="new JList()"/> + + <script><![CDATA[ + +public void init(JXPathDecorator<O> decorator, List<O> data) { + handler.init(decorator, data); +} + +public O getSelectedValue() { + return handler.getSelectedValue(); +} + +]]> + </script> + + <JLabel id="label" constraints='BorderLayout.CENTER' opaque='false' + text='{SwingUtil.getStringValue(getLabelText())}'/> + + <JToolBar floatable='false' borderPainted='false' + constraints='BorderLayout.EAST'> + + <!-- le boutton pour reinitialiser la valeur sélectionnée --> + <JButton id='resetSelection' + actionIcon='combobox-reset' + toolTipText='beanlist.action.reset.tip' + focusable='false' + focusPainted='false' + visible='{isShowReset()}' + enabled='{isEnabled() && getList().getSelectedValue() != null}' + onActionPerformed='getList().getSelectionModel().clearSelection()'/> + + <!-- le boutton pour changer le tri --> + <JToggleButton id='changeDecorator' + actionIcon='combobox-sort' + toolTipText='beanlist.action.sort.tip' + focusable='false' + focusPainted='false' + visible='{isShowDecorator()}' + onActionPerformed='getHandler().togglePopup()'/> + </JToolBar> +</JPanel> + diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java new file mode 100644 index 0000000..419da2e --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanListHeaderHandler.java @@ -0,0 +1,274 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.bean; + +import org.nuiton.util.decorator.DecoratorUtil; +import org.nuiton.util.decorator.JXPathDecorator; +import org.nuiton.util.decorator.MultiJXPathDecorator; +import jaxx.runtime.swing.JAXXButtonGroup; +import jaxx.runtime.swing.renderer.DecoratorListCellRenderer; +import org.apache.commons.collections.primitives.ArrayIntList; +import org.apache.commons.collections.primitives.IntList; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; + +/** + * Le handler d'un {@link BeanListHeader}. + * <p/> + * Note: ce handler n'est pas stateless et n'est donc pas partageable entre + * plusieurs ui. + * + * @author tchemit <chemit@codelutin.com> + * @param <O> le type des objet contenus dans le modèle du composant. + * @see BeanListHeader + * @since 2.2 + */ +public class BeanListHeaderHandler<O> implements PropertyChangeListener { + + public static final Log log = LogFactory.getLog(BeanListHeaderHandler.class); + + /** ui if the handler */ + protected BeanListHeader<O> ui; + + /** the decorator of data */ + protected MultiJXPathDecorator<O> decorator; + + /** flag to mark when handler was init (it can be init only once). */ + protected boolean init; + + private final BeanUIUtil.PopupHandler popupHandler = new BeanUIUtil.PopupHandler() { + + @Override + public JPopupMenu getPopup() { + return ui.getPopup(); + } + + @Override + public JComponent getInvoker() { + return ui.getChangeDecorator(); + } + }; + + public BeanListHeaderHandler(BeanListHeader<O> ui) { + this.ui = ui; + } + + /** + * Initialise le handler de l'ui + * + * @param decorator le decorateur a utiliser + * @param data la liste des données a gérer + */ + public void init(JXPathDecorator<O> decorator, List<O> data) { + + if (init) { + throw new IllegalStateException("can not init the handler twice"); + } + init = true; + + // list could have changed and the complex binding is not registred... + ui.removeDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + ui.applyDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + + JAXXButtonGroup indexes = ui.getIndexes(); + + this.decorator = BeanUIUtil.createDecorator(decorator); + + // init combobox renderer base on given decorator + ui.getList().setCellRenderer(new DecoratorListCellRenderer(this.decorator)); + + // build popup + popupHandler.preparePopup(ui.getSelectedToolTipText(), + ui.getNotSelectedToolTipText(), + ui.getI18nPrefix(), + ui.getPopupTitleText(), + indexes, + ui.getPopupLabel(), + ui.getSortUp(), + ui.getSortDown(), + this.decorator); + + ui.addPropertyChangeListener(this); + + // set datas + ui.setData(data); + + // select sort button + indexes.setSelectedButton(ui.getIndex()); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + popupHandler.togglePopup(); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + protected void setIndex(Integer oldValue, Integer newValue) { + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + updateUI(newValue, ui.isReverseSort()); + } + + /** + * Modifie l'index du décorateur + * + * @param oldValue l'ancienne valeur + * @param newValue la nouvelle valeur + */ + + protected void setSortOrder(Boolean oldValue, Boolean newValue) { + + if (newValue == null || newValue.equals(oldValue)) { + return; + } + if (log.isDebugEnabled()) { + log.debug("check state : <" + oldValue + " to " + newValue + ">"); + } + + updateUI(ui.getIndex(), newValue); + } + + @SuppressWarnings({"unchecked"}) + protected void updateUI(int index, boolean reverseSort) { + + // change decorator context + decorator.setContextIndex(index); + + String expression = decorator.getExpression(); + if (log.isDebugEnabled()) { + log.debug("will use expression (index = " + index + ") : " + + expression); + } + + // get the current selection in list + Object[] selection = ui.getList().getSelectedValues(); + + List<O> datas = ui.getData(); + try { + + // Sort data with the decorator jxpath tokens. + DecoratorUtil.sort(decorator, + datas, + index, + reverseSort); + } catch (Exception e) { + log.warn(e.getMessage(), e); + } + + ui.getList().setValueIsAdjusting(true); + try { + + // reload the model + ui.getList().setListData(datas.toArray(new Object[datas.size()])); + + // re-apply selection + if (selection.length > 0) { + + // re compute selection (the new data could not contains some + // previously selected items) + IntList newSelection = new ArrayIntList(); + for (Object o : selection) { + if (datas.contains(o)) { + + newSelection.add(datas.indexOf(o)); + } + } + + if (!newSelection.isEmpty()) { + + // there is still a selection to re-apply + int[] ints = newSelection.toArray(new int[newSelection.size()]); + newSelection.clear(); + ui.getList().setSelectedIndices(ints); + } + } + + } finally { + ui.getList().setValueIsAdjusting(false); + } + + ui.getList().requestFocus(); + } + + public MultiJXPathDecorator<O> getDecorator() { + return decorator; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propertyName = evt.getPropertyName(); + + if (BeanListHeader.PROPERTY_INDEX.equals(propertyName)) { + + // decorator index has changed, force reload of data in ui + setIndex((Integer) evt.getOldValue(), + (Integer) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_REVERSE_SORT.equals(propertyName)) { + + // sort order has changed, force reload of data in ui + setSortOrder((Boolean) evt.getOldValue(), + (Boolean) evt.getNewValue()); + return; + } + + if (BeanListHeader.PROPERTY_DATA.equals(propertyName)) { + + // list has changed, force reload of index + setIndex(-1, ui.getIndex()); + } + + if (BeanListHeader.PROPERTY_LIST.equals(propertyName)) { + + // ui list has changed, replace binding + ui.removeDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + ui.applyDataBinding(BeanListHeader.BINDING_RESET_SELECTION_ENABLED); + } + } + + public O getSelectedValue() { + JList list = ui.getList(); + return list==null?null: (O) list.getSelectedValue(); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java new file mode 100644 index 0000000..fd9464f --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/BeanUIUtil.java @@ -0,0 +1,404 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.bean; + +import org.nuiton.util.decorator.Decorator; +import org.nuiton.util.decorator.DecoratorUtil; +import org.nuiton.util.decorator.JXPathDecorator; +import org.nuiton.util.decorator.MultiJXPathDecorator; +import jaxx.runtime.swing.JAXXButtonGroup; +import org.apache.commons.beanutils.MethodUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jdesktop.swingx.autocomplete.AutoCompleteComboBoxEditor; +import org.jdesktop.swingx.autocomplete.AutoCompleteDecorator; +import org.jdesktop.swingx.autocomplete.AutoCompleteDocument; +import org.jdesktop.swingx.autocomplete.ComboBoxAdaptor; +import org.jdesktop.swingx.autocomplete.ObjectToStringConverter; + +import javax.swing.AbstractButton; +import javax.swing.ActionMap; +import javax.swing.ButtonGroup; +import javax.swing.ComboBoxEditor; +import javax.swing.InputMap; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionListener; +import java.awt.event.FocusListener; +import java.awt.event.KeyListener; +import java.beans.Introspector; +import java.beans.PropertyChangeListener; +import java.util.Date; +import java.util.List; + +import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableList; +import static org.nuiton.i18n.I18n._; +import static org.nuiton.i18n.I18n.n_; + +/** + * Class with usefull methods used in bean uis. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.2 + */ +public class BeanUIUtil { + + public static final String DEFAULT_POPUP_LABEL = n_("bean.popup.label"); + + public static final String DEFAULT_SELECTED_TOOLTIP = n_("bean.sort.on"); + + public static final String DEFAULT_NOT_SELECTED_TOOLTIP = n_("bean.sort.off"); + + public static final Object[] EMPTY_CLASS_ARRAY = new Object[0]; + + /** + * Encapsule un {@link Decorator} dans un {@link ObjectToStringConverter}. + * + * @param decorator le decorateur a encapsuler. + * @return le converter encapsule dans un {@link ObjectToStringConverter} + */ + public static ObjectToStringConverter newDecoratedObjectToStringConverter(final Decorator<?> decorator) { + + return new ObjectToStringConverter() { + + @Override + public String getPreferredStringForItem(Object item) { + return item instanceof String ? (String) item : item == null ? "" : decorator.toString(item); + } + }; + } + + /** + * Ajout l'auto-complétion sur une liste déroulante, en utilisant le + * converteur donné pour afficher les données. + * + * @param combo la combo à décorer + * @param convertor le converter utilisé pour afficher les données. + */ + public static void decorate(JComboBox combo, ObjectToStringConverter convertor) { + + // tchemit 2010-10-05 since swingx 1.6.2, undecorate stuff is no more + // public and we want to use it, so hack it... + combo.putClientProperty("oldEditor", combo.getEditor()); + combo.putClientProperty("oldDocument", combo.getEditor().getEditorComponent()); + + AutoCompleteDecorator.decorate(combo, convertor); + } + + /** + * Désactive l'aut-complétion sur une liste déroulante, en y repositionnant + * le modèle du document d'édition d'avant auto-complétion. + * + * @param comboBox la liste déroulante à décorer + * @param originalDocument le document original de l'édtieur de la + * liste déroulante. + */ + public static void undecorate(JComboBox comboBox, Document originalDocument) { + + // has not to be editable + comboBox.setEditable(false); + + // configure the text component=editor component + Component c = comboBox.getEditor().getEditorComponent(); + JTextComponent editorComponent = (JTextComponent) c; + editorComponent.setDocument(originalDocument); + editorComponent.setText(null); + //undecorate(comboBox); + + //remove old property change listener + //for (PropertyChangeListener l : c.getPropertyChangeListeners("editor")) { + // if (l instanceof AutoCompletePropertyChangeListener) { + // c.removePropertyChangeListener("editor", l); + // } + //} + + ComboBoxEditor oldEditor = (ComboBoxEditor) comboBox.getClientProperty("oldEditor"); + + if (editorComponent.getDocument() instanceof AutoCompleteDocument) { + AutoCompleteDocument doc = (AutoCompleteDocument) editorComponent.getDocument(); + + if (doc.isStrictMatching()) { + ActionMap map = comboBox.getActionMap(); + + for (String key : COMBO_BOX_ACTIONS) { + map.put(key, null); + } + } + + //remove old property change listener + for (PropertyChangeListener l : comboBox.getPropertyChangeListeners("editor")) { + //if (l instanceof AutoComplete.PropertyChangeListener) { + if (l.getClass().getName().contains("AutoComplete")) { + comboBox.removePropertyChangeListener("editor", l); + } + } + + for (PropertyChangeListener l : comboBox.getPropertyChangeListeners("enabled")) { + //if (l instanceof AutoComplete.PropertyChangeListener) { + if (l.getClass().getName().contains("AutoComplete")) { + comboBox.removePropertyChangeListener("enabled", l); + } + } + + AutoCompleteComboBoxEditor editor = (AutoCompleteComboBoxEditor) comboBox.getEditor(); + comboBox.setEditor(oldEditor); + + //remove old key listener + for (KeyListener l : editorComponent.getKeyListeners()) { + //if (l instanceof AutoComplete.KeyAdapter) { + if (l.getClass().getName().contains("AutoComplete")) { + editorComponent.removeKeyListener(l); + break; + } + } + + undecorate(editorComponent, originalDocument); + + for (ActionListener l : comboBox.getActionListeners()) { + if (l instanceof ComboBoxAdaptor) { + comboBox.removeActionListener(l); + break; + } + } + + //TODO remove aqua fix + + //TODO reset editibility + } + } + + static void undecorate(JTextComponent textComponent, Document originalDocument) { + Document doc = textComponent.getDocument(); + + if (doc instanceof AutoCompleteDocument) { + //remove autocomplete key/action mappings + InputMap map = textComponent.getInputMap(); + + while (map.getParent() != null) { + InputMap parent = map.getParent(); + + //if (parent instanceof AutoComplete.InputMap) { + if (parent.getClass().getName().contains("AutoComplete")) { + map.setParent(parent.getParent()); + } + + map = parent; + } + + textComponent.getActionMap().put("nonstrict-backspace", null); + + //remove old focus listener + for (FocusListener l : textComponent.getFocusListeners()) { + //if (l instanceof AutoComplete.FocusAdapter) { + if (l.getClass().getName().contains("AutoComplete")) { + textComponent.removeFocusListener(l); + break; + } + } + + //reset to original document + //textComponent.setDocument(((AutoCompleteDocument) doc).delegate); + textComponent.setDocument(originalDocument); + } + } + + public static <O> MultiJXPathDecorator<O> createDecorator(JXPathDecorator<O> decorator) { + if (decorator == null) { + throw new NullPointerException( + "can not have a null decorator as parameter"); + } + String separator; + String separatorReplacement; + + if (decorator instanceof Cloneable) { + Cloneable cloneable = (Cloneable) decorator; + + try { + Object clone = MethodUtils.invokeExactMethod(cloneable, + "clone", + EMPTY_CLASS_ARRAY + ); + return (MultiJXPathDecorator<O>) clone; + } catch (Exception e) { + throw new IllegalStateException("Could not clone decorator "+decorator, e); } + + } + if (decorator instanceof MultiJXPathDecorator<?>) { + + separator = ((MultiJXPathDecorator<?>) decorator).getSeparator(); + separatorReplacement = ((MultiJXPathDecorator<?>) decorator).getSeparatorReplacement(); + + } else { + + separator = "??" + new Date().getTime(); + separatorReplacement = " - "; + } + + return DecoratorUtil.newMultiJXPathDecorator( + decorator.getType(), + decorator.getInitialExpression(), + separator, + separatorReplacement + ); + } + + public static abstract class PopupHandler implements Runnable { + + public static final Log log = LogFactory.getLog(PopupHandler.class); + + public abstract JPopupMenu getPopup(); + + public abstract JComponent getInvoker(); + + @Override + public void run() { + + updatePopup(); + + Dimension dim = getPopup().getPreferredSize(); + + JComponent invoker = getInvoker(); + getPopup().show( + invoker, + (int) (invoker.getPreferredSize().getWidth() - dim.getWidth()), + invoker.getHeight() + ); + } + + /** Toggle the popup visible state. */ + public void togglePopup() { + boolean newValue = !getPopup().isVisible(); + + if (log.isTraceEnabled()) { + log.trace(newValue); + } + + if (!newValue) { + if (getPopup() != null) { + getPopup().setVisible(false); + } + return; + } + SwingUtilities.invokeLater(this); + } + + protected void updatePopup() { + getPopup().pack(); + } + + /** + * Creation de l'ui pour modifier le décorateur. + * + * @param selectedTip + * @param notSelectedTip + * @param i18nPrefix + * @param title + * @param indexes + * @param popupLabel + * @param sortUp + * @param sortDown + * @param decorator le decorateur a utiliser + */ + protected void preparePopup(String selectedTip, + String notSelectedTip, + String i18nPrefix, + String title, + ButtonGroup indexes, + JLabel popupLabel, + AbstractButton sortUp, + AbstractButton sortDown, + MultiJXPathDecorator<?> decorator) { + if (selectedTip == null) { + // use default selected tip text + selectedTip = DEFAULT_SELECTED_TOOLTIP; + } + if (notSelectedTip == null) { + // use default selected tip text + notSelectedTip = DEFAULT_NOT_SELECTED_TOOLTIP; + } + JPopupMenu popup = getPopup(); + + //Container container = ui.getIndexesContainer(); + for (int i = 0, max = decorator.getNbContext(); i < max; i++) { + String property = i18nPrefix + decorator.getProperty(i); + String propertyI18n = _(property); + JRadioButtonMenuItem button = new JRadioButtonMenuItem(propertyI18n); + button.putClientProperty(JAXXButtonGroup.BUTTON8GROUP_CLIENT_PROPERTY, indexes); + button.putClientProperty(JAXXButtonGroup.VALUE_CLIENT_PROPERTY, i); + popup.add(button); + if (selectedTip != null) { + button.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, _(selectedTip, propertyI18n)); + } + if (notSelectedTip != null) { + button.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, _(notSelectedTip, propertyI18n)); + } + button.setSelected(false); + indexes.add(button); + } + if (title == null) { + // use default popup title + title = DEFAULT_POPUP_LABEL; + + Class<?> type = decorator.getType(); + String beanI18nKey; + if (type == null) { + beanI18nKey = n_("bean.unknown.type"); + } else { + beanI18nKey = i18nPrefix + Introspector.decapitalize(type.getSimpleName()); + } + String beanI18n = _(beanI18nKey); + title = _(title, beanI18n); + } else { + title = _(title); + } + + sortDown.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, _("bean.sort.down.tip")); + sortDown.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, _("bean.sort.down.toSelect.tip")); + + sortUp.putClientProperty(JAXXButtonGroup.SELECTED_TIP_CLIENT_PROPERTY, _("bean.sort.up.tip")); + sortUp.putClientProperty(JAXXButtonGroup.NOT_SELECTED_TIP_CLIENT_PROPERTY, _("bean.sort.up.toSelect.tip")); + + popupLabel.setText(title); + getPopup().setLabel(title); + getPopup().invalidate(); + } + } + + + //these keys were pulled from BasicComboBoxUI from Sun JDK 1.6.0_20 + + private static final List<String> COMBO_BOX_ACTIONS = unmodifiableList(asList("selectNext", + "selectNext2", "selectPrevious", "selectPrevious2", "pageDownPassThrough", + "pageUpPassThrough", "homePassThrough", "endPassThrough")); +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/package.html b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/package.html new file mode 100644 index 0000000..e63d658 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/bean/package.html @@ -0,0 +1,35 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>Package jaxx.runtime.swing.editor.bean</h1> + +Package containing several rich editors based on JavaBeans: +<ul> + <li>BeanComboBox : a rich combo box selector (reset, auto-complete + use of decorators to customize view)</li> + <li>BeanListHeader : a rich list header (reset, use of decorators to customize view)</li> +</ul> +</body> +</html> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/DateCellEditor.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/DateCellEditor.java new file mode 100644 index 0000000..8acfbfd --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/DateCellEditor.java @@ -0,0 +1,55 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.util.Date; +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import jaxx.runtime.swing.JAXXDatePicker; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class DateCellEditor extends AbstractCellEditor + implements TableCellEditor { + + protected JAXXDatePicker datePicker; + + public DateCellEditor() { + datePicker = new JAXXDatePicker(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + datePicker.setDate((Date) value); + return datePicker; + } + + @Override + public Object getCellEditorValue() { + return datePicker.getDate(); + } +} \ No newline at end of file diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/FileCellEditor.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/FileCellEditor.java new file mode 100644 index 0000000..81ab799 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/FileCellEditor.java @@ -0,0 +1,73 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.table.TableCellEditor; +import jaxx.runtime.swing.editor.FileEditor; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class FileCellEditor extends AbstractCellEditor + implements TableCellEditor { + + protected FileEditor fileEditor; + + public FileCellEditor() { + setFileEditor(new FileEditor()); + } + + public FileCellEditor(FileEditor editor) { + setFileEditor(editor); + } + + public void setFileEditor(FileEditor fileEditor) { + this.fileEditor = fileEditor; + fileEditor.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + fireEditingStopped(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + File file = (File) value; + fileEditor.setSelectedFile(file); + return fileEditor; + } + + @Override + public Object getCellEditorValue() { + return fileEditor.getSelectedFile(); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java new file mode 100644 index 0000000..df0643c --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/KeyStrokeCellEditor.java @@ -0,0 +1,64 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.KeyStroke; +import javax.swing.table.TableCellEditor; +import jaxx.runtime.swing.editor.KeyStrokeEditor; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class KeyStrokeCellEditor extends AbstractCellEditor + implements TableCellEditor { + + protected KeyStrokeEditor keyStrokeEditor; + + public KeyStrokeCellEditor() { + keyStrokeEditor = new KeyStrokeEditor(); + keyStrokeEditor.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + fireEditingStopped(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + keyStrokeEditor.setKeyStroke((KeyStroke) value); + return keyStrokeEditor; + } + + @Override + public Object getCellEditorValue() { + return keyStrokeEditor.getKeyStroke(); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/NumberCellEditor.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/NumberCellEditor.java new file mode 100644 index 0000000..6e76308 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/cell/NumberCellEditor.java @@ -0,0 +1,129 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.cell; + +import java.awt.Component; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import javax.swing.AbstractCellEditor; +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.table.TableCellEditor; +import jaxx.runtime.swing.editor.NumberEditor; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class NumberCellEditor<E extends Number> extends AbstractCellEditor + implements TableCellEditor, FocusListener, AncestorListener { + + private static final long serialVersionUID = 1L; + + protected final NumberEditor numberEditor; + + /** constructor */ + public NumberCellEditor(Class<E> type, boolean useSign) { + numberEditor = new NumberEditor(); + numberEditor.getTextField().setHorizontalAlignment(SwingConstants.RIGHT); + numberEditor.getTextField().setBorder(null); + numberEditor.getTextField().addFocusListener(this); + numberEditor.getTextField().addAncestorListener(this); + + numberEditor.setModelType(type); + + numberEditor.setUseSign(useSign); + numberEditor.init(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, + boolean isSelected, int row, int column) { + + E number = (E) value; + numberEditor.setModel(number); + + // Check nullity and set the text that will be selected with the current value + if (number != null) { + numberEditor.setModelText(String.valueOf(number)); + } + return numberEditor; + } + + public NumberEditor getNumberEditor() { + return numberEditor; + } + + @Override + public E getCellEditorValue() { + return (E)numberEditor.getModel(); + } + + @Override + public void focusGained(FocusEvent e) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + numberEditor.getTextField().requestFocus(); + numberEditor.getTextField().selectAll(); + } + }); + } + + @Override + public void focusLost(FocusEvent e) { + } + + @Override + public void ancestorAdded(AncestorEvent event) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + numberEditor.getTextField().requestFocus(); + numberEditor.getTextField().selectAll(); + } + }); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + } + + @Override + public void ancestorMoved(AncestorEvent event) { + } + + @Override + public boolean stopCellEditing() { + boolean result = super.stopCellEditing(); + // Reset previous data to avoid keeping it on other cell edition + if (result) { + numberEditor.setModel(null); + // Use empty string, otherwise there is a NPE in NumberEditorHandler + numberEditor.setModelText(""); + } + return result; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCallBackUI.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCallBackUI.jaxx new file mode 100644 index 0000000..6aa7668 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCallBackUI.jaxx @@ -0,0 +1,66 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new BorderLayout()}'> + + <!--import> + jaxx.runtime.swing.editor.config.model.* + </import--> + + <script><![CDATA[ + /** + * Init the ui. + */ + public void init() { + getHandler().init(this); + } + ]]> + </script> + + <ConfigCallBackUIHandler + id='handler' + initializer='getContextValue(ConfigCallBackUIHandler.class)'/> + + <JScrollPane constraints='BorderLayout.CENTER' + columnHeaderView='{treeHeader}'> + + <JTree id='detectedCallBack' + editable='false' + rootVisible='false' + rowHeight='24'/> + + </JScrollPane> + + <JButton constraints='BorderLayout.SOUTH' + id='go' + text='config.launch.callBack' + toolTipText='config.launch.callBack.tip' + actionIcon='config-quit' + onActionPerformed='getHandler().doAction(this)'/> + + <JPanel id='treeHeader' constraints='BorderLayout.EAST'> + <JLabel text='config.detected.callBack'/> + </JPanel> + +</JPanel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCallBackUIHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCallBackUIHandler.java new file mode 100644 index 0000000..454c562 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCallBackUIHandler.java @@ -0,0 +1,190 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config; + +import jaxx.runtime.SwingUtil; +import jaxx.runtime.swing.editor.config.model.CallBackEntry; +import jaxx.runtime.swing.editor.config.model.CallBackMap; +import jaxx.runtime.swing.editor.config.model.OptionModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import java.awt.*; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n._; + +/** + * callBackUI handler + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class ConfigCallBackUIHandler { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ConfigCallBackUIHandler.class); + + public void init(ConfigCallBackUI ui) { + + // build tree model + DefaultMutableTreeNode root = new DefaultMutableTreeNode(); + + CallBackMap forSaved = ui.getContextValue( + CallBackMap.class, ConfigUIHandler.CALLBACKS_WITH_OPTIONS); + + for (Map.Entry<CallBackEntry, List<OptionModel>> e : + forSaved.entrySet()) { + + CallBackEntry callBackEntry = e.getKey(); + List<OptionModel> options = e.getValue(); + + DefaultMutableTreeNode callBackNode; + callBackNode = new DefaultMutableTreeNode(callBackEntry, true); + + root.add(callBackNode); + for (OptionModel o : options) { + + DefaultMutableTreeNode optionkNode; + optionkNode = new DefaultMutableTreeNode(o, false); + + callBackNode.add(optionkNode); + } + } + + JTree tree = ui.getDetectedCallBack(); + + tree.setModel(new DefaultTreeModel(root)); + + SwingUtil.expandTree(tree); + + tree.setCellRenderer(new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean sel, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + if (log.isDebugEnabled()) { + log.debug("value = " + value.getClass()); + } + if (value == null) { + return super.getTreeCellRendererComponent( + tree, + value, + sel, + expanded, + leaf, + row, + hasFocus); + } + + if (!(value instanceof DefaultMutableTreeNode)) { + return super.getTreeCellRendererComponent( + tree, + value, + sel, + expanded, + leaf, + row, + hasFocus); + } + + DefaultMutableTreeNode n = (DefaultMutableTreeNode) value; + value = n.getUserObject(); + + if (value instanceof CallBackEntry) { + CallBackEntry v = (CallBackEntry) value; + if (log.isDebugEnabled()) { + log.debug("callBackEntry detected " + v.getName()); + } + value = _(v.getDescription()); + } else if (value instanceof OptionModel) { + + OptionModel v = (OptionModel) value; + if (log.isDebugEnabled()) { + log.debug("option detected " + v.getKey()); + } + value = v.getKey() + " (" + _(v.getDescription()) + ")"; + } + + JLabel rendererComponent; + rendererComponent = (JLabel) + super.getTreeCellRendererComponent( + tree, + value, + sel, + expanded, + leaf, + row, + hasFocus); + + value = n.getUserObject(); + + if (value instanceof CallBackEntry) { + + CallBackEntry v = (CallBackEntry) value; + rendererComponent.setIcon(v.getIcon()); + } + return rendererComponent; + } + }); + } + + public void doAction(final ConfigCallBackUI ui) { + log.info("Launch callBacks..."); + Window parent = ui.getContextValue(Window.class, "parent"); + if (parent != null) { + log.info("dispose parent window..."); + parent.dispose(); + } + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + List<CallBackEntry> callBacks; + callBacks = ui.getContextValue( + List.class, + ConfigUIHandler.CALLBACKS); + for (CallBackEntry e : callBacks) { + if (log.isInfoEnabled()) { + log.info("launch callBack " + _(e.getDescription())); + } + e.getAction().run(); + } + } + }); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCategoryUI.css b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCategoryUI.css new file mode 100644 index 0000000..fe1118a --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCategoryUI.css @@ -0,0 +1,68 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + + +#categoryLabelPanel { + background:{Color.WHITE}; +} + +#descriptionPane { + columnHeaderView:{new JLabel(_("config.description"), SwingUtil.getUIManagerActionIcon("information"), 10)}; +} + +#description { + rows:3; + editable:false; + focusable:false; + font-size:10; + text:{_("config.no.option.selected")}; +} + +#tablePane { + columnHeaderView:{table.getTableHeader()}; + verticalScrollBarPolicy:{ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS}; + horizontalScrollBarPolicy:{ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER}; +} + +#table { + rowSelectionAllowed:false; + autoCreateRowSorter:true; + autoResizeMode:{JTable.AUTO_RESIZE_ALL_COLUMNS}; + rowHeight:25; +} + +#reset{ + text:"config.action.reset"; + toolTipText:"config.action.reset.tip"; + actionIcon:"config-reset"; + enabled:{getCategoryModel().isModified()}; +} + +#save{ + text:"config.action.save"; + toolTipText:"config.action.save.tip"; + actionIcon:"config-save"; + enabled:{getCategoryModel().isModified() && getCategoryModel().isValid()}; +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCategoryUI.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCategoryUI.jaxx new file mode 100644 index 0000000..7540171 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigCategoryUI.jaxx @@ -0,0 +1,133 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new BorderLayout()}'> + + <import> + java.awt.Color + java.awt.Font + javax.swing.DefaultListSelectionModel + javax.swing.ScrollPaneConstants + jaxx.runtime.swing.editor.config.model.CategoryModel + jaxx.runtime.swing.editor.config.model.ConfigTableModel + jaxx.runtime.swing.editor.config.model.ConfigUIModel + jaxx.runtime.swing.editor.config.model.OptionModel + static org.nuiton.i18n.I18n.n_ + </import> + + <!--<style source='ConfigCategoryUI.css'/>--> + + <script><![CDATA[ + +void $afterCompleteSetup() { + // prepare table + SwingUtil.setI18nTableHeaderRenderer(table, + n_("config.key"), + n_("config.key.tip"), + n_("config.value"), + n_("config.value.tip"), + n_("config.defaultValue"), + n_("config.defaultValue.tip")); + + ConfigTableRenderer renderer = new ConfigTableRenderer(); + SwingUtil.setTableColumnRenderer(table, 0, renderer); + SwingUtil.setTableColumnRenderer(table, 1, renderer); + SwingUtil.setTableColumnRenderer(table, 2, renderer); + Font f = table.getFont().deriveFont(Font.ITALIC | Font.BOLD); + int width = SwingUtil.computeTableColumnWidth(table, f, 0, "___*"); + SwingUtil.fixTableColumnWidth(table, 0, width); + SwingUtil.setTableColumnEditor(table, 1, new ConfigTableEditor((ConfigTableModel) table.getModel())); +} + +protected void updateDescriptionText() { + OptionModel option; + if (selectionModel.isSelectionEmpty()) { + option = null; + } else { + int row = selectionModel.getAnchorSelectionIndex(); + ConfigTableModel m = (ConfigTableModel) table.getModel(); + option = m.getEntry(row); + if (log.isDebugEnabled()) { + log.debug(row + " : " + option); + } + } + StringBuilder buffer = new StringBuilder(); + if (option == null) { + buffer.append(_("config.no.option.selected")); + } else { + buffer.append(_("config.option.label", option.getKey(), _(option.getDescription()))).append('\n'); + if (option.isModified()) { + buffer.append(_("config.option.modified", option.getOriginalValue(), option.getValue())).append('\n'); + } + if (option.isFinal()) { + buffer.append(_("config.option.final")).append('\n'); + } + } + description.setText(buffer.toString()); +} +]]> + </script> + + <!-- le modele de l'ui --> + <ConfigUIModel id='model' + initializer='getContextValue(ConfigUIModel.class)'/> + + <CategoryModel id='categoryModel' + javaBean='getContextValue(CategoryModel.class)'/> + + <ConfigTableModel id='tableModel' constructorParams='categoryModel' + onTableChanged='updateDescriptionText()'/> + + <ListSelectionModel id='selectionModel' + javaBean='new DefaultListSelectionModel()' + onValueChanged='if (!event.getValueIsAdjusting()) { updateDescriptionText(); }'/> + + <!--<ColumnSelector id='columnSelector' />--> + + <!-- categorie label --> + <JPanel id="categoryLabelPanel" constraints='BorderLayout.NORTH'> + <JLabel id='categoryLabel'/> + </JPanel> + + <!-- table of options --> + <JScrollPane id='tablePane' constraints='BorderLayout.CENTER'> + <JTable id="table" constructorParams='tableModel' + selectionModel='{selectionModel}'/> + </JScrollPane> + + <JPanel layout='{new BorderLayout()}' constraints='BorderLayout.SOUTH'> + + <!-- description of selected option in table --> + <JScrollPane id="descriptionPane" constraints='BorderLayout.CENTER'> + <JTextArea id='description'/> + </JScrollPane> + + <!-- actions of the category --> + <JPanel layout='{new GridLayout(1,0)}' + constraints='BorderLayout.SOUTH'> + <JButton id='reset' onActionPerformed='model.reset()'/> + <JButton id='save' onActionPerformed='model.saveModified()'/> + </JPanel> + </JPanel> +</JPanel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigTableEditor.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigTableEditor.java new file mode 100644 index 0000000..1f5407e --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigTableEditor.java @@ -0,0 +1,161 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.config; + +import com.google.common.io.Files; +import java.awt.Component; +import java.io.File; +import java.util.EventObject; +import java.util.Locale; +import javax.swing.DefaultCellEditor; +import javax.swing.JTable; +import javax.swing.KeyStroke; +import javax.swing.event.CellEditorListener; +import javax.swing.table.TableCellEditor; +import jaxx.runtime.swing.JAXXWidgetUtil; +import jaxx.runtime.swing.editor.ClassCellEditor; +import jaxx.runtime.swing.editor.EnumEditor; +import jaxx.runtime.swing.editor.LocaleEditor; +import jaxx.runtime.swing.editor.cell.FileCellEditor; +import jaxx.runtime.swing.editor.config.model.ConfigTableModel; +import jaxx.runtime.swing.editor.config.model.OptionModel; +import org.apache.commons.lang3.StringUtils; + +/** + * L'éditeur des valeurs des propriétés d'une configuration + * + * @author tchemit <chemit@codelutin.com> + */ +public class ConfigTableEditor implements TableCellEditor { + + protected TableCellEditor delegate; + protected ConfigTableModel model; + + public ConfigTableEditor(ConfigTableModel model) { + this.model = model; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + delegate = findDelegate(table, model.getEntry(row)); + return delegate.getTableCellEditorComponent(table, value, isSelected, row, column); + } + + @Override + public Object getCellEditorValue() { + return !hasDelegate() ? null : delegate.getCellEditorValue(); + } + + @Override + public boolean isCellEditable(EventObject anEvent) { + return !hasDelegate() || delegate.isCellEditable(anEvent); + } + + @Override + public boolean shouldSelectCell(EventObject anEvent) { + return hasDelegate() && delegate.shouldSelectCell(anEvent); + } + + @Override + public boolean stopCellEditing() { + return !hasDelegate() || delegate.stopCellEditing(); + } + + @Override + public void cancelCellEditing() { + if (hasDelegate()) { + delegate.cancelCellEditing(); + } + } + + @Override + public void addCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.addCellEditorListener(l); + } + } + + @Override + public void removeCellEditorListener(CellEditorListener l) { + if (hasDelegate()) { + delegate.removeCellEditorListener(l); + } + } + + protected TableCellEditor findDelegate(JTable table, OptionModel option) { + Class<?> type = option.getType(); + TableCellEditor editor = table.getDefaultEditor(type); + TableCellEditor defaultEditor = table.getDefaultEditor(Object.class); + //TODO always Search from option.getEditor() and store editor as cache + if (editor.equals(defaultEditor)) { + // find not a specialized editor for the type + if (type.isEnum()) { + // add a EnumEditor to table + editor = new DefaultCellEditor(EnumEditor.newEditor((Class<Enum>) type)); + + } else if (type.equals(Class.class)) { + editor = new ClassCellEditor(); + + } else if (type.equals(File.class)){ + editor = new FileCellEditorWithExtDetector(); + + } else if (type.equals(KeyStroke.class)){ + editor = JAXXWidgetUtil.newKeyStrokeTableCellEditor(); + + } else if (type.equals(Locale.class)) { + editor = new DefaultCellEditor(LocaleEditor.newEditor()); + + } else { + editor = table.getDefaultEditor(String.class); + } + table.setDefaultEditor(type, editor); + } + if (editor == null) { + throw new IllegalStateException("could not find a editor for type +" + type); + } + return editor; + } + + protected static class FileCellEditorWithExtDetector extends FileCellEditor { + + private static final long serialVersionUID = 1L; + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + + String fileExtension = Files.getFileExtension(((File)value).getName()); + if (StringUtils.isNotEmpty(fileExtension)) { + fileEditor.setExts(fileExtension); + fileEditor.setAcceptAllFileFilterUsed(true); + } + return super.getTableCellEditorComponent(table, value, isSelected, row, column); + } + } + + protected boolean hasDelegate() { + return delegate != null; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigTableRenderer.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigTableRenderer.java new file mode 100644 index 0000000..950581e --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigTableRenderer.java @@ -0,0 +1,138 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +/* + * *##% + * JAXX Widgets + * Copyright (C) 2008 - 2009 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * ##%* */ +package jaxx.runtime.swing.editor.config; + +import static org.nuiton.i18n.I18n._; + +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import jaxx.runtime.swing.editor.config.model.ConfigTableModel; +import jaxx.runtime.swing.editor.config.model.OptionModel; + +/** + * Pour le rendu du tableau des options d'une categorie + * + * @author tchemit <chemit@codelutin.com> + * @see ConfigTableModel + */ +public class ConfigTableRenderer extends DefaultTableCellRenderer { + + private static final long serialVersionUID = 1L; + protected static Color col; + protected static Font font; + protected static Font font2; + + public ConfigTableRenderer() { + col = getForeground(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + int modelRow = table.convertRowIndexToModel(row); + int modelColumn = table.convertColumnIndexToModel(column); + ConfigTableModel model = (ConfigTableModel) table.getModel(); + OptionModel key = model.getEntry(modelRow); + boolean isModified = key.isModified(); + + boolean isValid = key.isValid(); + + if (font == null) { + font = getFont(); + font2 = font.deriveFont(Font.ITALIC | Font.BOLD); + } + Component cellRenderer = null; + switch (modelColumn) { + case 0: + cellRenderer = getKeyCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); + break; + case 1: + cellRenderer = getValueCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); + break; + case 2: + cellRenderer = getValueCellRenderer(table, value, isSelected, hasFocus, modelRow, modelColumn, key, isValid, isModified); + break; + default: + throw new IllegalStateException("no renderer find for column " + modelColumn); + } + return cellRenderer; + } + + protected Component getKeyCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column, OptionModel key, boolean isValid, boolean isModified) { + String tooltip = _(key.getDescription()); + Object originalValue = key.getOriginalValue(); + boolean isFinal = key.isFinal(); + if (isFinal) { + tooltip += " [" + _("config.unmodifiable") + ']'; + } + if (isModified) { + String s = _("config.modified", originalValue); + value = value + " *"; + tooltip += " [" + s + ']'; + } + if (!isValid) { + String s2 = _("config.unvalid", originalValue, key.getType()); + tooltip += " (" + s2 + ")"; + value = value + " !"; + } + JComponent result = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + result.setToolTipText(tooltip); + result.setForeground(isValid ? col : Color.RED); + result.setFont(isModified || !isValid ? font2 : font); + result.setEnabled(!isFinal); + return result; + } + + protected Component getValueCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column, OptionModel key, boolean isValid, boolean isModified) { + TableCellRenderer defaultRenderer = table.getDefaultRenderer(key.getType()); + + Component result; + result = defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + return result; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUI.css b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUI.css new file mode 100644 index 0000000..a76f7c3 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUI.css @@ -0,0 +1,34 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +#quit{ + text:"config.action.quit"; + toolTipText:"config.action.quit.tip"; + actionIcon:"config-quit"; +} + +#categories{ + tabPlacement:{JTabbedPane.LEFT}; +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUI.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUI.jaxx new file mode 100644 index 0000000..929ec89 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUI.jaxx @@ -0,0 +1,67 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel layout='{new BorderLayout()}'> + + <import> + jaxx.runtime.swing.editor.config.model.ConfigUIModel + </import> + + <!--<style source='ConfigUI.css'/>--> + + <script><![CDATA[ + +public void init(String defaultCategory) { + getHandler().initUI(defaultCategory); +} + +public void destroy() { + log.info("destroy ui " + getName()); + JAXXUtil.destroy(this); + model.destroy(); +} + +@Override +protected void finalize() throws Throwable { + super.finalize(); + destroy(); +} + ]]> + </script> + + <ConfigUIHandler id='handler' constructorParams='this'/> + + <!-- le modele de l'ui --> + <ConfigUIModel id='model' + initializer='getContextValue(ConfigUIModel.class)'/> + + <!-- les differentes categories de la configuration --> + <JTabbedPane id='categories' constraints='BorderLayout.CENTER' + onStateChanged='getHandler().changeCategory(event)'/> + + <!-- pour quitter l'ui --> + <JPanel layout='{new GridLayout(1,0)}' constraints='BorderLayout.SOUTH'> + <JButton id='quit'/> + </JPanel> +</JPanel> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUIHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUIHandler.java new file mode 100644 index 0000000..768506b --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUIHandler.java @@ -0,0 +1,349 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Author$ + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config; + +import jaxx.runtime.SwingUtil; +import jaxx.runtime.context.JAXXInitialContext; +import jaxx.runtime.swing.editor.config.model.CallBackEntry; +import jaxx.runtime.swing.editor.config.model.CallBackMap; +import jaxx.runtime.swing.editor.config.model.CategoryModel; +import jaxx.runtime.swing.editor.config.model.ConfigUIModel; +import jaxx.runtime.swing.editor.config.model.OptionModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.DefaultSingleSelectionModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.JTabbedPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import java.awt.Frame; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; + +import static org.nuiton.i18n.I18n._; + +/** + * Handler of the {@link ConfigUI} ui. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ConfigUIHandler { + + public static final Log log = LogFactory.getLog(ConfigUIHandler.class); + + public static final String CALLBACKS_WITH_OPTIONS = "callbacksWithOptions"; + + public static final String CALLBACKS = "callbacks"; + + private final ConfigUI ui; + + public ConfigUIHandler(ConfigUI ui) { + this.ui = ui; + } + + public void initUI(String defaultCategory) { + + ConfigUIModel model = ui.getModel(); + + JTabbedPane categories = ui.getCategories(); + + categories.setModel(new DefaultSingleSelectionModel() { + + private static final long serialVersionUID = 1L; + + @Override + public void setSelectedIndex(int index) { + // check if catgeory can be quit + boolean canContinue = !isSelected() || canQuitCategory(); + if (canContinue) { + if (log.isDebugEnabled()) { + log.debug("new index : " + index); + } + // was authorized to continue + super.setSelectedIndex(index); + } + } + }); + + JButton quitButton = ui.getQuit(); + + // prepare quit action + Action quitAction = createQuitAction(); + + String tip = quitButton.getToolTipText(); + quitButton.setAction(quitAction); + quitButton.setToolTipText(tip); + + // build categories tabs + for (CategoryModel categoryModel : model) { + String category = categoryModel.getCategory(); + String categoryLabel = _(categoryModel.getCategoryLabel()); + ConfigCategoryUI p = new ConfigCategoryUI(new + JAXXInitialContext().add(ui).add(categoryModel)); + p.getCategoryLabel().setText(categoryLabel); + p.setName(category); + categories.addTab(_(category), null, p, categoryLabel); + } + + model.setCategory(defaultCategory); + int categoryIndex = model.getCategoryIndex(defaultCategory); + if (log.isDebugEnabled()) { + log.debug("index of default category (" + defaultCategory + ") : " + + categoryIndex); + } + categories.setSelectedIndex(categoryIndex); + } + + public void changeCategory(ChangeEvent e) { + JPanel p = (JPanel) ui.getCategories().getSelectedComponent(); + if (p == null) { + // pas de selection + return; + } + ui.getModel().setCategory(p.getName()); + ui.getCategories().invalidate(); + } + + public void displayUI(Frame parentUI, boolean undecorated) { + JDialog f = new JDialog(parentUI, true); + f.setTitle(_("config.title")); + f.add(ui); + if (parentUI != null) { + f.setIconImage(parentUI.getIconImage()); + } + // pour savoir si l'ui est autonome + ui.getModel().setStandalone(parentUI == null); + + f.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); + f.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + ActionEvent myEvent = new ActionEvent(e.getSource(), 1, "quit"); + ui.getQuit().getAction().actionPerformed(myEvent); + } + }); + f.setUndecorated(undecorated); + JRootPane rootPane = f.getRootPane(); + rootPane.setDefaultButton(ui.getQuit()); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke("ESCAPE"), "quit"); + rootPane.getActionMap().put("quit", ui.getQuit().getAction()); + f.pack(); + SwingUtil.center(ui, f); + f.setVisible(true); + } + + protected Action createQuitAction() { + + JButton button = ui.getQuit(); + + Action quitAction = new AbstractAction(button.getText(), + button.getIcon()) { + + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + if (!canQuitCategory()) { + return; + } + + final Window parentWindow = ui.getParentContainer(Window.class); + + + ConfigUIModel model = ui.getModel(); + if (!model.isSaved() || model.isStandalone()) { + + // just quit, no callBack can be apply here + closeUI(parentWindow, model); + return; + } + + CallBackMap forSaved = model.getCallBacksForSaved(); + + if (forSaved.isEmpty()) { + + // just quit, no callBack to call + closeUI(parentWindow, model); + return; + } + + forSaved = model.getCallBacksForSaved(); + + // init callBackUI + + JAXXInitialContext context = new JAXXInitialContext(). + add("parent", parentWindow). + add(ui). + add(CALLBACKS_WITH_OPTIONS, forSaved). + add(CALLBACKS, + new ArrayList<CallBackEntry>(forSaved.keySet())). + add(new ConfigCallBackUIHandler()); + + ConfigCallBackUI lastUI = new ConfigCallBackUI(context); + + lastUI.init(); + ui.setVisible(false); + parentWindow.remove(ui); + parentWindow.add(lastUI); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + parentWindow.validate(); + } + }); + } + }; + return quitAction; + } + + protected void closeUI(Window parentWindow, ConfigUIModel model) { + + ui.destroy(); + + // close the config ui + parentWindow.dispose(); + + Runnable runnable = model.getCloseAction(); + if (runnable != null) { + log.info("execute close action"); + runnable.run(); + } + } + + protected boolean canQuitCategory() { + boolean canContinue = true; + ConfigUIModel model = ui.getModel(); + CategoryModel categoryModel = model.getCategoryModel(); + String categoryName = _(categoryModel.getCategory()); + if (!categoryModel.isValid()) { + + // the category is not valid + // get all the invalid options + + StringBuilder buffer = new StringBuilder(); + buffer.append(_("config.message.quit.invalid.category", + categoryName)); + buffer.append('\n'); + for (OptionModel m : categoryModel.getInvalidOptions()) { + buffer.append("\n- ").append(m.getKey()); + } + buffer.append('\n'); + int reponse = askUser(_("config.title.need.confirm"), + buffer.toString(), + JOptionPane.ERROR_MESSAGE, + new Object[]{ + _("config.choice.continue"), + _("config.choice.cancel")}, + 0); + + switch (reponse) { + case JOptionPane.CLOSED_OPTION: + case 1: + canContinue = false; + break; + case 0: + if (categoryModel.isModified()) { + // wil reset category + model.reset(); + } + break; + } + } else if (categoryModel.isModified()) { + + // category was modified, ask user if wants to save + + StringBuilder buffer = new StringBuilder(); + buffer.append(_("config.message.quit.valid.and.modified.category", + categoryName)).append('\n'); + for (OptionModel m : categoryModel.getModifiedOptions()) { + buffer.append("\n- ").append(m.getKey()); + } + buffer.append('\n'); + + int reponse = askUser(_("config.title.need.confirm"), + buffer.toString(), + JOptionPane.WARNING_MESSAGE, + new Object[]{ + _("config.choice.save"), + _("config.choice.doNotSave"), + _("config.choice.cancel")}, + 0); + + switch (reponse) { + case JOptionPane.CLOSED_OPTION: + case 2: + canContinue = false; + break; + case 0: + // will save ui + model.saveModified(); + break; + case 1: + // wil reset ui + model.reset(); + break; + } + } + return canContinue; + } + + public int askUser(String title, + String message, + int typeMessage, + Object[] options, + int defaultOption) { + + int response = JOptionPane.showOptionDialog( + ui, + message, + title, + JOptionPane.DEFAULT_OPTION, + typeMessage, + null, + options, + options[defaultOption] + ); + + return response; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUIHelper.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUIHelper.java new file mode 100644 index 0000000..c6df007 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/ConfigUIHelper.java @@ -0,0 +1,157 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Author$ + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config; + +import jaxx.runtime.JAXXContext; +import jaxx.runtime.context.JAXXInitialContext; +import jaxx.runtime.swing.editor.config.model.CallBackFinalizer; +import jaxx.runtime.swing.editor.config.model.CategoryModel; +import jaxx.runtime.swing.editor.config.model.ConfigUIModel; +import jaxx.runtime.swing.editor.config.model.ConfigUIModelBuilder; +import jaxx.runtime.swing.editor.config.model.OptionModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ApplicationConfig; + +import javax.swing.Icon; +import javax.swing.table.TableCellEditor; +import java.awt.Frame; + +/** + * A helper to build a config ui. + * <p/> + * contains all states as method to build model, then ui and finally display it. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class ConfigUIHelper { + + public static final Log log = LogFactory.getLog(ConfigUIHelper.class); + + /** internal model builder */ + protected final ConfigUIModelBuilder modelBuilder; + + /** internal model after builder flush */ + protected ConfigUIModel model; + + protected ConfigUI ui; + + public ConfigUIHelper(ApplicationConfig config) { + modelBuilder = new ConfigUIModelBuilder(); + modelBuilder.createModel(config); + } + + public ConfigUIModel getModel() { + if (model == null) { + model = modelBuilder.flushModel(); + } + return model; + } + + public void addCategory(String categoryName, String categoryLabel) + throws IllegalStateException, NullPointerException { + modelBuilder.addCategory(categoryName, categoryLabel); + } + + public void addOption(ApplicationConfig.OptionDef def) + throws IllegalStateException, NullPointerException { + modelBuilder.addOption(def); + } + + public void addOption(ApplicationConfig.OptionDef def, String propertyName) + throws IllegalStateException, NullPointerException { + modelBuilder.addOption(def, propertyName); + } + + public void setOptionPropertyName(String propertyName) + throws IllegalStateException, NullPointerException { + modelBuilder.setOptionPropertyName(propertyName); + } + + public void setOptionEditor(TableCellEditor editor) + throws IllegalStateException, NullPointerException { + modelBuilder.setOptionEditor(editor); + } + + public void registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + modelBuilder.registerCallBack(name, description, icon, action); + } + + public void setOptionCallBack(String name) { + modelBuilder.setOptionCallBack(name); + } + + public void setModel(ConfigUIModel model) throws IllegalStateException { + modelBuilder.setModel(model); + } + + public void setCategory(CategoryModel categoryModel) + throws IllegalStateException { + modelBuilder.setCategory(categoryModel); + } + + public void setOption(OptionModel optionModel) + throws IllegalStateException { + modelBuilder.setOption(optionModel); + } + + public void setFinalizer(CallBackFinalizer finalizer) { + modelBuilder.setFinalizer(finalizer); + } + + public void setCloseAction(Runnable runnable) { + modelBuilder.setCloseAction(runnable); + } + + /** + * Construire l'ui de configuration (sous forme de panel) + * + * @param parentContext le context applicatif + * @param defaultCategory la categorie a selectionner + * @return l'ui instanciate + */ + public ConfigUI buildUI(JAXXContext parentContext, + String defaultCategory) { + + ConfigUIModel model = getModel(); + + JAXXContext tx = new JAXXInitialContext().add(parentContext).add(model); + + ui = new ConfigUI(tx); + + ui.init(defaultCategory); + + return ui; + } + + public void displayUI(Frame parentUI, boolean undecorated) { + ui.getHandler().displayUI(parentUI, undecorated); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackEntry.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackEntry.java new file mode 100644 index 0000000..8b176b3 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackEntry.java @@ -0,0 +1,81 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config.model; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; + +/** + * A call back with his attached options. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class CallBackEntry { + + protected final String name; + protected final String description; + protected final Icon icon; + protected final Runnable action; + protected List<OptionModel> options; + + public CallBackEntry(String name, + String description, + Icon icon, + Runnable action) { + this.description = description; + this.icon = icon; + options = new ArrayList<OptionModel>(); + this.name = name; + this.action = action; + } + + public Runnable getAction() { + return action; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Icon getIcon() { + return icon; + } + + public List<OptionModel> getOptions() { + // always send a copy + return new ArrayList<OptionModel>(options); + } + + protected void addOption(OptionModel option) { + options.add(option); + + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackFinalizer.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackFinalizer.java new file mode 100644 index 0000000..693a179 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackFinalizer.java @@ -0,0 +1,43 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Author$ + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config.model; + +/** + * Contract to finalize the callbacks to launch. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public interface CallBackFinalizer { + + /** + * Do finalize the result. + * + * @param result unfinalized result + * @return the finalized result + */ + CallBackMap finalize(CallBackMap result); +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackMap.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackMap.java new file mode 100644 index 0000000..da6ddef --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBackMap.java @@ -0,0 +1,59 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Author$ + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config.model; + +import java.util.LinkedHashMap; +import java.util.List; + +/** + * A convient map of callback entry for a list of option. + * <p/> + * This model is used to store callbacks to use before a saving action. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class CallBackMap extends LinkedHashMap<CallBackEntry, List<OptionModel>> { + private static final long serialVersionUID = 1L; + + public boolean containsCallBack(String callBackName) { + for (CallBackEntry entry : keySet()) { + if (callBackName.equals(entry.getName())) { + return true; + } + } + return false; + } + + public CallBackEntry getCallBack(String callBackName) { + for (CallBackEntry entry : keySet()) { + if (callBackName.equals(entry.getName())) { + return entry; + } + } + return null; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBacksManager.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBacksManager.java new file mode 100644 index 0000000..4414e5a --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CallBacksManager.java @@ -0,0 +1,252 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config.model; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * CallBack manager. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class CallBacksManager { + + /** lists of registred callback. */ + protected List<CallBackEntry> callbacks; + + /** optional callbacks finalizer */ + protected CallBackFinalizer finalizer; + + public CallBacksManager() { + callbacks = new ArrayList<CallBackEntry>(); + } + + /** + * Obtain the finalizer to use. + * + * @return the finalizer (can be {@code null}). + * @see CallBackFinalizer + */ + public CallBackFinalizer getFinalizer() { + return finalizer; + } + + /** + * Sets the finalizer. + * + * @param finalizer the new finalizer + * @see CallBackFinalizer + */ + public void setFinalizer(CallBackFinalizer finalizer) { + this.finalizer = finalizer; + } + + /** + * Registers a new callback. + * <p/> + * <b>Note:</b> the order of registred callback is used to determine + * the higher priority of callback to launch if required. + * + * @param name the unique name of a callback + * @param description the i18n key to describe the action + * @param icon icon of callBack (used in ui) + * @param action the action of the callback + */ + public void registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + if (name == null) { + throw new NullPointerException( + "parameter 'name' can not be null"); + } + if (action == null) { + throw new NullPointerException( + "parameter 'action' can not be null"); + } + if (description == null) { + throw new NullPointerException( + "parameter 'description' can not be null"); + } + if (icon == null) { + throw new NullPointerException("parameter 'icon' can not be null"); + } + if (getCallBack(name) != null) { + throw new IllegalArgumentException( + "there is already a callback with name '" + name + "'"); + } + callbacks.add(new CallBackEntry(name, description, icon, action)); + } + + /** + * Registers a option into a known callback. + * + * @param name the name of the callback + * @param option the option to register for the given callback + */ + public void registerOption(String name, OptionModel option) { + if (name == null) { + throw new NullPointerException("parameter 'name' can not be null"); + } + if (option == null) { + throw new NullPointerException( + "parameter 'option' can not be null"); + } + CallBackEntry callback = getCallBack(name); + if (callback == null) { + throw new IllegalArgumentException( + "could not find a callback with name '" + name + "'"); + } + callback.addOption(option); + } + + /** + * Scan a model and grab per callBack the options saved. + * + * @param model the model to scan + * @return the dictionnary of options for each callback to launch + */ + public CallBackMap getCallBacksForSaved(ConfigUIModel model) { + + CallBackMap result = getCallBacks(model,true,false); + return result; + } + + /** + * Scan a category and grab per callBack the options saved. + * + * @param category the category to scan + * @return the dictionnary of options for each callBack to launch + */ + public CallBackMap getCallBacksForSaved(CategoryModel category) { + + CallBackMap result = getCallBacks(category,true,false); + return result; + } + + /** + * Scan a model and grab per callBack the options. + * + * @param model the model to scan + * @param modified {@code true} to include modified options + * @param saved {@code true} to include saved options + * @return the dictionnary of options for each callback to launch + */ + public CallBackMap getCallBacks(ConfigUIModel model, + boolean saved, + boolean modified) { + + CallBackMap result = new CallBackMap(); + + for (CategoryModel categoryModel : model) { + CallBackMap callBacks = + getCallBacks(categoryModel, saved, modified); + for (Map.Entry<CallBackEntry, List<OptionModel>> entry : + callBacks.entrySet()) { + CallBackEntry key = entry.getKey(); + List<OptionModel> value = entry.getValue(); + if (result.containsKey(key)) { + result.get(key).addAll(value); + } else { + result.put(key, value); + } + } + callBacks.clear(); + } + + CallBackFinalizer finalizer = getFinalizer(); + if (finalizer != null) { + result = finalizer.finalize(result); + } + return result; + } + + /** + * Scan a category and grab per callBack the options. + * + * @param category the category to scan + * @param modified {@code true} to include modified options + * @param saved {@code true} to include saved options + * @return the dictionnary of options for each callBack to launch + */ + public CallBackMap getCallBacks(CategoryModel category, + boolean saved, + boolean modified) { + + CallBackMap result = new CallBackMap(); + + for (OptionModel optionModel : category) { + if (modified && optionModel.isModified() || + saved && optionModel.isSaved()) { + CallBackEntry callBackEntry = getCallBack(optionModel); + if (callBackEntry != null) { + List<OptionModel> models = result.get(callBackEntry); + if (models == null) { + models = new ArrayList<OptionModel>(); + result.put(callBackEntry, models); + } + models.add(optionModel); + } + } + } + return result; + } + + /** + * Get the first callBack for a given option. + * + * @param option the option + * @return the first callBack (so the most important) on which the given + * option is attacjed. (can be null) + */ + protected CallBackEntry getCallBack(OptionModel option) { + for (CallBackEntry callback : callbacks) { + if (callback.getOptions().contains(option)) { + return callback; + } + } + return null; + } + + /** + * Obtain a registred callBack from his name. + * + * @param name the name of the searched callBack + * @return the callBack for the given name (or {@code null} if not found). + */ + protected CallBackEntry getCallBack(String name) { + for (CallBackEntry callback : callbacks) { + if (callback.getName().equals(name)) { + return callback; + } + } + return null; + } + +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CategoryModel.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CategoryModel.java new file mode 100644 index 0000000..d43b9d7 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/CategoryModel.java @@ -0,0 +1,213 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.config.model; + +import jaxx.runtime.JAXXUtil; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * le modele d'une categorie d'options. + * <p/> + * Une categorie est un ensemble d'options. + * + * @author tchemit + */ +public class CategoryModel implements Iterable<OptionModel>, Serializable { + + private static final long serialVersionUID = 1L; + + public static final String RELOAD_PROPERTY_NAME = "reload"; + + public static final String MODIFIED_PROPERTY_NAME = "modified"; + + public static final String VALID_PROPERTY_NAME = "valid"; + + /** category short name (i18n key) */ + protected String category; + + /** category long name (i18n key) */ + protected String categoryLabel; + + /** options of the category */ + protected List<OptionModel> entries; + + /** suport of modification */ + protected PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + protected CategoryModel(String category, String categoryLabel) { + this.category = category; + this.categoryLabel = categoryLabel; + entries = new ArrayList<OptionModel>(); + } + + protected void addOption(OptionModel option) { + entries.add(option); + } + + @Deprecated + public CategoryModel(String category, String categoryLabel, OptionModel[] entries) { + this.category = category; + this.categoryLabel = categoryLabel; + this.entries = Collections.unmodifiableList(Arrays.asList(entries)); + } + + public String getCategory() { + return category; + } + + public String getCategoryLabel() { + return categoryLabel; + } + + public List<OptionModel> getEntries() { + return entries; + } + + public boolean isModified() { + boolean modified = false; + for (OptionModel m : this) { + if (m.isModified()) { + modified = true; + break; + } + } + return modified; + } + + public boolean isValid() { + boolean valid = true; + for (OptionModel m : this) { + if (!m.isValid()) { + valid = false; + break; + } + } + return valid; + } + + public void setValue(OptionModel key, Object val) { + boolean wasModified = isModified(); + boolean wasValid = isValid(); + key.setValue(val); + boolean modified = isModified(); + boolean valid = isValid(); + if (wasModified != modified) { + // change modified state + firePropertyChange(MODIFIED_PROPERTY_NAME, wasModified, modified); + } + if (wasValid != valid) { + // change valid state + firePropertyChange(VALID_PROPERTY_NAME, wasValid, valid); + } + } + + @Override + public Iterator<OptionModel> iterator() { + return entries.iterator(); + } + + public List<OptionModel> getInvalidOptions() { + + List<OptionModel> result = new ArrayList<OptionModel>(); + for (OptionModel m : this) { + if (!m.isValid()) { + result.add(m); + } + } + return result; + } + + public List<OptionModel> getModifiedOptions() { + + List<OptionModel> result = new ArrayList<OptionModel>(); + for (OptionModel m : this) { + if (m.isModified()) { + result.add(m); + } + } + return result; + } + + public List<OptionModel> getSavedOptions() { + List<OptionModel> result = new ArrayList<OptionModel>(); + for (OptionModel option : this) { + if (option.isSaved()) { + result.add(option); + } + } + return result; + } + + public void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + 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 boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + public void destroy() { + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigTableModel.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigTableModel.java new file mode 100644 index 0000000..75a2f4d --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigTableModel.java @@ -0,0 +1,156 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.config.model; + +import org.nuiton.util.converter.ConverterUtil; + +import javax.swing.table.AbstractTableModel; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * le modele du tableau d'options pour une categorie donnee. + * <p/> + * Le modele se base sur le modele d'une categorie d'option. + * + * @author tchemit + * @see CategoryModel + */ +public class ConfigTableModel extends AbstractTableModel { + + private static final long serialVersionUID = 1L; + + private static final Class<?>[] columnClass = {String.class, Object.class, String.class}; + + /** le modele d'une categorie */ + protected final CategoryModel categoryModel; + + public ConfigTableModel(CategoryModel categoryModel) { + this.categoryModel = categoryModel; + // listen of property reload of the category model + // to known when to refresh table + this.categoryModel.addPropertyChangeListener(CategoryModel.RELOAD_PROPERTY_NAME, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + fireTableDataChanged(); + } + }); + } + + public CategoryModel getCategoryModel() { + return categoryModel; + } + + public OptionModel getEntry(int rowIndex) { + return categoryModel.getEntries().get(rowIndex); + } + + @Override + public int getRowCount() { + return categoryModel.getEntries().size(); + } + + @Override + public int getColumnCount() { + return columnClass.length; + } + + @Override + public Class<?> getColumnClass(int columnIndex) { + return columnClass[columnIndex]; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex == 1 && !getEntry(rowIndex).isFinal(); + } + + @Override + public Object getValueAt(int row, int column) { + OptionModel key = getEntry(row); + Object value = null; + switch (column) { + case 0: + value = key.getKey(); + break; + case 1: + value = key.getValue(); + break; + case 2: + value = key.getDefaultValue(); + if (value != null) { + value = ConverterUtil.convert(key.getType(), value); + } + break; + } + return value; +// if (column == 0) { +// return key.getKey(); +// } +// return key.getValue(); + } + + @Override + public void setValueAt(Object aValue, int row, int column) { + if (column != 1) { + // seul la colonne 1 est editable (valeur de l'option) + throw new IllegalArgumentException("can not edit column " + column); + } + OptionModel key = getEntry(row); + Object val; + if (aValue == null || key.getType().equals(aValue.getClass())) { + val = aValue; + } else { + String valStr = String.valueOf(aValue).trim(); + try { + val = ConverterUtil.convert(key.getType(), valStr); + if (val != null && val instanceof Integer) { + if (new Integer(0).equals(val) && !valStr.equals("0")) { + val = null; + } + } + } catch (Exception e) { + val = null; + } + } + categoryModel.setValue(key, val); + fireTableRowsUpdated(row, row); + } + + + public void destroy() { + if (categoryModel != null) { + categoryModel.destroy(); + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigUIModel.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigUIModel.java new file mode 100644 index 0000000..c237e65 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigUIModel.java @@ -0,0 +1,354 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.config.model; + +import jaxx.runtime.JAXXUtil; +import org.apache.commons.beanutils.PropertyUtils; +import org.nuiton.util.ApplicationConfig; + +import javax.swing.Icon; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static org.nuiton.i18n.I18n._; + +/** + * Le modele de l'ui des preferences. + * <p/> + * Ce modele contient les catégories des options. + * + * @author tchemit <chemit@codelutin.com> + */ +public class ConfigUIModel implements Iterable<CategoryModel> { + + public static final String CATEGORY_MODEL_PROPERTY_NAME = "categoryModel"; + + /** le dictionnaire des options disponibles par categorie */ + protected final Map<String, CategoryModel> categories; + + /** La configuration de l'application */ + protected final ApplicationConfig config; + + /** la cateogrie en cours d'utilisation */ + protected CategoryModel categoryModel; + + /** + * un drapeau pour savoir si la configuration a été modifiée au moins une + * fois. + * <p/> + * On utilise ce drapeau lors de la sortie pour verifier s'il faut ou non + * redemarer l'application (si non en mode standalone) + */ + protected boolean saved; + + /** + * un drapeau pour savoir si l'ui de configuration a été lancée en mode + * standalone ou pas. + * <p/> + * Si pas lancée en mode standalone, et si la confi a été sauvé on vérifie + * s'il ne faut pas relancer l'application. + */ + protected boolean standalone; + + /** Callbacks manager */ + protected CallBacksManager callBacksManager; + + /** + * optional action to execute (if not null) if no call backs fits. + * @since 1.4.2 + */ + protected Runnable closeAction; + + /** support of modification notifications */ + protected final PropertyChangeSupport pcs; + + public ConfigUIModel(ApplicationConfig config) { + this.config = config; + categories = new LinkedHashMap<String, CategoryModel>(); + callBacksManager = new CallBacksManager(); + pcs = new PropertyChangeSupport(this); + } + + /** + * Ajoute une categorie dans le modele. + * + * @param category la categorie a ajouter au modèle. + */ + public void addCategory(CategoryModel category) { + if (categories.containsKey(category.getCategory())) { + throw new IllegalArgumentException( + _("config.error.category.already.exists", + category.getCategory())); + } + categories.put(category.getCategory(), category); + } + + /** + * Change la categorie en cours d'édition. + * + * @param category l'id de la categorie courante + */ + public void setCategory(String category) { + if (!categories.containsKey(category)) { + throw new IllegalArgumentException( + _("config.error.category.not.found", category)); + } + CategoryModel newCategoryModel = categories.get(category); + setCategoryModel(newCategoryModel); + newCategoryModel.firePropertyChange( + CategoryModel.MODIFIED_PROPERTY_NAME, false, + getCategoryModel().isModified()); + newCategoryModel.firePropertyChange( + CategoryModel.VALID_PROPERTY_NAME, false, + getCategoryModel().isValid()); + } + + /** + * Registers a new callback. + * <p/> + * <b>Note:</b> the order of registred callback is used to determine + * the higher priority of callback to launch if required. + * + * @param name the unique name of a callback + * @param description the i18n key to describe the action + * @param icon the icon of the callBack (used in ui) + * @param action the action of the callback + */ + public void registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + callBacksManager.registerCallBack(name, description, icon, action); + } + + /** + * Registers a option into a known callback. + * + * @param name the name of the callback + * @param option the option to register for the given callback + */ + public void registerOptionCallBack(String name, OptionModel option) { + callBacksManager.registerOption(name, option); + } + + public void setFinalizer(CallBackFinalizer finalizer) { + callBacksManager.setFinalizer(finalizer); + } + + public Runnable getCloseAction() { + return closeAction; + } + + public void setCloseAction(Runnable closeAction) { + this.closeAction=closeAction; + } + + /** + * Obtain the dictionnary of callback for all to saved modified options. + * + * @return the dictonnary + */ + public CallBackMap getCallBacksForSaved() { + return callBacksManager.getCallBacksForSaved(this); + } + + @Override + public Iterator<CategoryModel> iterator() { + return categories.values().iterator(); + } + + public CategoryModel getCategoryModel() { + return categoryModel; + } + + public void setCategoryModel(CategoryModel categoryModel) { + CategoryModel old = this.categoryModel; + this.categoryModel = categoryModel; + firePropertyChange(CATEGORY_MODEL_PROPERTY_NAME, old, categoryModel); + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public boolean isStandalone() { + return standalone; + } + + public void setStandalone(boolean standalone) { + this.standalone = standalone; + } + + public void saveModified() { + // compute transients keys (to never be saved) + List<String> transients = new ArrayList<String>(); + + config.setAdjusting(true); + + try { + for (OptionModel option : categoryModel) { + if (option.isModified()) { + Object value = option.getValue(); + if (option.getPropertyName() != null) { + + // this is a javaBean option, push value via mutator + try { + PropertyUtils.setProperty(config, + option.getPropertyName(), value); + } catch (Exception e) { + throw new RuntimeException( + "could not set property [" + + option.getPropertyName() + + "] with value = " + value, e); + } + } else { + + // simple option with no javabeans, just push the option + // value + config.setOption(option.getKey(), value == null ? + null : value.toString()); + } + // l'option a été sauvegardée, on la marque + option.setSaved(true); + // this is the new original value + option.initValue(value); + } + if (option.isTransient()) { + transients.add(option.getKey()); + } + } + } finally { + config.setAdjusting(false); + } + + setSaved(true); + // save config + config.saveForUser(transients.toArray(new String[transients.size()])); + // notify data has changed + categoryModel.firePropertyChange( + CategoryModel.MODIFIED_PROPERTY_NAME, + categoryModel.isModified(), true); + categoryModel.firePropertyChange( + CategoryModel.VALID_PROPERTY_NAME, + false, categoryModel.isValid()); + categoryModel.firePropertyChange( + CategoryModel.RELOAD_PROPERTY_NAME, false, true); + } + + public void reset() { + // reset all modified options of the current category + for (OptionModel key : categoryModel) { + if (key.isModified()) { + key.initValue(key.getOriginalValue()); + } + } + // notify data has changed + categoryModel.firePropertyChange( + CategoryModel.MODIFIED_PROPERTY_NAME, + categoryModel.isModified(), true); + categoryModel.firePropertyChange( + CategoryModel.VALID_PROPERTY_NAME, + false, categoryModel.isValid()); + categoryModel.firePropertyChange( + CategoryModel.RELOAD_PROPERTY_NAME, false, true); + } + + public int getCategoryIndex(String category) { + int i = 0; + for (CategoryModel m : this) { + if (category.equals(m.getCategory())) { + return i; + } + i++; + } + // not found + return -1; + } + + public void firePropertyChange(String propertyName, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + 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 boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners( + String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + public void destroy() { + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } + + protected ApplicationConfig getConfig() { + return config; + } + + protected CallBacksManager getCallBacksManager() { + return callBacksManager; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigUIModelBuilder.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigUIModelBuilder.java new file mode 100644 index 0000000..6130bd5 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/ConfigUIModelBuilder.java @@ -0,0 +1,333 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config.model; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ApplicationConfig; + +import javax.swing.Icon; +import javax.swing.table.TableCellEditor; + +/** + * A builder of {@link ConfigUIModel} + * Created: 22 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class ConfigUIModelBuilder { + /** Logger */ + private static final Log log = LogFactory.getLog(ConfigUIModelBuilder.class); + + /** current model used */ + ConfigUIModel model; + + /** current category used */ + CategoryModel category; + + /** current option used */ + OptionModel option; + + /** + * Create a new model and set it as current model. + * + * @param config the configuration used in model + * @throws IllegalStateException if there is already a current model + * @throws NullPointerException if config is {@code null} + */ + public void createModel(ApplicationConfig config) + throws IllegalStateException, NullPointerException { + checkNoCurrent(model, "model"); + checkNotNull(config, "createModel", "config"); + model = new ConfigUIModel(config); + if (log.isDebugEnabled()) { + log.debug("model created : " + model); + } + } + + /** + * Add a new category, and set it as current. + * <p/> + * <b>Note:</b> As side effets, if a previous category, then store it to + * the model. + * + * @param categoryName the name of the new category + * (can not to be {@code null}) + * @param categoryLabel the label of the new category + * (can not to be {@code null}) + * @throws IllegalStateException if there is not a current model, + * nor category + * @throws NullPointerException if any of parameter is {@code null} + */ + public void addCategory(String categoryName, String categoryLabel) + throws IllegalStateException, NullPointerException { + checkCurrent(model, "model"); + checkNotNull(categoryName, "addCategory", "categoryName"); + checkNotNull(categoryLabel, "addCategory", "categoryLabel"); + flushCategory(); + category = new CategoryModel(categoryName, categoryLabel); + if (log.isDebugEnabled()) { + log.debug("category created : " + category); + } + } + + /** + * Add a new option, and set it as current. + * <p/> + * <b>Note:</b> As side effets, if a previous option, then store it to + * the model. + * + * @param def the def ot the new option + * @throws IllegalStateException if there is not a current model, + * nor category + * @throws NullPointerException if any of parameter is {@code null} + */ + public void addOption(ApplicationConfig.OptionDef def) + throws IllegalStateException, NullPointerException { + checkCurrent(model, "model"); + checkCurrent(category, "category"); + checkNotNull(def, "addOption", "def"); + flushOption(); + Object value = model.getConfig().getOption(def); + option = new OptionModel(def, value); + if (log.isDebugEnabled()) { + log.debug("option created : " + option); + } + } + + /** + * Add a new option with a propertyName, and set it as current. + * <p/> + * <b>Note:</b> As side effets, if a previous option, then store it to + * the model. + * <p/> + * <b>Note:</b> This method is a short-cut for + * {@link #addOption(org.nuiton.util.ApplicationConfig.OptionDef)} then + * {@link #setOptionPropertyName(String)}. + * + * @param def the def ot the new option + * @param propertyName the propertyName to set on the option + * @throws IllegalStateException if there is not a current model, nor + * category + * @throws NullPointerException if any of parameter is {@code null} + */ + public void addOption(ApplicationConfig.OptionDef def, String propertyName) + throws IllegalStateException, NullPointerException { + addOption(def); + checkNotNull(propertyName, "setOptionPropertyName", "propertyName"); + option.setPropertyName(propertyName); + } + + /** + * Set the propertyName on the current option. + * + * @param propertyName the propertyName to set in the current option. + * @throws IllegalStateException if there is not a current option set. + * @throws NullPointerException if any of parameter is {@code null} + * @see OptionModel#setPropertyName(String) + */ + public void setOptionPropertyName(String propertyName) + throws IllegalStateException, NullPointerException { + checkCurrent(option, "option"); + checkNotNull(propertyName, "setOptionPropertyName", "propertyName"); + option.setPropertyName(propertyName); + } + + /** + * Set the editor on the current option. + * + * @param editor the editor to set in the current option. + * @throws IllegalStateException if there is not a current option set. + * @throws NullPointerException if any of parameter is {@code null} + * @see OptionModel#setEditor(TableCellEditor) + */ + public void setOptionEditor(TableCellEditor editor) + throws IllegalStateException, NullPointerException { + checkCurrent(option, "option"); + checkNotNull(editor, "setOptionEditor", "editor"); + option.setEditor(editor); + } + + /** + * Registers a new callback. + * <p/> + * <b>Note:</b> the order of registred callback is used to determine + * the higher priority of callback to launch if required. + * + * @param name the unique name of a callback + * @param description the i18n key to describe the action + * @param icon the icon of the callBack (used in ui) + * @param action the action of the callback + */ + public void registerCallBack(String name, + String description, + Icon icon, + Runnable action) { + checkCurrent(model, "model"); + checkNotNull(name, "registerCallBack", "name"); + checkNotNull(description, "registerCallBack", "description"); + checkNotNull(action, "registerCallBack", "action"); + model.registerCallBack(name, description, icon, action); + } + + /** + * Registers the current option into a known callback. + * + * @param name the name of the callback + */ + public void setOptionCallBack(String name) { + checkCurrent(option, "option"); + checkNotNull(name, "setOptionCallBack", "name"); + model.registerOptionCallBack(name, option); + } + + public void setFinalizer(CallBackFinalizer finalizer) { + model.setFinalizer(finalizer); + } + + /** + * Flush the model and return it. + * <p/> + * <b>Note:</b> As a side effect, nothing is available in the builder + * after this operation. + * To reuse the builder on a model, use the dedicated setter. + * + * @return the final model + * @throws IllegalStateException if there is not a current model set. + */ + public ConfigUIModel flushModel() throws IllegalStateException { + checkCurrent(model, "model"); + flushCategory(); + ConfigUIModel result = model; + model = null; + return result; + } + + /** + * Set the given model as current model. + * <p/> + * <b>Note:</b> As side effets, il will clean current category and option. + * + * @param model the model to use + * @throws IllegalStateException if there is already a current model + */ + public void setModel(ConfigUIModel model) throws IllegalStateException { + checkNoCurrent(model, "model"); + this.model = model; + if (log.isDebugEnabled()) { + log.debug("new current model : " + this.model); + } + category = null; + option = null; + } + + /** + * Set the given category as current category. + * <p/> + * <b>Note:</b> As side effets, il will clean current option. + * + * @param categoryModel the category to use + * @throws IllegalStateException if there is not a current model or a + * current category + */ + public void setCategory(CategoryModel categoryModel) + throws IllegalStateException { + checkCurrent(model, "model"); + checkNoCurrent(category, "category"); + category = categoryModel; + if (log.isDebugEnabled()) { + log.debug("new current category : " + category); + } + option = null; + } + + /** + * Sets the given option as current option. + * + * @param optionModel the option to use + * @throws IllegalStateException if there is not a current model, nor + * category, or a current option + */ + public void setOption(OptionModel optionModel) + throws IllegalStateException { + checkCurrent(model, "model"); + checkCurrent(category, "category"); + checkNoCurrent(option, "option"); + option = optionModel; + if (log.isDebugEnabled()) { + log.debug("new current option : " + option); + } + } + + public void setCloseAction(Runnable runnable) { + checkNotNull(runnable, "setCloseAction", "runnable"); + checkCurrent(model, "model"); + model.setCloseAction(runnable); + + } + + protected CategoryModel flushCategory() { + CategoryModel result = category; + if (category != null) { + flushOption(); + // add the previous category to the model + model.addCategory(category); + category = null; + } + return result; + } + + protected OptionModel flushOption() { + OptionModel result = option; + if (option != null) { + // add the previous option to the category + category.addOption(option); + option = null; + } + return result; + } + + protected void checkCurrent(Object o, String type) { + if (o == null) { + throw new IllegalStateException("no current " + type + "!"); + } + } + + protected void checkNoCurrent(Object o, String type) { + if (o != null) { + throw new IllegalStateException( + "there is already a current " + type + "!"); + } + } + + protected void checkNotNull(Object o, String method, String parameter) { + if (o == null) { + throw new NullPointerException( + "method " + method + " does not support null parameter " + + parameter + "!"); + } + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/MainCallBackFinalizer.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/MainCallBackFinalizer.java new file mode 100644 index 0000000..2012e29 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/MainCallBackFinalizer.java @@ -0,0 +1,66 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Author$ + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config.model; + +import java.util.ArrayList; +import java.util.List; + +/** + * A finalizer to mark a special category to eat every others categories + * when finalizing. + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.2 + */ +public class MainCallBackFinalizer implements CallBackFinalizer { + + /** name of call back which eats everybody */ + protected final String mainCallBack; + + public MainCallBackFinalizer(String mainCallBack) { + this.mainCallBack = mainCallBack; + } + + @Override + public CallBackMap finalize(CallBackMap result) { + CallBackEntry applicationEntry = result.getCallBack(mainCallBack); + CallBackMap newResult; + if (applicationEntry == null) { + // rien n'a change + newResult = result; + } else { + newResult = new CallBackMap(); + // on passe toutes les options sur ce callback + List<OptionModel> options = new ArrayList<OptionModel>(); + + for (List<OptionModel> optionModels : result.values()) { + options.addAll(optionModels); + } + newResult.put(applicationEntry, options); + } + return newResult; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/OptionModel.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/OptionModel.java new file mode 100644 index 0000000..d413aec --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/OptionModel.java @@ -0,0 +1,164 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.config.model; + +import org.nuiton.util.ApplicationConfig.OptionDef; + +import javax.swing.table.TableCellEditor; + +/** + * le modele d'une option de la configuration a editer. + * + * @author tchemit + */ +public class OptionModel implements OptionDef { + + private static final long serialVersionUID = 1L; + + /** la definition de l'option (venant de la config) */ + protected final OptionDef def; + + /** un drapeau pour savoir si l'option est valide (n'est pas utilisé actuellement) */ + protected boolean valid = true; + + /** un drapeau pour savoir si l'option a été sauvée */ + protected boolean saved; + + /** la valeur non modifié de l'option */ + protected Object originalValue; + + /** la valeur actuelle de l'option (peut être la valeur orignal si non modifée) */ + protected Object value; + + /** le nom de la propriété javaBean (peut etre null, si option sans support javaBean) */ + protected String propertyName; + + /** l'editeur utilise pour modifier graphiquement l'option */ + protected TableCellEditor editor; + + protected OptionModel(OptionDef def, Object value) { + this.def = def; + initValue(value); + } + + @Override + public String getKey() { + return def.getKey(); + } + + @Override + public Class<?> getType() { + return def.getType(); + } + + @Override + public String getDescription() { + return def.getDescription(); + } + + @Override + public String getDefaultValue() { + return def.getDefaultValue(); + } + + @Override + public boolean isTransient() { + return def.isTransient(); + } + + @Override + public boolean isFinal() { + return def.isFinal(); + } + + public Object getOriginalValue() { + return originalValue; + } + + public Object getValue() { + return value; + } + + @Override + public void setDefaultValue(String defaultValue) { + def.setDefaultValue(defaultValue); + } + + @Override + public void setTransient(boolean isTransient) { + def.setTransient(isTransient); + } + + @Override + public void setFinal(boolean isFinal) { + def.setFinal(isFinal); + } + + public void setValue(Object value) { + this.value = value; + } + + public boolean isModified() { + return !originalValue.equals(value); + } + + public boolean isValid() { + return valid; + } + + public void setValid(boolean valid) { + this.valid = valid; + } + + public boolean isSaved() { + return saved; + } + + public void setSaved(boolean saved) { + this.saved = saved; + } + + public void initValue(Object originalValue) { + this.originalValue = originalValue; + value = originalValue; + } + + public String getPropertyName() { + return propertyName; + } + + public TableCellEditor getEditor() { + return editor; + } + + protected void setEditor(TableCellEditor editor) { + this.editor = editor; + } + + protected void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/package.html b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/package.html new file mode 100644 index 0000000..5103706 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/model/package.html @@ -0,0 +1,31 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>Package jaxx.runtime.swing.editor.config.model</h1> + +the package contains the models of the Config UI. +</body> +</html> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/package.html b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/package.html new file mode 100644 index 0000000..c6f35b5 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/config/package.html @@ -0,0 +1,42 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>Package jaxx.runtime.swing.editor.config</h1> + +This package contains the Config ui, based on org.nuiton.util.ApplicationConfig. + +The config ui is categorized and offers possibility to add callbacks to run +when configuration was saved. + +<hr/> +<ul> + <li> + ConfigUIBuilder offers you a simple way to build the ConfigUI (and his + model). + </li> +</ul> +</body> +</html> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/package.html b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/package.html new file mode 100644 index 0000000..6e19f32 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/editor/package.html @@ -0,0 +1,36 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>Package jaxx.runtime.swing.editor</h1> + +Package containing several richi editors : +<ul> + <li>NumberEditor : a rich number editor with a calculator on popup</li> + <li>TimeEditor : a rich time editor based on JSpinner components</li> + <li>I18nEditor : a rich locale editor</li> +</ul> +</body> +</html> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jAppender.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jAppender.java new file mode 100644 index 0000000..30a3357 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jAppender.java @@ -0,0 +1,141 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.log; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.LinkedList; +import java.util.List; +import org.apache.log4j.Level; +import org.apache.log4j.WriterAppender; +import org.apache.log4j.spi.LoggingEvent; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class JAXXLog4jAppender extends WriterAppender { + + public static final String PROPERTY_LOGS = "logs"; + public static final String PROPERTY_LEVEL = "level"; + + protected List<LoggingEvent> events; + protected StringBuilder logs; + protected Level level; + + protected final PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public JAXXLog4jAppender() { + events = new LinkedList<LoggingEvent>(); + logs = new StringBuilder(); + } + + public String getLogs() { + return logs.toString(); + } + + public void setLogs(String logs) { + String oldValue = getLogs(); + this.logs = new StringBuilder(logs); + firePropertyChange(PROPERTY_LOGS, oldValue, logs); + } + + public Level getLevel() { + if (level == null) { + level = Level.ALL; + } + return level; + } + + public void setLevel(Level level) { + Level oldValue = getLevel(); + this.level = level; + firePropertyChange(PROPERTY_LEVEL, oldValue, level); + updateLogs(); + } + + @Override + public void append(LoggingEvent event) { + super.append(event); + if (event != null) { + events.add(event); + updateLog(event); + } + } + + protected void updateLogs() { + String oldValue = getLogs(); + logs = new StringBuilder(); + for (LoggingEvent event : events) { + updateLog(event); + } + firePropertyChange(PROPERTY_LOGS, oldValue, getLogs()); + } + + protected void updateLog(LoggingEvent event) { + Level level = event.getLevel(); + if (getLevel() != null && level.isGreaterOrEqual(getLevel())) { + String log = this.layout.format(event); + appendLog(log); + if(layout.ignoresThrowable()) { + String[] errorLogs = event.getThrowableStrRep(); + if (errorLogs != null) { + for (String errorLog : errorLogs) { + appendLog(errorLog + "\n"); + } + } + } + } + } + + protected void appendLog(String log) { + String oldValue = getLogs(); + logs.append(log); + firePropertyChange(PROPERTY_LOGS, oldValue, getLogs()); + } + + 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); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected void firePropertyChange(String propertyName, Object newValue) { + firePropertyChange(propertyName, null, newValue); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jHandler.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jHandler.java new file mode 100644 index 0000000..c4debaf --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jHandler.java @@ -0,0 +1,126 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.log; + +import java.awt.Component; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; +import jaxx.runtime.JAXXUtil; +import jaxx.runtime.SwingUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class JAXXLog4jHandler { + + private static final Log log = LogFactory.getLog(JAXXLog4jHandler.class); + + protected JAXXLog4jUI ui; + + protected static JAXXLog4jAppender appender; + + public JAXXLog4jHandler(JAXXLog4jUI ui) { + this.ui = ui; + } + + /** + * Init {@link JAXXLog4jAppender} with level INFO and pattern : %5p [%t] (%F:%L) %M - %m%n + */ + public static void init() { + init("INFO", "%5p [%t] (%F:%L) %M - %m%n"); + } + + /** + * Init {@link JAXXLog4jAppender} with specific {@link Level} and {@link PatternLayout} + * + * @param level specify log4j {@link Level} + * @param patternLayout log4j {@link PatternLayout} to display + */ + public static void init(String level, String patternLayout) { + Logger logger = Logger.getRootLogger(); + + if (appender == null) { + appender = new JAXXLog4jAppender(); + logger.addAppender(appender); + } + appender.setLevel(Level.toLevel(level)); + appender.setLayout(new PatternLayout(patternLayout)); + } + + final protected Action closeAction = new AbstractAction("close") { + private static final long serialVersionUID = 1L; + + @Override + public void actionPerformed(ActionEvent e) { + JDialog container = ui.getParentContainer(JDialog.class); + if (container != null) { + container.dispose(); + } else { + ui.setVisible(false); + } + } + }; + + public JAXXLog4jAppender getAppender() { + return appender; + } + + public void showInDialog(Frame ui, boolean undecorated) { + JDialog f = new JDialog(ui, this.ui.getTitle(), false); + f.add(this.ui); + f.setResizable(true); + f.setSize(550, 450); + f.setUndecorated(undecorated); + JRootPane rootPane = f.getRootPane(); + rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "close"); + rootPane.getActionMap().put("close", closeAction); + f.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + Component ui = (Component) e.getSource(); + if (log.isInfoEnabled()) { + log.info("destroy ui " + ui); + } + JAXXUtil.destroy(ui); + JAXXUtil.destroy(JAXXLog4jHandler.this.ui); + } + }); + SwingUtil.center(ui, f); + f.setVisible(true); + } +} diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx new file mode 100644 index 0000000..0a4272d --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/log/JAXXLog4jUI.jaxx @@ -0,0 +1,121 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2012 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<JPanel id='log4jUI' layout='{new BorderLayout()}'> + + <import> + java.awt.Frame + org.apache.log4j.Level + </import> + + <script><![CDATA[ + + /** + * Init {@link JAXXLog4jAppender} with level INFO and pattern : %5p [%t] (%F:%L) %M - %m%n + */ + public static void init() { + JAXXLog4jHandler.init(); + } + + /** + * Init {@link JAXXLog4jAppender} with specific {@link Level} and {@link PatternLayout} + * + * @param level specify log4j {@link Level} + * @param patternLayout log4j {@link PatternLayout} to display + */ + public static void init(String level, String patternLayout) { + JAXXLog4jHandler.init(level, patternLayout); + } + + public void showInDialog(Frame ui, boolean undecorated) { + handler.showInDialog(ui, undecorated); + } + ]]></script> + + <String id='title' javaBean='null'/> + + <JAXXLog4jHandler id='handler' constructorParams='this'/> + + <JAXXLog4jAppender id='model' initializer='getHandler().getAppender()'/> + + <JScrollPane constraints='BorderLayout.CENTER'> + <JEditorPane id='logArea' + text='{model.getLogs()}'/> + </JScrollPane> + + <Table constraints='BorderLayout.SOUTH'> + <row> + <cell> + <JRadioButton id='fatalRadio' + buttonGroup="levelRadioGroup" + text='{Level.FATAL.toString()}' + value='{Level.FATAL}' + onActionPerformed='model.setLevel(Level.FATAL)'/> + </cell> + <cell> + <JRadioButton id='errorRadio' + buttonGroup="levelRadioGroup" + text='{Level.ERROR.toString()}' + value='{Level.ERROR}' + onActionPerformed='model.setLevel(Level.ERROR)'/> + </cell> + <cell> + <JRadioButton id='warnRadio' + buttonGroup="levelRadioGroup" + text='{Level.WARN.toString()}' + value='{Level.WARN}' + onActionPerformed='model.setLevel(Level.WARN)'/> + </cell> + <cell> + <JRadioButton id='infoRadio' + buttonGroup="levelRadioGroup" + text='{Level.INFO.toString()}' + value='{Level.INFO}' + onActionPerformed='model.setLevel(Level.INFO)'/> + </cell> + <cell> + <JRadioButton id='debugRadio' + buttonGroup="levelRadioGroup" + text='{Level.DEBUG.toString()}' + value='{Level.DEBUG}' + onActionPerformed='model.setLevel(Level.DEBUG)'/> + </cell> + <cell> + <JRadioButton id='traceRadio' + buttonGroup="levelRadioGroup" + text='{Level.TRACE.toString()}' + value='{Level.TRACE}' + onActionPerformed='model.setLevel(Level.TRACE)'/> + </cell> + <cell> + <JRadioButton id='allRadio' + buttonGroup="levelRadioGroup" + text='{Level.ALL.toString()}' + value='{Level.ALL}' + selected='true' + onActionPerformed='model.setLevel(Level.ALL)'/> + </cell> + </row> + </Table> +</JPanel> \ No newline at end of file diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/package.html b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/package.html new file mode 100644 index 0000000..c959e9a --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/package.html @@ -0,0 +1,49 @@ +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<html> +<body> +<h1>Package jaxx.runtime.swing</h1> + +<p> + Base package of the project <strong>jaxx-widgets</strong>. +</p> + +In this package, we can find several simple widgets : + +<ul> + <li>AboutPanel : an About dialog ui</li> + <li>ClockWidget : a widget which displays time</li> + <li>EntityComboBox : a rich drop list of beans based on Decorator api</li> + <li>ErrordialogUI : error dialog to use each time there is an error</li> + <li>FontSizor : a widget to change font size</li> + <li>HidorButton : a simple widget to show and hide components</li> + <li>ListSelectorUI :</li> + <li>MemoryStatusWidget : a widget to display memory usage</li> + <li>StatusMessagePanel : a panel to display messages and show status of + application (busy, waking, ...) + </li> +</ul> +</body> +</html> diff --git a/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/renderer/DateCellRenderer.java b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/renderer/DateCellRenderer.java new file mode 100644 index 0000000..2c98fbc --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/jaxx/runtime/swing/renderer/DateCellRenderer.java @@ -0,0 +1,62 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.renderer; + +import java.awt.Component; +import java.text.SimpleDateFormat; +import java.util.Date; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.TableCellRenderer; +import org.apache.commons.lang3.StringUtils; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class DateCellRenderer implements TableCellRenderer { + + protected TableCellRenderer delegate; + protected SimpleDateFormat dateFormat; + + public DateCellRenderer(TableCellRenderer renderer, String datePattern) { + this.delegate = renderer; + dateFormat = new SimpleDateFormat(); + if (datePattern != null) { + dateFormat.applyPattern(datePattern); + } + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel render = (JLabel) delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + Date date = (Date) value; + String formatedDate = StringUtils.EMPTY; + if (date != null) { + formatedDate = dateFormat.format(date); + } + render.setText(formatedDate); + return render; + + } +} diff --git a/trunk/jaxx-widgets/src/main/java/org/jdesktop/swingx/plaf/basic/ExtendedBasicDatePickerUI.java b/trunk/jaxx-widgets/src/main/java/org/jdesktop/swingx/plaf/basic/ExtendedBasicDatePickerUI.java new file mode 100644 index 0000000..4de48d8 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/java/org/jdesktop/swingx/plaf/basic/ExtendedBasicDatePickerUI.java @@ -0,0 +1,91 @@ +/* + * #%L + * JAXX :: Widgets + * $Id:$ + * $HeadURL:$ + * %% + * Copyright (C) 2008 - 2012 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package org.jdesktop.swingx.plaf.basic; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyVetoException; +import java.util.Date; +import javax.swing.JButton; + +/** + * @author sletellier <letellier@codelutin.com> + */ +public class ExtendedBasicDatePickerUI extends BasicDatePickerUI { + + public static final String PROPERTY_SHOW_POPUP_BUTTON = "showPopupButton"; + + protected JButton popupButton; + protected PropertyChangeSupport p; + protected boolean showPopupButton; + + public ExtendedBasicDatePickerUI() { + p = new PropertyChangeSupport(this); + p.addPropertyChangeListener(PROPERTY_SHOW_POPUP_BUTTON, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + + // dont do this on init + if (datePicker != null) { + installComponents(); + installListeners(); + } + } + }); + } + + public boolean isShowPopupButton() { + return showPopupButton; + } + + public void setShowPopupButton(boolean showPopupButton) { + boolean oldValue = isShowPopupButton(); + this.showPopupButton = showPopupButton; + p.firePropertyChange("showPopupButton", oldValue, showPopupButton); + } + + @Override + protected JButton createPopupButton() { + + if (datePicker != null && popupButton != null) { + datePicker.remove(popupButton); + } + if (isShowPopupButton()) { + popupButton = super.createPopupButton(); + return popupButton; + } + return null; + } + + @Override + public Date getSelectableDate(Date date) throws PropertyVetoException { + if (date == null) { + // one place to interrupt the update spiral + throw new PropertyVetoException("date not selectable", null); + } + return date; + } +} diff --git a/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_en_GB.properties b/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_en_GB.properties new file mode 100644 index 0000000..c60b2f6 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_en_GB.properties @@ -0,0 +1,86 @@ +aboutframe.about=About +aboutframe.license=License +aboutframe.ok=OK +aboutframe.thirdparty=Third party +bean.popup.label=Object '%1$s' +bean.sort.down=Descending sort +bean.sort.down.tip=Actually, sort order is descending +bean.sort.down.toSelect.tip=To sort in Descending order +bean.sort.label=Sort order +bean.sort.off=Click to activate the sort on this property +bean.sort.on=This is the property actually used +bean.sort.up=Ascending sort +bean.sort.up.tip=Actually, sort order is acending +bean.sort.up.toSelect.tip=Click here to sort in ascending order +bean.unknown.type=Object of unkown type +beancombobox.action.reset.tip=Reset the selected value +beancombobox.action.sort.tip=Change the sorted property +beancombobox.popup.title=Change the sorted property +beanlist.action.reset.tip=Reset the selected selection +beanlist.action.sort.tip=Change the sorted property +beanlist.popup.title=Change the sorted property +config.action.quit=Quit +config.action.quit.tip=Quit the configuration editor +config.action.reset=Cancel +config.action.reset.tip=Cancel the modifications for the category +config.action.save=Save +config.action.save.tip=Save the modifications for the category +config.choice.cancel=Cancel +config.choice.continue=Continue +config.choice.doNotSave=Do not save +config.choice.save=Save +config.defaultValue=Default value +config.defaultValue.tip=Default value of the option +config.description=Description +config.detected.callBack=Detected actions +config.error.category.already.exists=category with name '%1$s' does already exist\! +config.error.category.not.found=category with name '%1$s' does not exist\! +config.key=Key +config.key.tip=Key of the option +config.launch.callBack=Perform +config.launch.callBack.tip=Perform necessary actions +config.message.quit.invalid.category=The category '%1$s' is not valid\! +config.message.quit.valid.and.modified.category=The category '%1$s' has some modified options \: +config.modified=Option was modified (previous value \: %1$s) +config.no.option.selected=< No selected option > +config.option.final=This option can not be modified +config.option.label=Option '%1$s' (%2$s) +config.option.modified=Value is modified < original value \: '%1$s' - new value \: '%2$s' > +config.title=Preferences +config.title.need.confirm=A confirmation is required +config.unmodifiable=Can not be modified +config.unvalid=Option is not valid \! (previous value \: %1$s, required type \: %2$s) +config.value=Value +config.value.tip=Value of the option +errorUI.action.close=Close +errorUI.message=An error wad detected... +errorUI.title=Error... +fontsize.action.default.tip=Restore default font size +fontsize.action.down.tip=Decrease font size +fontsize.action.up.tip=Increase font size +hidor.hideTip=Hide +hidor.showTip=Show +i18neditor.empty.locales=< No locale to select > +i18neditor.popup.title=Change language +i18neditor.selected=Selected language \: %1$s +i18neditor.unselected=Select this langage \: %1$s +listSelector.hideList=Hide the list +listSelector.showList=Show the list +memorywidget.memory=%d/%dMb +numbereditor..=. +numbereditor.0=0 +numbereditor.1=1 +numbereditor.2=2 +numbereditor.3=3 +numbereditor.4=4 +numbereditor.5=5 +numbereditor.6=6 +numbereditor.7=7 +numbereditor.8=8 +numbereditor.9=9 +numbereditor.action.reset.tip=Reset +numbereditor.action.show.tip=Show numeric panel +numbereditor.clearAll=C +numbereditor.clearOne=CE +numbereditor.toggleSign=+/- +timeeditor.H=H diff --git a/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_es_ES.properties b/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_es_ES.properties new file mode 100644 index 0000000..a089336 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_es_ES.properties @@ -0,0 +1,86 @@ +aboutframe.about=A cerca de +aboutframe.license=Licecia +aboutframe.ok=OK +aboutframe.thirdparty=Tierce partie +bean.popup.label=Objeto '%1$s' +bean.sort.down=Calsificación decreciente +bean.sort.down.tip=Clasificación decreciente actualmente utilizada +bean.sort.down.toSelect.tip=Clic para clasificar según orden decreciente +bean.sort.label=Orden de clasificación +bean.sort.off=Click para activar la clasificación de la propiedad '%1$s' +bean.sort.on=Clasificación realizada sobre la propiedad '%1$s' +bean.sort.up=Clasificación creciente +bean.sort.up.tip=Clasificación creciente actualmente utilizada +bean.sort.up.toSelect.tip=Clic para clasificar según orden creciente +bean.unknown.type=Objeto de tipo desconocido +beancombobox.action.reset.tip=Reiniciar el valor de la lista desplegable +beancombobox.action.sort.tip=Modificar la clasificación de la lista desplegable +beancombobox.popup.title=Modificar la clasificación +beanlist.action.reset.tip=Eliminar la selección +beanlist.action.sort.tip=Modificar la clasificación de la lista despleglable +beanlist.popup.title=Modificar la clasificación +config.action.quit=Salir +config.action.quit.tip=Salir del editor de configuración +config.action.reset=Cancelar +config.action.reset.tip=Cancelar las modificaciones de esta categoría +config.action.save=Guardar +config.action.save.tip=Guardar las modificaciones de esta categoría +config.choice.cancel=Cancelar +config.choice.continue=Continuar +config.choice.doNotSave=No guardar +config.choice.save=Guardar +config.defaultValue=Valor por defecto +config.defaultValue.tip=Valor por defecto de la opción +config.description=Descripción +config.detected.callBack=Acciones detectadas para las opciones modificadas +config.error.category.already.exists=la categoría '%1$s' ya existe\! +config.error.category.not.found=La categoria '%1$s' no existe\! +config.key=Clave +config.key.tip=Calve de la opcion +config.launch.callBack=Lanzar +config.launch.callBack.tip=Lanzar las acciones necesarias +config.message.quit.invalid.category=La categoría '%1$s' no es valida\! +config.message.quit.valid.and.modified.category=La categoria '%1$s' tiene opciones modificadas \: +config.modified=Opción modificada (valor original \: %1$s) +config.no.option.selected=< No hay opciones seleccionadas > +config.option.final=Opción no modificable +config.option.label=Opción '%1$s' (%2$s) +config.option.modified=Valor modificado < valor anterior \: '%1$s' - nuevo valor \: '%2$s' > +config.title=Preferencias +config.title.need.confirm=Se requiere confirmación del usuario... +config.unmodifiable=No puede ser modificado +config.unvalid=Opción no valida (valor original \: %1$s, tipo requerido \: %2$s) +config.value=Valor +config.value.tip=Valor de la opción +errorUI.action.close=Cerrar +errorUI.message=ha habido un error \! +errorUI.title=Error... +fontsize.action.default.tip=Volver al tamaño por defecto +fontsize.action.down.tip=Disminuir el tamaño del origen +fontsize.action.up.tip=Aumentar el tamaño de la fuente +hidor.hideTip=Ocultar +hidor.showTip=Ver +i18neditor.empty.locales=< Aucune locale à sélectionner > +i18neditor.popup.title=Cambiar idioma +i18neditor.selected=Idioma usado actualmente \: %1$s +i18neditor.unselected=Para usar este idioma \: %1$s +listSelector.hideList=Ocultar la lista +listSelector.showList=Mostar la lista +memorywidget.memory=%d/%dMo +numbereditor..=. +numbereditor.0=0 +numbereditor.1=1 +numbereditor.2=2 +numbereditor.3=3 +numbereditor.4=4 +numbereditor.5=5 +numbereditor.6=6 +numbereditor.7=7 +numbereditor.8=8 +numbereditor.9=9 +numbereditor.action.reset.tip=Reinicializar +numbereditor.action.show.tip=Mostar el teclado numérico +numbereditor.clearAll=C +numbereditor.clearOne=CE +numbereditor.toggleSign=+/- +timeeditor.H=H diff --git a/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_fr_FR.properties b/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_fr_FR.properties new file mode 100644 index 0000000..1445e46 --- /dev/null +++ b/trunk/jaxx-widgets/src/main/resources/i18n/jaxx-widgets_fr_FR.properties @@ -0,0 +1,86 @@ +aboutframe.about=À propos +aboutframe.license=Licence +aboutframe.ok=OK +aboutframe.thirdparty=Tierce partie +bean.popup.label=Objet '%1$s' +bean.sort.down=Tri décroissant +bean.sort.down.tip=Tri décroissant actuellement utilisé +bean.sort.down.toSelect.tip=Cliquer pour trier selon l'ordre décroissant +bean.sort.label=Ordre de tri +bean.sort.off=Cliquer pour activer le tri sur la propriété '%1$s' +bean.sort.on=Le tri est effectué sur la propriété '%1$s' +bean.sort.up=Tri croissant +bean.sort.up.tip=Tri croissant actuellement utilisé +bean.sort.up.toSelect.tip=Cliquer pour trier selon l'ordre croissant +bean.unknown.type=Objet de type inconnu +beancombobox.action.reset.tip=Réinitialiser la valeur de la liste déroulante +beancombobox.action.sort.tip=Modifier le tri de la liste déroulante +beancombobox.popup.title=Modifier le tri +beanlist.action.reset.tip=Supprimer la sélection +beanlist.action.sort.tip=Modifier le tri de la liste déroulante +beanlist.popup.title=Modifier le tri +config.action.quit=Quitter +config.action.quit.tip=Quitter l'éditeur de configuration +config.action.reset=Annuler +config.action.reset.tip=Annuler les modifications de cette catégorie +config.action.save=Enregistrer +config.action.save.tip=Sauver les modifications de cette catégorie +config.choice.cancel=Annuler +config.choice.continue=Continuer +config.choice.doNotSave=Ne pas enregistrer +config.choice.save=Enregistrer +config.defaultValue=Valeur par défaut +config.defaultValue.tip=Valeur par défaut de l'option +config.description=Description +config.detected.callBack=Actions détectées pour les options modifiées +config.error.category.already.exists=La catégorie de nom '%1$s' existe déjà\! +config.error.category.not.found=La catégorie de nom '%1$s' n'existe pas\! +config.key=Clef +config.key.tip=Clef de l'option +config.launch.callBack=Lancer +config.launch.callBack.tip=Lancer les actions nécessaires +config.message.quit.invalid.category=La catégorie '%1$s' n'est pas valide\! +config.message.quit.valid.and.modified.category=La catégorie '%1$s' possèdent des options modifiées \: +config.modified=Option modifiée (valeur originale \: %1$s) +config.no.option.selected=< Pas d'option sélectionnée > +config.option.final=Option non modifiable +config.option.label=Option '%1$s' (%2$s) +config.option.modified=Valeur modifiée < ancienne valeur \: '%1$s' - nouvelle valeur \: '%2$s' > +config.title=Préférences +config.title.need.confirm=Une confirmation de votre part est requise... +config.unmodifiable=Ne peut pas être modifié +config.unvalid=Option non valide (valeur originale \: %1$s, type requis \: %2$s) +config.value=Valeur +config.value.tip=Valeur de l'option +errorUI.action.close=Fermer +errorUI.message=Une erreur est survenue \! +errorUI.title=Erreur... +fontsize.action.default.tip=Retour sur la taille par défaut +fontsize.action.down.tip=Diminuer la taille de la police +fontsize.action.up.tip=Augmenter la taille de la police +hidor.hideTip=Cacher +hidor.showTip=Voir +i18neditor.empty.locales=< Aucune locale à sélectionner > +i18neditor.popup.title=Changer de langue +i18neditor.selected=Langue actuellement utilisée \: %1$s +i18neditor.unselected=Pour utiliser cette langue \: %1$s +listSelector.hideList=Cacher la liste +listSelector.showList=Afficher la liste +memorywidget.memory=%d/%dMo +numbereditor..=. +numbereditor.0=0 +numbereditor.1=1 +numbereditor.2=2 +numbereditor.3=3 +numbereditor.4=4 +numbereditor.5=5 +numbereditor.6=6 +numbereditor.7=7 +numbereditor.8=8 +numbereditor.9=9 +numbereditor.action.reset.tip=Réinitialiser +numbereditor.action.show.tip=Afficher le pavé numérique +numbereditor.clearAll=C +numbereditor.clearOne=CE +numbereditor.toggleSign=+/- +timeeditor.H=H diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-add.png b/trunk/jaxx-widgets/src/main/resources/icons/action-add.png new file mode 100644 index 0000000..6332fef Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-add.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort-down.png b/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort-down.png new file mode 100644 index 0000000..e1d8816 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort-down.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort-up.png b/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort-up.png new file mode 100644 index 0000000..94fa577 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort-up.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort.png b/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort.png new file mode 100644 index 0000000..f86aafd Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-bean-sort.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-collapse.png b/trunk/jaxx-widgets/src/main/resources/icons/action-collapse.png new file mode 100644 index 0000000..f88a24a Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-collapse.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-combobox-reset.png b/trunk/jaxx-widgets/src/main/resources/icons/action-combobox-reset.png new file mode 100644 index 0000000..0fb00f9 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-combobox-reset.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-combobox-sort.png b/trunk/jaxx-widgets/src/main/resources/icons/action-combobox-sort.png new file mode 100644 index 0000000..188e1c1 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-combobox-sort.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-config-quit.png b/trunk/jaxx-widgets/src/main/resources/icons/action-config-quit.png new file mode 100644 index 0000000..2541d2b Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-config-quit.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-config-reset.png b/trunk/jaxx-widgets/src/main/resources/icons/action-config-reset.png new file mode 100644 index 0000000..c149c2b Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-config-reset.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-config-save.png b/trunk/jaxx-widgets/src/main/resources/icons/action-config-save.png new file mode 100644 index 0000000..41b3f43 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-config-save.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-expand.png b/trunk/jaxx-widgets/src/main/resources/icons/action-expand.png new file mode 100644 index 0000000..3c19e48 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-expand.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-font-size-down.png b/trunk/jaxx-widgets/src/main/resources/icons/action-font-size-down.png new file mode 100644 index 0000000..66e5e5f Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-font-size-down.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-font-size-up.png b/trunk/jaxx-widgets/src/main/resources/icons/action-font-size-up.png new file mode 100644 index 0000000..ac7160e Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-font-size-up.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-font-size.png b/trunk/jaxx-widgets/src/main/resources/icons/action-font-size.png new file mode 100644 index 0000000..ef125e9 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-font-size.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-be.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-be.png new file mode 100644 index 0000000..d86ebc8 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-be.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-ca.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-ca.png new file mode 100644 index 0000000..1f20419 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-ca.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-ch.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-ch.png new file mode 100644 index 0000000..242ec01 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-ch.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-de.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-de.png new file mode 100644 index 0000000..ac4a977 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-de.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-dk.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-dk.png new file mode 100644 index 0000000..e2993d3 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-dk.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-es.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-es.png new file mode 100644 index 0000000..c2de2d7 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-es.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-fi.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-fi.png new file mode 100644 index 0000000..14ec091 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-fi.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-fr.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-fr.png new file mode 100644 index 0000000..8332c4e Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-fr.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-gb.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-gb.png new file mode 100644 index 0000000..ff701e1 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-gb.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-it.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-it.png new file mode 100644 index 0000000..89692f7 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-it.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-nl.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-nl.png new file mode 100644 index 0000000..fe44791 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-nl.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-no.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-no.png new file mode 100644 index 0000000..160b6b5 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-no.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-se.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-se.png new file mode 100644 index 0000000..1994653 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-se.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-us.png b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-us.png new file mode 100644 index 0000000..10f451f Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-i18n-us.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-calculator.png b/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-calculator.png new file mode 100644 index 0000000..701a60a Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-calculator.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-reset.png b/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-reset.png new file mode 100644 index 0000000..0fb00f9 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-reset.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-validate.png b/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-validate.png new file mode 100644 index 0000000..a9925a0 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-numbereditor-validate.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-open.png b/trunk/jaxx-widgets/src/main/resources/icons/action-open.png new file mode 100755 index 0000000..e9c4476 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-open.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-remove.png b/trunk/jaxx-widgets/src/main/resources/icons/action-remove.png new file mode 100644 index 0000000..08f2493 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-remove.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-select.png b/trunk/jaxx-widgets/src/main/resources/icons/action-select.png new file mode 100644 index 0000000..6332fef Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-select.png differ diff --git a/trunk/jaxx-widgets/src/main/resources/icons/action-unselect.png b/trunk/jaxx-widgets/src/main/resources/icons/action-unselect.png new file mode 100644 index 0000000..08f2493 Binary files /dev/null and b/trunk/jaxx-widgets/src/main/resources/icons/action-unselect.png differ diff --git a/trunk/jaxx-widgets/src/site/rst/index.rst b/trunk/jaxx-widgets/src/site/rst/index.rst new file mode 100644 index 0000000..15a5a3a --- /dev/null +++ b/trunk/jaxx-widgets/src/site/rst/index.rst @@ -0,0 +1,52 @@ +.. - +.. * #%L +.. * JAXX :: Widgets +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============ +JAXX Widgets +============ + +The module of rich widgets for swing designed in jaxx. + + +Editors +======= + +TODO Explain editors + +Screen shot +----------- + +TODO + +Widgets +======= + +TODO Explain widgets + + +Screen shot +----------- + +TODO diff --git a/trunk/jaxx-widgets/src/site/site_fr.xml b/trunk/jaxx-widgets/src/site/site_fr.xml new file mode 100644 index 0000000..a3df85b --- /dev/null +++ b/trunk/jaxx-widgets/src/site/site_fr.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX :: Widgets + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <src>http://maven-site.chorem.org/public/images/logos/jaxx-logo.png</src> + <href>index.html</href> + </bannerLeft> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="index.html"/> + </breadcrumbs> + + <menu ref="parent"/> + + <menu name="Utilisateur"/> + + <menu ref="reports"/> + + <menu ref="modules"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> diff --git a/trunk/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/config/model/ConfigUIModelBuilderTest.java b/trunk/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/config/model/ConfigUIModelBuilderTest.java new file mode 100644 index 0000000..069af5b --- /dev/null +++ b/trunk/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/config/model/ConfigUIModelBuilderTest.java @@ -0,0 +1,298 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ +package jaxx.runtime.swing.editor.config.model; + +import jaxx.runtime.SwingUtil; +import jaxx.runtime.swing.editor.MyDefaultCellEditor; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.swing.*; +import javax.swing.table.TableCellEditor; + +/** + * Created: 22 déc. 2009 + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class ConfigUIModelBuilderTest { + + ConfigUIModelBuilder builder; + + static MyConfig config; + + @BeforeClass + public static void beforeeClass() { + config = new MyConfig(); + } + + + @Before + public void setup() { + builder = new ConfigUIModelBuilder(); + } + + @Test(expected = NullPointerException.class) + public void testCreateModelLimitCase0() throws Exception { + builder.createModel(null); + } + + @Test(expected = IllegalStateException.class) + public void testFlushModelLimitCase0() throws Exception { + builder.flushModel(); + } + + @Test + public void testCreateModel() throws Exception { + builder.createModel(config); + ConfigUIModel configModel = builder.flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNotNull(configModel.getConfig()); + } + + @Test(expected = IllegalStateException.class) + public void testRegisterCallbackLimitCase() throws Exception { + builder.registerCallBack(null, null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase0() throws Exception { + builder.createModel(config); + builder.registerCallBack(null, null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase1() throws Exception { + builder.createModel(config); + builder.registerCallBack("yo", null, null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase2() throws Exception { + builder.createModel(config); + builder.registerCallBack("yo", "yo description", null, null); + } + + @Test(expected = NullPointerException.class) + public void testRegisterCallbackLimitCase4() throws Exception { + builder.createModel(config); + Runnable callback = new Runnable() { + + @Override + public void run() { + } + }; + builder.registerCallBack("yo", "yo description", null, callback); + } + + @Test + public void testRegisterCallback() throws Exception { + builder.createModel(config); + Runnable callback = new Runnable() { + + @Override + public void run() { + } + }; + ImageIcon icon = SwingUtil.createActionIcon("add"); + builder.registerCallBack("yo","yo description", icon, callback); + ConfigUIModel configModel = builder.flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNotNull(configModel.getConfig()); + CallBackEntry callBackEntry = + configModel.getCallBacksManager().getCallBack("yo"); + Assert.assertNotNull(callBackEntry ); + + Assert.assertEquals(callback, callBackEntry.getAction()); + } + + @Test(expected = IllegalStateException.class) + public void testAddCategoryLimitCase0() throws Exception { + builder.addCategory(null, null); + } + + @Test(expected = NullPointerException.class) + public void testAddCategoryLimitCase1() throws Exception { + builder.createModel(config); + builder.addCategory(null, null); + } + + @Test(expected = NullPointerException.class) + public void testAddCategoryLimitCase2() throws Exception { + builder.createModel(config); + builder.addCategory("", null); + } + + @Test + public void testAddCategory() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + CategoryModel categoryModel = builder.flushCategory(); + Assert.assertNotNull(categoryModel); + Assert.assertEquals("cat0", categoryModel.category); + Assert.assertEquals("cat0 label", categoryModel.categoryLabel); + Assert.assertEquals(0, categoryModel.entries.size()); + + } + + @Test(expected = IllegalStateException.class) + public void testAddOptionLimitCase0() throws Exception { + builder.addOption(null); + } + + @Test(expected = IllegalStateException.class) + public void testAddOptionLimitCase1() throws Exception { + builder.createModel(config); + builder.addOption(null); + } + + @Test(expected = NullPointerException.class) + public void testAddOptionLimitCase2() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.addOption(null); + } + + @Test + public void testAddOption() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.addOption(MyConfig.Option.LOCALE); + OptionModel optionModel = builder.flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyConfig.Option.LOCALE, optionModel.def); + + CategoryModel categoryModel = builder.flushCategory(); + Assert.assertNotNull(categoryModel); + Assert.assertEquals("cat0", categoryModel.category); + Assert.assertEquals("cat0 label", categoryModel.categoryLabel); + Assert.assertEquals(1, categoryModel.entries.size()); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase0() throws Exception { + builder.setOptionPropertyName(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase1() throws Exception { + builder.createModel(config); + builder.setOptionPropertyName(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionPropertyNameLimitCase2() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.setOptionPropertyName(null); + } + + @Test(expected = NullPointerException.class) + public void testSetOptionPropertyNameLimitCase3() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.addOption(MyConfig.Option.LOCALE); + builder.setOptionPropertyName(null); + } + + @Test + public void testSetOptionPropertyName() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.addOption(MyConfig.Option.LOCALE); + builder.setOptionPropertyName(MyConfig.PROPERTY_LOCALE); + OptionModel optionModel = builder.flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyConfig.Option.LOCALE, optionModel.def); + Assert.assertEquals(MyConfig.PROPERTY_LOCALE, optionModel.propertyName); + Assert.assertNull(optionModel.editor); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase0() throws Exception { + builder.setOptionEditor(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase1() throws Exception { + builder.createModel(config); + builder.setOptionEditor(null); + } + + @Test(expected = IllegalStateException.class) + public void testSetOptionEditorLimitCase2() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.setOptionEditor(null); + } + + + @Test(expected = NullPointerException.class) + public void testSetOptionEditorLimitCase3() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.addOption(MyConfig.Option.LOCALE); + builder.setOptionEditor(null); + } + + @Test + public void testSetOptionEditor() throws Exception { + builder.createModel(config); + builder.addCategory("cat0", "cat0 label"); + builder.addOption(MyConfig.Option.LOCALE); + TableCellEditor cellEditor = MyDefaultCellEditor.newBooleanEditor(); + builder.setOptionEditor(cellEditor); + OptionModel optionModel = builder.flushOption(); + Assert.assertNotNull(optionModel); + Assert.assertEquals(MyConfig.Option.LOCALE, optionModel.def); + Assert.assertNull(optionModel.propertyName); + Assert.assertEquals(cellEditor, optionModel.editor); + } + + @Test + public void testFlushModel() throws Exception { + builder.createModel(config); + ConfigUIModel configModel = builder.flushModel(); + Assert.assertNotNull(configModel); + Assert.assertNull(builder.model); + } + + @Test + public void testSetModel() throws Exception { + + } + + @Test + public void testSetCategory() throws Exception { + } + + @Test + public void testSetOption() throws Exception { + } + +} diff --git a/trunk/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/config/model/MyConfig.java b/trunk/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/config/model/MyConfig.java new file mode 100644 index 0000000..9fc1aee --- /dev/null +++ b/trunk/jaxx-widgets/src/test/java/jaxx/runtime/swing/editor/config/model/MyConfig.java @@ -0,0 +1,241 @@ +/* + * #%L + * JAXX :: Widgets + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2008 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package jaxx.runtime.swing.editor.config.model; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.ApplicationConfig; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Date; +import java.util.Locale; + +import static org.nuiton.i18n.I18n._; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 2.0.0 + */ +public class MyConfig extends ApplicationConfig { + + /** Logger */ + static private Log log = LogFactory.getLog(MyConfig.class); + + public static final String PROPERTY_FULLSCREEN = "fullscreen"; + + public static final String PROPERTY_LOCALE = "locale"; + + public static final String PROPERTY_FONT_SIZE = "fontSize"; + + public static final String PROPERTY_ADJUSTING = "adjusting"; + + /** + * un drapeau pour bloquer la sauvegarde lors de la modification en masse des options + * via les setter. + */ + protected boolean adjusting; + + protected final PropertyChangeListener saveAction = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (adjusting) { + if (log.isDebugEnabled()) { + log.debug("skip save while adjusting"); + } + return; + } + if (log.isDebugEnabled()) { + log.debug("Saving configuration at " + new Date()); + } + saveForUser(); + } + }; + + @Override + public void saveForUser(String... excludeKeys) { + // never save anything :) + } + + public MyConfig() { + + setConfigFileName(Option.CONFIG_FILE.defaultValue); + + // chargement de la configuration interne + + for (Option o : Option.values()) { + setDefaultOption(o.key, o.defaultValue); + } + + adjusting = true; + addPropertyChangeListener(PROPERTY_FULLSCREEN, saveAction); + addPropertyChangeListener(PROPERTY_FONT_SIZE, saveAction); + addPropertyChangeListener(PROPERTY_LOCALE, saveAction); + adjusting = false; + } + + @Override + public void setOption(String key, String value) { + if (key.equals(PROPERTY_ADJUSTING)) { + setAdjusting(Boolean.valueOf(value)); + return; + } + super.setOption(key, value); + } + + + public boolean isFullScreen() { + Boolean result = getOptionAsBoolean(Option.FULL_SCREEN.key); + return result != null && result; + } + + public Locale getLocale() { + Locale result = getOption(Locale.class, Option.LOCALE.key); + return result; + } + + public Float getFontSize() { + Float result = getOption(Float.class, Option.FONT_SIZE.key); + return result; + } + + public void setFullscreen(boolean fullscreen) { + Object oldValue = null; + setOption(Option.FULL_SCREEN.key, fullscreen + ""); + firePropertyChange(PROPERTY_FULLSCREEN, oldValue, fullscreen); + } + + public void setLocale(Locale newLocale) { + setOption(Option.LOCALE.key, newLocale.toString()); + firePropertyChange(PROPERTY_LOCALE, null, newLocale); + } + + public void setFontSize(Float newFontSize) { + Float oldValue = getFontSize(); + if (log.isDebugEnabled()) { + log.debug("changing font-size to " + newFontSize); + } + setOption(Option.FONT_SIZE.key, newFontSize.toString()); + firePropertyChange(PROPERTY_FONT_SIZE, oldValue, newFontSize); + } + + public boolean isAdjusting() { + return adjusting; + } + + public void setAdjusting(boolean adjusting) { + if (log.isDebugEnabled()) { + log.debug("changing adjusting to " + adjusting); + } + boolean oldValue = this.adjusting; + this.adjusting = adjusting; + firePropertyChange(PROPERTY_ADJUSTING, oldValue, adjusting); + } + + ////////////////////////////////////////////////// + // Toutes les options disponibles + ////////////////////////////////////////////////// + + public enum Option implements OptionDef { + + CONFIG_FILE(CONFIG_FILE_NAME, _("jaxxdemo.config.configFileName.description"), "jaxxdemo", String.class, true, true), + FULL_SCREEN("ui.fullscreen", _("jaxxdemo.config.ui.fullscreen"), "false", Boolean.class, false, false), + LOCALE("ui." + PROPERTY_LOCALE, _("jaxxdemo.config.ui." + PROPERTY_LOCALE), Locale.FRANCE.toString(), Locale.class, false, false), + FONT_SIZE("ui." + PROPERTY_FONT_SIZE, _("jaxxdemo.config.ui." + PROPERTY_FONT_SIZE), "10f", Float.class, false, false); + + public final String key; + + public final String description; + + public String defaultValue; + + public final Class<?> type; + + public boolean _transient; + + public boolean _final; + + Option(String key, + String description, + String defaultValue, + Class<?> type, + boolean _transient, + boolean _final) { + this.key = key; + this.description = description; + this.defaultValue = defaultValue; + this.type = type; + this._final = _final; + this._transient = _transient; + } + + @Override + public boolean isFinal() { + return _final; + } + + @Override + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public void setTransient(boolean _transient) { + this._transient = _transient; + } + + @Override + public void setFinal(boolean _final) { + this._final = _final; + } + + @Override + public boolean isTransient() { + return _transient; + } + + @Override + public String getDefaultValue() { + return defaultValue; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getKey() { + return key; + } + + @Override + public Class<?> getType() { + return type; + } + } +} diff --git a/trunk/jaxx-widgets/src/test/resources/log4j.properties b/trunk/jaxx-widgets/src/test/resources/log4j.properties new file mode 100644 index 0000000..114301b --- /dev/null +++ b/trunk/jaxx-widgets/src/test/resources/log4j.properties @@ -0,0 +1,34 @@ +### +# #%L +# JAXX :: Widgets +# +# $Id$ +# $HeadURL$ +# %% +# Copyright (C) 2008 - 2010 CodeLutin +# %% +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +# +# You should have received a copy of the GNU General Lesser Public +# License along with this program. If not, see +# <http://www.gnu.org/licenses/lgpl-3.0.html>. +# #L% +### +# 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.swing=INFO +#log4j.logger.jaxx.runtime.swing.editor.config.model.ConfigUIModelBuilder=DEBUG +log4j.logger.org.nuiton=WARN diff --git a/trunk/pom.xml b/trunk/pom.xml new file mode 100644 index 0000000..33544a9 --- /dev/null +++ b/trunk/pom.xml @@ -0,0 +1,645 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> +<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/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>mavenpom4redmineAndCentral</artifactId> + <version>3.3.4</version> + </parent> + + <artifactId>jaxx</artifactId> + <version>2.5.2</version> + + <modules> + <module>jaxx-runtime</module> + <module>jaxx-validator</module> + <module>jaxx-compiler</module> + <module>jaxx-maven-plugin</module> + <module>jaxx-widgets</module> + </modules> + + <developers> + + <developer> + <name>Tony Chemit</name> + <id>tchemit</id> + <email>chemit at codelutin dot com</email> + <organization>CodeLutin</organization> + <timezone>+2</timezone> + <roles> + <role>Developer</role> + </roles> + </developer> + + <developer> + <name>Sylvain Letellier</name> + <id>sletellier</id> + <email>letellier at codelutin dot com</email> + <organization>CodeLutin</organization> + <timezone>+2</timezone> + <roles> + <role>Developer</role> + </roles> + </developer> + + <developer> + <name>Jean Couteau</name> + <id>jcouteau</id> + <email>couteau at codelutin dot com</email> + <organization>CodeLutin</organization> + <timezone>+2</timezone> + <roles> + <role>Technical Writer</role> + </roles> + </developer> + + <developer> + <name>Yannick Martel</name> + <id>ymartel</id> + <email>martel at codelutin dot com</email> + <organization>CodeLutin</organization> + <timezone>+2</timezone> + <roles> + <role>Developer</role> + </roles> + </developer> + </developers> + + + <name>JAXX</name> + <description>JAXX Project</description> + <inceptionYear>2008</inceptionYear> + <url>http://maven-site.nuiton.org/jaxx</url> + + <packaging>pom</packaging> + + <properties> + + <!-- pour un muli module on doit fixer le projectId --> + <projectId>jaxx</projectId> + <nuitonUtilsVersion>2.5.1</nuitonUtilsVersion> + <nuitonI18nVersion>2.4.1</nuitonI18nVersion> + <eugeneVersion>2.4.2</eugeneVersion> + <xworkVersion>2.3.1.2</xworkVersion> + <jxLayerVersion>3.0.4</jxLayerVersion> + <javaHelpVersion>2.0.05</javaHelpVersion> + <swingXVersion>1.6.3</swingXVersion> + + <!-- i18n configuration --> + <i18n.bundles>fr_FR,en_GB,es_ES</i18n.bundles> + + <site.verbose>true</site.verbose> + <!-- FIXME-tchemit-2012-07-02 Still not working, normalize all rst docs --> + <!--pdfGenerationEnabled>true</pdfGenerationEnabled--> + </properties> + + + <!-- Source control management. --> + <scm> + <connection>scm:svn:http://svn.nuiton.org/svn/jaxx/tags/jaxx-2.5.2</connection> + <developerConnection> + scm:svn:http://svn.nuiton.org/svn/jaxx/tags/jaxx-2.5.2 + </developerConnection> + <url>http://www.nuiton.org/repositories/browse/jaxx/tags/jaxx-2.5.2</url> + </scm> + + <distributionManagement> + <site> + <id>${platform}</id> + <url>${our.site.repository}/${projectId}</url> + </site> + </distributionManagement> + + <dependencyManagement> + <dependencies> + + <!-- lutin dependencies --> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-utils</artifactId> + <version>${nuitonUtilsVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + <version>${nuitonUtilsVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.i18n</groupId> + <artifactId>nuiton-i18n</artifactId> + <version>${nuitonI18nVersion}</version> + </dependency> + + <dependency> + <groupId>org.nuiton.eugene</groupId> + <artifactId>eugene</artifactId> + <version>${eugeneVersion}</version> + <exclusions> + <exclusion> + <groupId>jaxen</groupId> + <artifactId>jaxen</artifactId> + </exclusion> + <exclusion> + <groupId>net.sourceforge.saxon</groupId> + <artifactId>saxon</artifactId> + </exclusion> + <exclusion> + <groupId>xerces</groupId> + <artifactId>xercesImpl</artifactId> + </exclusion> + <exclusion> + <groupId>xml-apis</groupId> + <artifactId>xml-apis</artifactId> + </exclusion> + <exclusion> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </exclusion> + <exclusion> + <groupId>commons-digester</groupId> + <artifactId>commons-digester</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>helper-maven-plugin</artifactId> + <version>${helperPluginVersion}</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven</groupId> + <artifactId>maven-artifact-manager</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-dependency-tree</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven</groupId> + <artifactId>maven-model</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven</groupId> + <artifactId>maven-profile</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven</groupId> + <artifactId>maven-settings</artifactId> + </exclusion> + <exclusion> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + </exclusion> + + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-simple</artifactId> + </exclusion> + + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-api</artifactId> + </exclusion> + + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-javamail</artifactId> + </exclusion> + + <exclusion> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + </exclusion> + + <exclusion> + <groupId>org.sonatype.plexus</groupId> + <artifactId>plexus-cipher</artifactId> + </exclusion> + + <exclusion> + <groupId>org.sonatype.plexus</groupId> + <artifactId>plexus-sec-dispatcher</artifactId> + </exclusion> + + </exclusions> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>helper-maven-plugin</artifactId> + <version>${helperPluginVersion}</version> + <scope>test</scope> + <classifier>tests</classifier> + <exclusions> + + <exclusion> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-dependency-tree</artifactId> + </exclusion> + + <exclusion> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + </exclusion> + + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-simple</artifactId> + </exclusion> + + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-api</artifactId> + </exclusion> + + <exclusion> + <groupId>plexus</groupId> + <artifactId>plexus-mail-sender-javamail</artifactId> + </exclusion> + + <exclusion> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + </exclusion> + + <exclusion> + <groupId>org.sonatype.plexus</groupId> + <artifactId>plexus-cipher</artifactId> + </exclusion> + + <exclusion> + <groupId>org.sonatype.plexus</groupId> + <artifactId>plexus-sec-dispatcher</artifactId> + </exclusion> + + </exclusions> + </dependency> + + <!-- sun dependencies --> + + <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>${javaHelpVersion}</version> + </dependency> + + <!-- maven dependencies --> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>${mavenVersion}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>${mavenVersion}</version> + <scope>provided</scope> + </dependency> + + <!-- rsyntaxtextarea dependency --> + <dependency> + <groupId>com.fifesoft</groupId> + <artifactId>rsyntaxtextarea</artifactId> + <version>1.5.0</version> + </dependency> + + <!-- swinglabs dependencies --> + + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>jxlayer</artifactId> + <version>${jxLayerVersion}</version> + </dependency> + + <dependency> + <groupId>org.swinglabs.swingx</groupId> + <artifactId>swingx-core</artifactId> + <version>${swingXVersion}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-velocity</artifactId> + <version>1.1.8</version> + <exclusions> + <exclusion> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-container-default</artifactId> + </exclusion> + <exclusion> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-component-api</artifactId> + </exclusion> + <exclusion> + <groupId>velocity</groupId> + <artifactId>velocity</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- dependencies to mojo annotations --> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <version>${pluginPluginVersion}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven.shared</groupId> + <artifactId>maven-verifier</artifactId> + <version>1.3</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven.plugin-testing</groupId> + <artifactId>maven-plugin-testing-harness</artifactId> + <version>1.2</version> + <scope>test</scope> + <exclusions> + + <exclusion> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-archiver</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-http-lightweight</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-file</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-ssh</artifactId> + </exclusion> + + <exclusion> + <groupId>org.apache.maven.reporting</groupId> + <artifactId>maven-reporting-api</artifactId> + </exclusion> + + </exclusions> + </dependency> + + <!-- FIXME si on ne le rajoute pas, on se retrouve avec la version 1.1 qui ne convient pas --> + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + <version>3.0.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + <version>${nuitonUtilsVersion}</version> + <scope>test</scope> + <classifier>tests</classifier> + </dependency> + + </dependencies> + </dependencyManagement> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <build> + + <pluginManagement> + <plugins> + + <!-- plugin i18n --> + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <version>${nuitonI18nVersion}</version> + </plugin> + + <plugin> + <artifactId>maven-site-plugin</artifactId> + <dependencies> + <dependency> + <groupId>org.nuiton.jrst</groupId> + <artifactId>doxia-module-jrst</artifactId> + <version>${jrstPluginVersion}</version> + </dependency> + </dependencies> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>webstart-maven-plugin</artifactId> + <version>${webstartPluginVersion}</version> + <configuration> + + <libPath>lib</libPath> + <makeArchive>false</makeArchive> + <verbose>false</verbose> + <canUnsign>false</canUnsign> + <jnlp> + <mainClass>${maven.jar.main.class}</mainClass> + <allPermissions>true</allPermissions> + <offlineAllowed>true</offlineAllowed> + </jnlp> + <sign> + <keystore>${keystorepath}</keystore> + <storepass>${keystorepass}</storepass> + <alias>${keyalias}</alias> + <keypass>${keypass}</keypass> + <verify>true</verify> + <keystoreConfig> + <delete>false</delete> + <gen>false</gen> + </keystoreConfig> + </sign> + <gzip>true</gzip> + <unsign>true</unsign> + <canUnsign>false</canUnsign> + <!--Can't use pack2000 since there is some already signed jar--> + <!--<pack200>true</pack200>--> + <jnlpExtensions> + <!--jnlpExtension> + <name>sun</name> + <title>Sun MicroSystems</title> + <vendor>Sun MicroSystems, Inc.</vendor> + <includes> + <include>javax.help:javahelp</include> + </includes> + </jnlpExtension--> + <jnlpExtension> + <name>jxlayer</name> + <title>Swing labs JXLayer</title> + <vendor>Swing Labs</vendor> + <includes> + <include>org.swinglabs:jxlayer</include> + </includes> + </jnlpExtension> + </jnlpExtensions> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-release-plugin</artifactId> + <configuration> + <prepareVerifyArgs>-Ptutorial,demo</prepareVerifyArgs> + </configuration> + </plugin> + + </plugins> + </pluginManagement> + + </build> + + <reporting> + <excludeDefaults>true</excludeDefaults> + </reporting> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + + <profiles> + + <!-- build jaxx-demo project --> + <profile> + <id>demo</id> + <modules> + <module>jaxx-demo</module> + </modules> + + </profile> + + <!-- This profile is here just to make more automatic release. + This profile will be use to do a releasse:prepare, this modules are not + in default build but need to be release + --> + <profile> + <id>extra-modules</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + <modules> + <module>jaxx-demo</module> + </modules> + + </profile> + + <!-- reporting at release time --> + <profile> + <id>reporting</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + + <reporting> + <plugins> + + <plugin> + <artifactId>maven-plugin-plugin</artifactId> + <version>${pluginPluginVersion}</version> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>cobertura-maven-plugin</artifactId> + <version>${coberturaPluginVersion}</version> + </plugin> + + <plugin> + <artifactId>maven-project-info-reports-plugin</artifactId> + <version>${projectInfoReportsPluginVersion}</version> + <reportSets> + <reportSet> + <reports> + <report>project-team</report> + <report>mailing-list</report> + <report>cim</report> + <report>issue-tracking</report> + <report>license</report> + <report>scm</report> + <report>dependencies</report> + <report>dependency-convergence</report> + <report>plugin-management</report> + <report>plugins</report> + <report>dependency-management</report> + <report>summary</report> + </reports> + </reportSet> + </reportSets> + </plugin> + </plugins> + </reporting> + </profile> + + </profiles> + +</project> diff --git a/trunk/src/site/resources/demo1.png b/trunk/src/site/resources/demo1.png new file mode 100644 index 0000000..16bc6c1 Binary files /dev/null and b/trunk/src/site/resources/demo1.png differ diff --git a/trunk/src/site/resources/demo2.png b/trunk/src/site/resources/demo2.png new file mode 100644 index 0000000..a415acb Binary files /dev/null and b/trunk/src/site/resources/demo2.png differ diff --git a/trunk/src/site/resources/jaxx.png b/trunk/src/site/resources/jaxx.png new file mode 100644 index 0000000..c3d68c9 Binary files /dev/null and b/trunk/src/site/resources/jaxx.png differ diff --git a/trunk/src/site/resources/tutos/alwaysEnabledButton.png b/trunk/src/site/resources/tutos/alwaysEnabledButton.png new file mode 100644 index 0000000..5591d90 Binary files /dev/null and b/trunk/src/site/resources/tutos/alwaysEnabledButton.png differ diff --git a/trunk/src/site/resources/tutos/disabledButton.png b/trunk/src/site/resources/tutos/disabledButton.png new file mode 100644 index 0000000..28dcbef Binary files /dev/null and b/trunk/src/site/resources/tutos/disabledButton.png differ diff --git a/trunk/src/site/resources/tutos/enabledButton.png b/trunk/src/site/resources/tutos/enabledButton.png new file mode 100644 index 0000000..25f488b Binary files /dev/null and b/trunk/src/site/resources/tutos/enabledButton.png differ diff --git a/trunk/src/site/resources/tutos/helloworld.png b/trunk/src/site/resources/tutos/helloworld.png new file mode 100644 index 0000000..48ee3a8 Binary files /dev/null and b/trunk/src/site/resources/tutos/helloworld.png differ diff --git a/trunk/src/site/resources/tutos/helloworld2-red-big-button.png b/trunk/src/site/resources/tutos/helloworld2-red-big-button.png new file mode 100644 index 0000000..fe4ae1b Binary files /dev/null and b/trunk/src/site/resources/tutos/helloworld2-red-big-button.png differ diff --git a/trunk/src/site/resources/tutos/helloworld2-red-big.png b/trunk/src/site/resources/tutos/helloworld2-red-big.png new file mode 100644 index 0000000..1d032e2 Binary files /dev/null and b/trunk/src/site/resources/tutos/helloworld2-red-big.png differ diff --git a/trunk/src/site/resources/tutos/helloworld2-red.png b/trunk/src/site/resources/tutos/helloworld2-red.png new file mode 100644 index 0000000..b59beef Binary files /dev/null and b/trunk/src/site/resources/tutos/helloworld2-red.png differ diff --git a/trunk/src/site/resources/tutos/sliderAfter100.png b/trunk/src/site/resources/tutos/sliderAfter100.png new file mode 100644 index 0000000..4853d97 Binary files /dev/null and b/trunk/src/site/resources/tutos/sliderAfter100.png differ diff --git a/trunk/src/site/resources/tutos/sliderBefore100.png b/trunk/src/site/resources/tutos/sliderBefore100.png new file mode 100644 index 0000000..a0b8853 Binary files /dev/null and b/trunk/src/site/resources/tutos/sliderBefore100.png differ diff --git a/trunk/src/site/resources/tutos/webstart.gif b/trunk/src/site/resources/tutos/webstart.gif new file mode 100644 index 0000000..079fc1b Binary files /dev/null and b/trunk/src/site/resources/tutos/webstart.gif differ diff --git a/trunk/src/site/rst/BeanValidator.rst b/trunk/src/site/rst/BeanValidator.rst new file mode 100644 index 0000000..2cff03e --- /dev/null +++ b/trunk/src/site/rst/BeanValidator.rst @@ -0,0 +1,177 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +----------------- +Api de validation +----------------- + +.. contents:: + + +**WARNING : documentation non à jour...** + +Présentation +============ + +Ajout du support de validation dans JAXX. + +On se base depuis la version 2.3 sur l'api de **nuiton-validator**. + +Voir la documentation de **nuiton-validator**. + +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.swing.SwingValidatorErrorListModel*. 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.swing.ui.AbstractBeanValidatorUI*. Si non présent, on utilise par défaut le render *jaxx.runtime.validator.swing.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.swing.SwingValidator +************************************************** + +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.swing.SwingValidatorErrorModel +************************************************************ + +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.swing.SwingValidatorErrorListModel +**************************************************************** + +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.swing.SwingValidatorErrorListMouseListener +************************************************************************ + +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.JAXXUtil.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*). + + + + diff --git a/trunk/src/site/rst/Core.rst b/trunk/src/site/rst/Core.rst new file mode 100644 index 0000000..9acfa03 --- /dev/null +++ b/trunk/src/site/rst/Core.rst @@ -0,0 +1,180 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +++++ +Core +++++ + +.. contents:: + + +Nouvelles fonctionnalités apportées sur les classes générées. + +--------- +Interface +--------- + +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*. + +-------- +Abstract +-------- + +Présentation +============ + +Ajout de la possibilité de générer des classes abstraites. + +Mécanisme +========= + +Ajout d'un attribut *abstract*. + +:: + + <JPanel abstract='true'/> + +La classe générée sera abstraite. + +-------- +Generics +-------- + +Présentation +============ + +Ajout de possible de type generique sur les inferfaces et superclass. + +Mécanisme +========= + +Ajout d'un attribut genericType et superGenericType. + +Exemple : (fichier Parent.jaxx) +:: + + <JPanel genericType='E' + implements='java.lang.Comparable<E>' + abstract='true' /> + +La classe générée sera de la forme : + +:: + + public abstract Parent<E> implements java.lang.Comparable<E> { + ... + } + +Pour surcharger une telle classe (fichier Son.jaxx) : + +:: + + <Parent superGenericType='String' + abstract='true'/> + +La classe générée sera de la forme : + +:: + + public Son extends Parent<String> { + ... + } + + +TODO +==== + +Permettre l'utilisation des types génériques dans les scripts. + +-------- +JavaBean +-------- + +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' javaBean='true'/> + <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é. + +Note: le contenu de l'attribut *javaBean* est l'initialiteur de la propriété. diff --git a/trunk/src/site/rst/I18n.rst b/trunk/src/site/rst/I18n.rst new file mode 100644 index 0000000..5cbd529 --- /dev/null +++ b/trunk/src/site/rst/I18n.rst @@ -0,0 +1,115 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +==================== +Internationalisation +==================== + +.. contents:: + + +Présentation +============ + +L'internationalisation est présente par défaut dans JAXX et utilise la librairie +`Nuiton-I18n`_ + +.. _Nuiton-I18n: http://maven-site.nuiton.org/i18n/ + +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). Pour la désactiver, il suffit de +rajouter *<i18nable>false</i18nable>* dans la configuration du plugin. + + +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.nuiton.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. + +Exemple +======= + +Si on prend l'exemple suivant, on a une JFrame avec le titre myKey :: + + <JFrame id='mainFrame' + width='800' + height='800' + title='myKey'/> + +Maintenant, si on configure le plugin i18n de la manière suivante (pour plus +d'information sur le plugin i18n, reportez vous à la `documentation ad-hoc`_ ):: + + <plugin> + <groupId>org.nuiton.i18n</groupId> + <artifactId>maven-i18n-plugin</artifactId> + <configuration> + <entries> + <entry> + <basedir>${maven.gen.dir}/java</basedir> + </entry> + </entries> + </configuration> + <executions> + <execution> + <goals> + <goal>parserJava</goal> + <goal>bundle</goal> + </goals> + </execution> + </executions> + </plugin> + +On peut changer le titre de la +JFrame depuis le fichier de traduction en changeant la valeur pour la clé myKey. + +.. _documentation ad-hoc: http://maven-site.nuiton.org/i18n/ + + +Pourquoi ne plus utiliser l'ancien parserJaxx du plugin i18n ? +============================================================== + +Le *parserJaxx* du plugin i18n avait besoin des appels explicites à la méthode +de traduction et de par sa conception n'était pas capable de détecter les +nouvelles clés à traduire. Il faut lui préférer l'utilisation du *parserJava* +qui se sert du code Java généré pour travailler avec les traductions. diff --git a/trunk/src/site/rst/JAXXContext.rst b/trunk/src/site/rst/JAXXContext.rst new file mode 100644 index 0000000..731b784 --- /dev/null +++ b/trunk/src/site/rst/JAXXContext.rst @@ -0,0 +1,186 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +----------- +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.context.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ée 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.context.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. + diff --git a/trunk/src/site/rst/JAXXFile.rst b/trunk/src/site/rst/JAXXFile.rst new file mode 100644 index 0000000..2dc013c --- /dev/null +++ b/trunk/src/site/rst/JAXXFile.rst @@ -0,0 +1,49 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============================== +Qu'est-ce qu'un fichier JAXX ? +============================== + +Un fichier JAXX est un fichier XML. Le tag racine de votre fichier JAXX est le +composant qui va être généré. Par exemple, un fichier myJaxxComponent.jaxx comme +ceci:: + + <JPanel id='myPanelId'> + </JPanel> + +Ce code va générer une classe myJaxxComponent.java qui étends JPanel et +implémente JAXXObject. + +Maintenant, si on souhaite ajouter des composants à l'intérieur de ce panel, +il suffit de rajouter un fils à l'élément JPanel :: + + <JPanel id='myPanelId'> + <JButton id='myButton'/> + </JPanel> + +Ce code va générer un JPanel qui contient un JButton nommé myButton. On peut +maintenant jouer avec l'arborescence de notre fichier JAXX pour créer simplement +des interfaces complexes. \ No newline at end of file diff --git a/trunk/src/site/rst/NavigationModel.rst b/trunk/src/site/rst/NavigationModel.rst new file mode 100644 index 0000000..abc1e36 --- /dev/null +++ b/trunk/src/site/rst/NavigationModel.rst @@ -0,0 +1,296 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +^^^^^^^^^^^^^^^ +NavigationModel +^^^^^^^^^^^^^^^ + +.. contents:: + + +**WARNING : certaines parties de la documentation ne sont pas à jour...** + +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.NavigationModel +============================================= + +Contrat representant le model de l'arbre de navigation. + +Les noeuds présents dans se modèle sont aussi typés en +*jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode*. + +L'idée principale est de pouvoir associer à 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. + +Tout les models suivants implémantent cette interface. + +jaxx.runtime.swing.navigation.tree.NavigationTreeModel +====================================================== + +Il s'agit du modèle de l'arbre utilisé, c'est une extension d'un +*javax.swing.tree.DefaultTreeModel*. + +jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModel +================================================================ + +Il s'agit du modèle de l'arbre tableau (*org.jdesktop.swingx.JXTreeTable*), +c'est une extension d'un *org.jdesktop.swingx.treetable.DefaultTreeTableModel*. + +Les noeuds présents dans se modèle sont typés en +*jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeTableNode* qui +étend *jaxx.runtime.swing.navigation.tree.NavigationTreeModel.NavigationTreeNode*. + +NavigationTreeTableNode est abstaite, l'instance doit donc être crée en +implementant la méthode createNavigationTreeTableNode +du builder (*jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModelBuilder*). + +Les builders +____________ + +jaxx.runtime.swing.navigation.NavigationModelBuilder +==================================================== + +Les builders sont des classes utilitaires permétant de construire le model et +les rendus de l'arbre simplement. + +Tous les builders implémentent cette interface. + +jaxx.runtime.swing.navigation.tree.NavigationTreeModelBuilder +============================================================= + +Classe utilitaire pour construire le model (ici un +*jaxx.runtime.swing.navigation.tree.NavigationTreeModel*) et décorer un arbre. + +jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModelBuilder +======================================================================= + +Classe utilitaire pour construire le model (ici un +*jaxx.runtime.swing.navigation.treetable.NavigationTreeTableModel*) et décorer un arbre +tableau. + +Les Handlers +____________ + +jaxx.runtime.swing.navigation.handler.AbstractNavigationHandler +=============================================================== + +Cette classe est une implémentation d'un model de sélection pour les arbres +de navigations. + +Il y a 2 façons de l'utiliser, soit l'on associe une ui par noeud +(*Strategy.PER_NODE*) soit on associe une ui par type de noeud +(*Strategy.PER_UI_TYPE*). + +jaxx.runtime.swing.navigation.handler.NavigationTreeHandlerWithCardLayout +========================================================================= + +Extension de *jaxx.runtime.swing.navigation.handler.AbstractNavigationHandler* pour +l'utilisation de CardLayout (*jaxx.runtime.swing.CardLayout2*). + +jaxx.runtime.swing.navigation.handler.NavigationMultiTreeHandler +================================================================ + +TODO ajouter la strategie de la multiselection + +Extension de *jaxx.runtime.swing.navigation.handler.AbstractNavigationHandler* pour +ajouter la possibilité d'utiliser la multisélection. + +jaxx.runtime.swing.navigation.handler.NavigationOneClicSelectionHandler +======================================================================= + +Extension de *jaxx.runtime.swing.navigation.handler.NavigationMultiTreeHandler* pour +activer le simple clic lors de la multi-selection. + +Définition d'un noeud +_____________________ + +Le noeud +(*jaxx.runtime.swing.navigation.tree.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 noeud 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 noeud 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. + diff --git a/trunk/src/site/rst/Todo.rst b/trunk/src/site/rst/Todo.rst new file mode 100644 index 0000000..49ef412 --- /dev/null +++ b/trunk/src/site/rst/Todo.rst @@ -0,0 +1,34 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +==== +TODO +==== + + + - mettre à jour les documentations techniques et utilisateur. + + - enrichir les démos. + diff --git a/trunk/src/site/rst/contractProgramming.rst b/trunk/src/site/rst/contractProgramming.rst new file mode 100644 index 0000000..1d1ddb1 --- /dev/null +++ b/trunk/src/site/rst/contractProgramming.rst @@ -0,0 +1,97 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +========================= +Programmation par contrat +========================= + +Comme tout bon développeur Java, vous utilisez régulièrement la programmation +par contrat et la puissance de Java dans votre code en ajoutant des génériques, +des interfaces,... dès que possible et vous souhaitez retrouver les mêmes +mécanismes dans JAXX. + +Ajout de contrats sur le code généré +------------------------------------ + +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, vous pouvez utiliser l'attribut spécial +*implements*. + +Cet 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éparé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*. + +Attention a bien implémenter toutes les méthodes du contrat dans les scripts ou +votre fichier ne compilera pas. + +Générer des classes abstraites +------------------------------ + +En utilisant l'attribut abstract et en le positionnant à true, la classe générée +est abstraite. :: + + <JPanel abstract='true'/> + +Manipuler les types génériques +------------------------------ + +Il est possible d'utiliser les types génériques dans JAXX en utilisant les +attributs *genericType* et *superGenericType*. + +L'attribut genericType précise le type générique d'une classe. Exemple (fichier +Parent.jaxx) : :: + + <JPanel genericType='E' + implements='java.lang.Comparable<E>' + abstract='true' /> + +La classe générée sera de la forme : :: + + public abstract Parent<E> implements java.lang.Comparable<E> { + ... + } + +Pour surcharger une telle classe, on utilise l'attibut *superGenericType* en lui +donnant le type à utiliser. Par exemple (fichier Son.jaxx) : :: + + <Parent superGenericType='String' + abstract='true'/> + +La classe générée sera de la forme : :: + + public Son extends Parent<String> { + ... + } \ No newline at end of file diff --git a/trunk/src/site/rst/dataBinding.rst b/trunk/src/site/rst/dataBinding.rst new file mode 100644 index 0000000..c5bcf69 --- /dev/null +++ b/trunk/src/site/rst/dataBinding.rst @@ -0,0 +1,95 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +======================== +Utiliser le data-binding +======================== + +Dans un fichier JAXX, Les attributs peuvent prendre la valeur d'expressions Java +évaluées au runtime. Cela semble censé pour des expressions comme new +GridLayout(1, 0, 6, 0), mais que se passe-t-il quand vous utilisez une +expression dont la valeur change ? + +En fait, c'est ce que nous appelons data-binding. A la compilation, JAXX parse +les expressions Java pour trouver toutes leurs dépendances et ajouter les +listeners d'évènement pour détecter quand elles changent. Quand la valeur +de l'expression change, la nouvelle value est automatiquement changée. A peu +près toutes les propriétés de tous les tags peuvent être gérées de cette +manière. Par example:: + + <JTextField id='nameField'/> + + <JButton text='Button' + enabled='{nameField.getText().length() != 0}'/> + +Ainsi, le JButton ne sera activé que si un texte est rentré dans le JTextField. + +En utilisant ainsi le data-binding, vous pouvez aussi : + +* Afficher une vue détaillée des éléments sélectionnés d'une liste. +* Appliquer les préférences utilisateur comme une taille de police. +* Afficher automatiquement un curseur d'attente dès que l'application passe dans un état occupé. +* Mettre à jour la barre de titre pour refléter le fichier actif. +* Mettre à jour automatiquement une barre de progression. +* Pré-remplir des éléments de formulaire. +* ... + +Virtuellement, à chaque fois qu'un évènement change la valeur d'une propriété, +vous pouvez remplacer la gestion d'évènements Java par une expression de +data-binding plus simple et plus facile à lire. Bien sûr, JAXX n'est pas devin. +Non seulement la propriété à suivre doit lancer un évènement quand elle est +modifiée, mais JAXX doit savoir quel évènement est lancé pour ajouter le +listener approprié. Heureusement JAXX sait comment traquer presque toutes les +propriétés de tous les composants Swing, et peut automatiquement traquer les +propriétés attachées (les propriétés qui lancent des PropertyChangeEvent quand +elles sont modifiées), même sur des classes qu'il n'a jamais vu auparavant. + +Vous pouvez aussi complexifier la gestion de vos évènements en utilisant des +attributs de classe. JAXX détecte les changements que vous pouvez y apporter et +instrumente le code en conséquence. JAXX reconnait que l'on met à jour un +attribut et ajoute des PropertyChangeEvent synthétiques. L'impact sur les +performances est le plus souvent négligeable. + +Limitations +----------- + +Le data-binding parse le code Java cherchant des méthodes et attributs dont il +sait écouter les modifications. Si une méthode représente une propriété qui +lance un PropertyChangeEvent, JAXX le découvre via l'introspection. + + Limitations + +.. Data binding parses through Java code looking for methods and fields that it +.. knows how to listen for changes to. If a method represents a property which +.. fires PropertyChangeEvent (a bound property), JAXX discovers this via +.. introspection. For non-bound properties or other types of methods altogether, +.. the TagHandler for the tag must know how to deal with the method. The TagHandler +.. for JTextField, for instance, knows that getText() must be handled via a +.. DocumentListener on the Document. + +.. If a method is not 'known' as described above, JAXX has no idea how to listen to it or if it even makes sense to listen to. + +.. As field updates are handled by instrumenting the JAXX code, changing fields outside of JAXX (i.e. from ordinary Java code) bypasses JAXX's listeners and the changes will not be detected. + diff --git a/trunk/src/site/rst/demo.rst b/trunk/src/site/rst/demo.rst new file mode 100644 index 0000000..d25e80c --- /dev/null +++ b/trunk/src/site/rst/demo.rst @@ -0,0 +1,58 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +==== +Demo +==== + +Une démonstration de JAXX est disponible en utilisant Java Webstart. + +`Demonstration de JAXX`_ + +..Fonctionne seulement si site déployé + +Cette démonstration a été réalisée en utilisant JAXX, et vous pouvez visionner +tout ou partie du code source en cliquant sur l'onglet 'Sources'. + +Dans cette démonstration, vous pouvez observer nombre des atouts de JAXX et de +ses composants : + + * Boutons + * Eléments de formulaire + * Layouts + * Menus + * Fenêtres + * Editeurs + * Arbre de navigation + * Data-binding + * Validation + +.. image::demo1.png + :width:800px + +.. image::demo2.png + :width:800px + +.. _Demonstration de JAXX: ./jaxx-demo/jnlp/launch.jnlp diff --git a/trunk/src/site/rst/index.rst b/trunk/src/site/rst/index.rst new file mode 100644 index 0000000..28c0bcc --- /dev/null +++ b/trunk/src/site/rst/index.rst @@ -0,0 +1,355 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +==== +JAXX +==== + +.. contents:: + +Presentation +------------ + +JAXX is a framework that allows you to build Swing User Interface in XML. + +JAXX documentation is in French, we are planning to update it and make an +english translation at the same time. To help you wait, you can have a look to +the demo_. + +Nouveautés de la version 2.5 +---------------------------- + +Changement de l'artifactId du plugin +____________________________________ + +Avant la version 2.4, l'artifactId du plugin était **maven-jaxx-plugin**, mais +Maven depuis la version 3 demande que nous utilisions plutôt +**jaxx-maven-plugin** car à terme la première forme d'artifactId ne sera plus +acceptée que pour les projets de maven. + +Pour plus d'information sur comment utiliser le plugin, veuillez visiter la +`page des goals`_ + +Suppression des tutoriels +_________________________ + +La maintenance des tutoriels est compliquée, nous les désactivons dans cette version, il seront remplacés +bientôt par des articles sur notre blog (voir page `tutoriels`_). + +Nouveautés de la version 2.4 +---------------------------- + +Amélioration des imports +________________________ + +La version 2.4 fait le ménage dans le code généré par JAXX en se rapprochant du +projet eugene_. + +Toute la génération n'est pas encore basée sur Eugene mais cela viendra avant la +version 3. + +JAXX n'utilise plus des imports de paquetaques (import avec *), il est donc +désormais (enfin...) possible d'utiliser dans les scripts directement un import +sur *java.util.List*. + +Le fait de ne plus importer des paquetages a des impacts et pourrait rendre +votre code non compilable. + +Pour reproduire la génération comme en version *2.3*, il suffit de renseigner +dans la configuration du plugin la propriété *extraImportList* avec les valeurs +suivantes : + +:: + + <extraImportList> + java.awt.* + javax.swing.* + javax.swing.event.* + java.util.* + </extraImportList> + +Il est cependant déconseillé de laisser une telle configuration car le fait +d'utiliser des paquetages au lieu de noms de classes précises alourdit les +temps du compilateur JAXX et génère du code de moins bonne qualité... + +D'ici la version *3.0* on écrira une documentation précise de fonctionnement du +compilateur et on va faire une différence entre les namespaces utilisés pour +trouver les objets correspondants au tags d'un fichier jaxx et les imports d'une +classe java à générer. Actuellement les deux concepts sont mélangés. + +Utilisation de JXLayer 3.0.4 +____________________________ + +L'utilisation de cette mise à jour (à partir de la 3.0.3) a des impacts car +l'api a été modifiée et n'est plus compatible... Il s'agit en fait de +modification des generics sur JXLayer, vous devrez peut-être modifier votre code +pour qu'il compile. + +Nouveautés de la version 2.3 +---------------------------- + +Validation +__________ + +JAXX se base désormais sur la librarie nuiton-validator_ (qui a été extraite de +jaxx). + +Cela a entrainé un certain nombre de modification dans l'api de jaxx. Notamment : + +- Les validateurs ont changé de packages et sont dans l'autre librairie : il + faut donc modifier dans son validators.xml les fqn des validateurs en question. + Un exemple est donné dans le module **jaxx-demo** ou + **jaxx-tutorial-validation**. + +- Réécriture de l'api de validation (on travaille désormais par annotation pour + spécifier les validateurs d'un GUI ainsi que les champs à valider). + +- L'api SwingValidator a été modifiée sans conserver les anciennes signatures + car les propriétés en question (contextName devient context) sont des + propriétés de type JavaBean et la maintenance de l'ancienne et la nouvelle + api aurait été trop compliquée et confuse. + +Dans la version 2.3.x ou 2.4 une documentation complête va être écrite +concernant l'utilisation de la validation avec JAXX, en attendant un nouveau +tutorial jaxx-tutorial-validation a été écrit pour aider un peu (seul +l'application est écrite, sans documentation pour le moment...) et la page +suivante : BeanValidator_ + +Amélioration du générateur +__________________________ + +Le compilateur JAXX est désormais capable plus facilement de générer des +annotations sur les champs et les méthodes. + +Montées de version +__________________ + +Un certain nombre de librairies ont été montées de version, notamment +**nuiton-i18n** en version 2.2. Veuillez bien utiliser au moins cette version +car cela peut casser l'éxécution au runtime sinon. + + +Nouveautés de la version 2.2.4 +------------------------------ + +Nouveau module de validation +____________________________ + +Un nouveau module a été crée **jaxx-validator** qui regroupe tout ce qui +concerne le framework de validation proposé par JAXX (anciennement quand **jaxx-runtime**). + +Toute l'api de neutre non lié à JAXX a été dépréciée et sera supprimer en version +*2.3* pour utiliser celle de nuiton-validator (qui récupère le code). + +A noter que le module **jaxx-runtime** n'est plus exposé en classifier **tests** +mais **jaxx-validator** l'est (pour pouvoir utiliser les tests abstraits sur +les validateurs). + +Utilisation de i18n 2.0 +_______________________ + +En utilisant **i18n 2.0**, on a des bundles de traductions compatible +**ResourceBundle**, ceci étant dit il faut que vous utilisiez aussi cette +version de i18n sinon il ne pourra pas utiliser les traductions offertes par +jaxx. + +Nouveautés de la version 2.1 +---------------------------- + +Introduction d'un nouveau tag **import** +________________________________________ + +Ce tag simplifie la gestion des imports. + +Chaque ligne correspond à un import à effectuer. + +Exemple : + +:: + <import> + java.io.File + static java.io.File.separatorChar + </import> + +Voir http://nuiton.org/issues/show/685 + +Meilleure gestion de l'héritage +_______________________________ + +La gestion de l'héritage a été amélioré. + +On peut désormais surcharger un tag dans un fichier jaxx fils, le getter surchargé +sera bien généré. + +Si aucun initializer n'est renseigné (constructorParams, javabean, initializer) +alors rien de plus ne sera généré. + +De plus pour les bindings, on doit utiliser la propriété surchargée et non pas +l'accesseur sur la propriété. + +Lors de la génération, l'accesseur sera utilisé à la place de la propriété. + +WARNING:: + Cette évolution admet une restriction : si on veut surcharger un + component swing, on DOIT alors toujours lui préciser un initializer, sinon le + component surchargé ne sera pas généré et à l'exécution on risque d'avoir un + *ClassCastException* si le type n'est pas le même. + +Une documentation plus détaillée sur le mécanisme d'héritage sera écrite pour la +version 2.2. + + +Voir + + * http://nuiton.org/issues/show/625 + * http://nuiton.org/issues/show/626 + +Nouvelle api d'arbre +____________________ + +Le package *jaxx.runtime.swing.tree** contient une api simplifié pour créer des +arbres qui savent se charger tout seul. + +Cette api remplace celle du package **jaxx.runtime.swing.navigation**. + +Voir http://nuiton.org/issues/show/666 + +Nouvelle api d'assistant +________________________ + +Le package *jaxx.runtime.swing.wizard.ext** contient une nouvelle api simplifié +pour créer des assitants avec des modèles attachés aux étapes. + +Cette api remplace celle du **jaxx.runtime.swing.wizard.WizardOperationXXX**. + +Voir http://nuiton.org/issues/show/665 + +Ajout de tutoriaux +__________________ + +JAXX intègre désormais des tutoriaux. + +Voir + + * http://nuiton.org/issues/show/640 + * http://nuiton.org/issues/show/641 + * http://nuiton.org/issues/show/642 + +Présentation +------------ + +JAXX est un framework qui vous permet de créer des interfaces utilisateur Swing +à partir de fichiers de description en XML. La documentation n'est plus à jour. +En attendant la mise à jour de la documentation (en cours), vous pouvez vous +reporter à la demo_ . + +.. TODO A faire car plus a jour... + +Le projet JAXX ... + + +Depuis la version 1.0, et en prévision de nouveaux générateurs s'appuyant sur Jaxx,on a revu l'architecture du projet. + +Désormais, une séparation a été effectuée entre le code de compilation et le code d'exécution. + +Tout le code de compilation est en dépendance du plugin maven et vous ne devriez pas à avoir à vous en servir. + +Ce dont vous avez besoin dans vos dépendances sont uniquement les modules jaxx-runtime-xxx. + +.. TODO A finir la présentation de la nouvelle architecture (dans la version 1.2). + +**Veuillez consulter la JavaDoc pour de plus ample détails sur les différentes +librairies.** + +Migration vers JAXX 2.0 +----------------------- + +La version 2.0 de JAXX n'est pas compatible avec les versions antérieures. + +Pour plus de détail consulter la page `Migration`_. + +Nouvelles fonctionnalités 2.0 +----------------------------- + + * Core_ + + * I18n_ + + * JAXXContext_ + + * BeanValidator_ + + * NavigationModel_ + +Qui utilise JAXX ? +------------------ + +Voici une liste de projets utilisant JAXX : + + * Isis-fish_ - Logiciel de simulation de pêcheries complexes - GPL + + * simExplorer-si_ + + * ObServe_ - Logiciel de saisie de données concernant la pèche thonière - GPL + + * Lima_ - Logiciel de comptabilité française adaptée aux PME - GPL + + * Vradi_ - Logiciel de traitement de flux XML - GPL + + * Nuiton-i18n-editor + +.. TODO Finish this list and add icons + +.. _Isis-fish: http://www.isis-fish.org/ + +.. _simExplorer-si: http://www.simexplorer.org + +.. _ObServe: http://maven-site.forge.codelutin.com/observe/ + +.. _Lima: http://maven-site.chorem.org/lima/ + +.. _Vradi: http://maven-site.forge.codelutin.com/vradi + +.. _Migration: ./migration.html + +.. _Core: ./Core.html + +.. _demo: ./jaxx-demo/index.html + +.. _I18n: ./I18n.html + +.. _JAXXContext: ./JAXXContext.html + +.. _BeanValidator: ./BeanValidator.html + +.. _NavigationModel: ./NavigationModel.html + +.. _nuiton-validator: http://maven-site.nuiton.org/nuiton-utils/nuiton-validator + +.. _eugene: http://maven-site.nuiton.org/eugene + +.. _page des goals: ./jaxx-maven-plugin/plugin-info.html + +.. _tutoriels: ./tutoriels.html \ No newline at end of file diff --git a/trunk/src/site/rst/javaBeans.rst b/trunk/src/site/rst/javaBeans.rst new file mode 100644 index 0000000..b13df4e --- /dev/null +++ b/trunk/src/site/rst/javaBeans.rst @@ -0,0 +1,58 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +------------------------------------ +Utilisation des java beans dans JAXX +------------------------------------ + +Il est possible dans JAXX de rajouter des objets quelconques via leur nom +qualifié de classe. Example :: + + <JPanel> + <java.lang.Boolean id='myState' constructorParams='true'/> + <JLabel text='text' visible='{isMyState()}'/> + </JPanel> + +Cela permet de faire du data-binding en ajoutant un attribut *javaBean* sur +l'objet, sa valeur initialisant le bean. Exemple :: + + <JPanel> + <java.lang.Boolean id='myState' javaBean='true'/> + <JLabel text='text' visible='{isMySate()}'/> + </JPanel> + +ou :: + + <java.lang.String id='myStatus' javaBean='Opening...'/> + + +Cela permet d'avoir un mutateur sur la propriété *myState* qui déclenchera +l'envoi d'un *PropertyChange* sur la propriété lors de modification de valeur +(ce qui n'est pas possible en utilisant une propriété en lecture seule). + +Ainsi le compilateur JAXX sera capable d'enregistrer un nouveau dataBinding sur +la propriété *visible* du label et la modification de l'état *myState* sera +automatiquement répercuté sur la propriété. + diff --git a/trunk/src/site/rst/migration.rst b/trunk/src/site/rst/migration.rst new file mode 100644 index 0000000..821c865 --- /dev/null +++ b/trunk/src/site/rst/migration.rst @@ -0,0 +1,64 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +======================= +Migration vers JAXX 2.0 +======================= + +.. contents:: + + +Présentation +------------ + +Ce document énumère les choses à migrer pour passer sur la version 2.0 de JAXX. + +Nouvelles fonctionnalités +------------------------- + + * JList, JComboBox et JTree n'acceptent plus de fils Item (utiliser JAXXList, + JAXXComboBox, JAXXTree). + + * Changement de paquetage de jaxx.runtime.JAXXContext vers jaxx.runtime.JAXXContext + + * Changement de paquetage de jaxx.runtime.Decorator vers jaxx.runtime.decorator.Decorator + + * Le framwork de Navigation n'est plus compatible avec l'ancien... + + * JAXX interprète toutes les interfaces, elles doivent être donc importer + + * Les classe PropertychangeListener et PropertyChangeEvent ne sont plus + automatiquement importées et il faut le faire manuellement quand requis. + + * L'api des bindings a complètement été revue et permet de les utiliser par + programmation. + +Aide à la migration +------------------- + +Pour tout problème rencontré lors d'un passage à la version 2.0, vous pouvez +utiliser les listes de diffusions du projet disponibles ici : +http://maven-site.nuiton.org/jaxx/mail-lists.html + diff --git a/trunk/src/site/rst/old-compiler-doc/BeanValidator.rst b/trunk/src/site/rst/old-compiler-doc/BeanValidator.rst new file mode 100644 index 0000000..ffbbc38 --- /dev/null +++ b/trunk/src/site/rst/old-compiler-doc/BeanValidator.rst @@ -0,0 +1,206 @@ +.. - +.. * #%L +.. * JAXX :: Compiler +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +------------- +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 fait 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. + +TODO Refaire cette doc qui n'est plas à jour suite au refactoring de la validation (20090202) + +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.swing.SwingValidatorErrorListModel*. 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.swing.ui.AbstractBeanValidatorUI*. Si non présent, on utilise par défaut le render *jaxx.runtime.validator.swing.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.swin.SwingValidator +************************************************* + +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.swing.SwingValidatorErrorModel +************************************************************ + +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.swing.SwingValidatorErrorListModel +**************************************************************** + +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.swing.SwingValidatorErrorListMouseListener +************************************************************************ + +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.JAXXUtil.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*). + + + + diff --git a/trunk/src/site/rst/old-compiler-doc/I18n.rst b/trunk/src/site/rst/old-compiler-doc/I18n.rst new file mode 100644 index 0000000..e87368c --- /dev/null +++ b/trunk/src/site/rst/old-compiler-doc/I18n.rst @@ -0,0 +1,81 @@ +.. - +.. * #%L +.. * JAXX :: Compiler +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +---- +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.nuiton.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. diff --git a/trunk/src/site/rst/old-compiler-doc/Interface.rst b/trunk/src/site/rst/old-compiler-doc/Interface.rst new file mode 100644 index 0000000..b3f9ce6 --- /dev/null +++ b/trunk/src/site/rst/old-compiler-doc/Interface.rst @@ -0,0 +1,63 @@ +.. - +.. * #%L +.. * JAXX :: Compiler +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +--------- +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. diff --git a/trunk/src/site/rst/old-compiler-doc/JAXXContext.rst b/trunk/src/site/rst/old-compiler-doc/JAXXContext.rst new file mode 100644 index 0000000..748a3d2 --- /dev/null +++ b/trunk/src/site/rst/old-compiler-doc/JAXXContext.rst @@ -0,0 +1,186 @@ +.. - +.. * #%L +.. * JAXX :: Compiler +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +----------- +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.context.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.context.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. + diff --git a/trunk/src/site/rst/old-compiler-doc/JavaBean.rst b/trunk/src/site/rst/old-compiler-doc/JavaBean.rst new file mode 100644 index 0000000..89ac87f --- /dev/null +++ b/trunk/src/site/rst/old-compiler-doc/JavaBean.rst @@ -0,0 +1,75 @@ +.. - +.. * #%L +.. * JAXX :: Compiler +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +-------- +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é. + + + diff --git a/trunk/src/site/rst/old-compiler-doc/NavigationTreeModel.rst b/trunk/src/site/rst/old-compiler-doc/NavigationTreeModel.rst new file mode 100644 index 0000000..4f65c66 --- /dev/null +++ b/trunk/src/site/rst/old-compiler-doc/NavigationTreeModel.rst @@ -0,0 +1,193 @@ +.. - +.. * #%L +.. * JAXX :: Compiler +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +------------------- +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.tree.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.tree.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.tree.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. + diff --git a/trunk/src/site/rst/presentation.rst b/trunk/src/site/rst/presentation.rst new file mode 100644 index 0000000..07a33c1 --- /dev/null +++ b/trunk/src/site/rst/presentation.rst @@ -0,0 +1,50 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============ +Présentation +============ + +Qu'est-ce que JAXX ? +-------------------- + +JAXX est un framework de création d'interfaces utilisateur Swing libre en XML +automatisant un certain nombre de mécanismes complexes de Swing. En effet, qui +ne s'est pas arraché les cheveux sur des layouts managers trop complexes, des +classes internes anonymes à répétition et des bidouillages bas-niveau pour +réaliser une interface utilisateur, certes magnifique, mais à quel prix. + +JAXX se base sur XML qui permet de décrire les interfaces en gardant le principe +d'arbre et d'inclusion de composants sans se préocupper des classes internes, +du style, des layouts,... + +Pourquoi utiliser JAXX au lieu de Swing ? +----------------------------------------- + +- Les fichiers XML ont naturellement une structure d'arbre. Les tags contiennent des tags, tout comme les composants contiennent des composants. +- JAXX gère les évènements et le data binding pour vous. Plus besoin de créer de classes anonymes à la main pour gérer les évènements. +- La gestion des CSS vous permet de séparer le fond de la forme, et de changer l'aspect de votre programme en changeant juste de feuille de style. +- Les fichiers JAXX sont bien plus courts et faciles à comprendre que le code Java équivalent. +- La balise <Table> fournit la puissance du GridBagLayout en en simplifiant l'utilisation. \ No newline at end of file diff --git a/trunk/src/site/rst/scripting.rst b/trunk/src/site/rst/scripting.rst new file mode 100644 index 0000000..b0a9e53 --- /dev/null +++ b/trunk/src/site/rst/scripting.rst @@ -0,0 +1,104 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +=============================================== +Utiliser des scripts pour améliorer l'ordinaire +=============================================== + +Dans JAXX, le scripting c'est la capacité d'embarquer du code Java directement +dans les fichiers JAXX. Et contrairement à ce qu'on entends par script, le code +n'est pas interprété à l'exécution, mais compilé afin de ne pas souffrir d'un +défaut de performances. + +Dans JAXX, les scripts peuvent apparaitre à plein d'endroits : + + * dans des balise script + * dans le data binding + * dans les gestionnaires d'évènements + * dans l'attribut constraints + * dans les paramètres des constructeurs + +Les balises script +------------------ + +Du code Java peut être embarqué n'importe où dans les fichiers JAXX en utilisant +les balises <script>. Les balises script peuvent définir des méthodes, des +champs, des constructeurs, et peuvent aussi exécuter directement du code Java. + +Exemple:: + + <script><![CDATA[ + import javax.swing.table.JTableHeader; + + public SearchHandler getSearchHandler() { + return getContextValue(SearchHandler.class); + } + ]]> + </script> + +Le data-binding +--------------- + +Le code Java peut être placé en valeur d'attributs XML quand il est échappé par +des accolades ({ }). La valeur de l'attribut est ensuite calculée en utilisant +le code Java, et recalculée quand ses dépendances (s'il y en a) changent. Cette +utilisation des script est appelée data-binding_ + +.. _data-binding: dataBinding.html + +Exemple:: + + <JPanel layout='{new BorderLayout()}'> + +Gestionnaires d'évènements +-------------------------- + +Dans les balises de classes, les attributs dont le nom commence par 'on' suivi +d'une majuscule (e.g. onMousePressed, onActionPerformed) sont des gestionnaires +d'évènement. La valeur de l'attribut est du code Java qui est exécuté lorsque +l'évènement est lancé. + +Exemple:: + + <JButton onActionPerformed='myAction()'/> + +Attribut constraints +-------------------- + +Sur les composants, l'attribut constraints spécifie les contraintes du layout +(e.g. BorderLayout.NORTH, GridBagConstraints) qui devraient être utilisées +lorsque le composant est ajouté dans son conteneur parent. La valeur de cet +attribut est du code Java qui est évalué à la création du composant. + +Exemple:: + + <JButton constraints='BorderLayout.SOUTH'/> + +Paramètres des constructeurs +---------------------------- + +Dans les balises de classe, l'attribut constructorParams spécifie les +paramètres, séparés par des virgules, du constructeur de l'objet. Ces paramètres +sont interprétés comme du code Java. diff --git a/trunk/src/site/rst/spec-validator2.rst b/trunk/src/site/rst/spec-validator2.rst new file mode 100644 index 0000000..aba495b --- /dev/null +++ b/trunk/src/site/rst/spec-validator2.rst @@ -0,0 +1,80 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +========================================================================= +Amelioration de la gestion des validateurs dans les interfaces graphiques +========================================================================= + +Abstract +~~~~~~~~ + +Fonctionnement actuel +--------------------- + +Dans la version 2.2 de JAXX, tout se fait a la generation : chaque composant a +valider est encapsule dans un layer pour pouvoir ensuite afficher l'etat de +validation de la propriete du bean qu'il represente. + +Cela nous force a toujours avoir un couplage fort entre ce qui est a valider +et les composants d'edition, on ne peut pas avoir actuellement un composant +d'edition portant sur plusieurs proprietes d'un bean. + +De meme, on ne peut pas avoir des validateurs qui descendent et se greffe sur +des composants complexes (car a la generation des composants on ne sait pas qui +va les valider). + +Nouveau fonctionnement +---------------------- + +L'idee c'est d'utiliser un seul layer par formulaire. Cela a de multiple +avantages : + +- utilisation de moins de resources : un layer au lieu de n. + +- ne plus alterer les composants d'edition (le fait d'ajouter un layer perturbre + l'affichage, et par exemple si on valider sur des boutons ils sont plus petits + que les autres et c'est moche). + +- ne plus rien fige a la generation + +- permettre d'utiliser des composants d'edition portant sur plus d'une propriete + +Mise en place +~~~~~~~~~~~~~ + +- definir un nouveau tag dans JAXX BeanValidatorForm (ou un decorator) qui + correspond au layer unique du formulaire a valider + +- ecrire le layer qui va dessiner ce qu'il faut a l'ecran : + + - il doit connaitre les validateurs qui lui sont attaches et il faut ainsi + retrouver tous les composants d'edition (en descendant si besoin dans des + sous interfaces graphiques, plus de probleme car non lie a la generation). + - il faut une methode computeUI pour calculer la position des notifications + pour chaque composant. + + - il ecoute le modele des messages de validation pour modifier la vue. + - il ecoute le composant container pour recalculer la disposition (changement + de taille, changement de disposition,...). diff --git a/trunk/src/site/rst/tutoriels.rst b/trunk/src/site/rst/tutoriels.rst new file mode 100644 index 0000000..164c51d --- /dev/null +++ b/trunk/src/site/rst/tutoriels.rst @@ -0,0 +1,33 @@ +.. - +.. * #%L +.. * JAXX +.. * $Id:$ +.. * $HeadURL:$ +.. * %% +.. * Copyright (C) 2008 - 2012 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +========= +Tutoriels +========= + +Une série d'articles est en cours d'écriture pour remplacer les anciens tutoriels embarqués. + +Vous pourrez les lire dans la version 2.6 sur notre `blog`_ . + +:: _blog: http://www.codelutin.com/tag:blogtech?do=showtag&tag=tag%3Ablogtech diff --git a/trunk/src/site/rst/tutos/config.rst b/trunk/src/site/rst/tutos/config.rst new file mode 100644 index 0000000..e741382 --- /dev/null +++ b/trunk/src/site/rst/tutos/config.rst @@ -0,0 +1,54 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +========================== +Interface de Configuration +========================== + +Dans ce tutoriel, nous allons apprendre à utiliser l'api de construction +d'interface graphique de configuration. + +Sources de ce tutoriel +---------------------- + +Les sources de ce tutoriel sont disponibles au `telechargement ici`_. + +.. _telechargement ici: http://nuiton.org/projects/list_files/jaxx + +Lancer ce tutoriel +------------------ + +.. image::webstart.gif + +Pour lancer ce tutoriel via `Java Web Start`_, suivez `ce lien`_. + +Pour plus de détail sur `webstart`_. + +.. _Java Web Start: http://java.sun.com/products/javawebstart/ + +.. _ce lien: ../jaxx-tutorial-config/jnlp/launch.jnlp + +.. _webstart: ../jaxx-tutorial-config/jnlp-report.html + diff --git a/trunk/src/site/rst/tutos/css.rst b/trunk/src/site/rst/tutos/css.rst new file mode 100644 index 0000000..6d1ccb7 --- /dev/null +++ b/trunk/src/site/rst/tutos/css.rst @@ -0,0 +1,140 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +==================================== +CSS - Utiliser les feuilles de style +==================================== + +Dans ce troisième tutoriel, nous allons essayer de simplifier notre code JAXX en +utilisant une feuille de style. Nous allons, pour cela, nous baser sur le code +du précédent tutoriel : helloworld2. + +Le principe des feuilles de style JAXX +-------------------------------------- + +Dans JAXX, les feuilles de style permettent de sortir du fichier JAXX +toutes les instructions ayant trait au style de l'application. Cela permet aussi +de mutualiser les déclarations d'éléments graphiques (comme pour les feuilles +de style en HTML). Pour approfondir le sujet, vous pouvez consulter `la +documentation`_ + +.. _la documentation: ../useStylesheets.html + +Enlever le style de notre fichier JAXX +-------------------------------------- + +Nous allons enlever toutes les informations de style de notre fichier JAXX et +ajouter un tag id à chaque élément afin de l'identifier dans notre feuille de +style. On obtient le code suivant:: + + <Application id='tuto'> + + <JLabel id='hello' + constraints='BorderLayout.NORTH'/> + + <JButton id='button' + constraints='BorderLayout.SOUTH' + onActionPerformed='dispose()'/> + + </Application> + +Cela simplifie grandement notre code. + +Créer la feuille de style +------------------------- + +Nous allons créer une feuille de style, située au même niveau de l'arborescence +que notre fichier JAXX. Nous allons référencer la feuille de style dans notre +fichier JAXX en rajoutant le code suivant en fils de notre tag Application:: + + <style source='Css.css'/> + +Dans la feuille de style, il faut retrouver le même niveau que lors du premier +tutoriel. Nous allons donc commencer par notre Application et lui donner un +titre. + +Pour l'identifiant tuto, on veux rajouter l'attribut title et lui donner une +valeur. On écrira donc dans la feuille de style:: + + #tuto { + title:"CSS Tutorial"; + } + +Pour notre JLabel, on va décider que le même style et le même texte seront +appliqués à tous les JLabel. On mettra le texte à Hello World, la couleur à +rouge et la taille à 20. On écrira donc:: + + JLabel { + font-size:20; + foreground:red; + text:"Hello World"; + } + +Nous allons aussi mettre le texte de notre JButton:: + + #button { + text:"Close" + } + +Ajouter du style dynamique +-------------------------- + +Nous allons maintenant ajouter du style dynamique. Nous allons faire changer la +couleur de notre JLabel lorsqu'il est survolé. Nous utiliserons pour cela le +modifieur mouseover:: + + #hello:mouseover { + foreground:green; + } + +Conclusion +---------- + +Dans ce tutoriel vous avez vu comment mettre du style sur vos composants depuis +un fichier CSS externe. Cela vous permet de créer un style pour votre +application et de le changer au besoin en changeant juste la feuille de style. +Pas besoin de multiplier les fichiers à impacter. + +Sources de ce tutoriel +---------------------- + +Les sources de ce tutoriel sont disponibles au `telechargement ici`_. + +.. _telechargement ici: http://nuiton.org/projects/list_files/jaxx + +Lancer ce tutoriel +------------------ + +.. image::webstart.gif + +Pour lancer ce tutoriel via `Java Web Start`_, suivez `ce lien`_. + +Pour plus de détail sur `webstart`_. + +.. _Java Web Start: http://java.sun.com/products/javawebstart/ + +.. _ce lien: ../jaxx-tutorial-css/jnlp/launch.jnlp + +.. _webstart: ../jaxx-tutorial-css/jnlp-report.html diff --git a/trunk/src/site/rst/tutos/data-binding.rst b/trunk/src/site/rst/tutos/data-binding.rst new file mode 100644 index 0000000..ff36b1f --- /dev/null +++ b/trunk/src/site/rst/tutos/data-binding.rst @@ -0,0 +1,131 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============ +Data-binding +============ + +Dans ce tutoriel, nous allons voir comment utiliser le `data-binding`_ pour +rendre votre application dynamique très simplement. Dans cet exemple, nous +réaliserons une petite application comprenant un champ texte à remplir, un +slider qui change de couleur en fonction de sa valeur et un boutton permettant +de quitter l'application, mais qui est disponible uniquement lorsque du texte +est entré dans le champ à remplir. + +Textfield et bouton +------------------- + +Nous allons laisser de côté pour l'instant notre slider et nous focaliser sur +le textfield et le bouton. Créons tout d'abord notre vue :: + + <Application id='tuto'> + + <style source='data-binding.css'/> + + <JTextField id='textField' + constraints='BorderLayout.NORTH'/> + + <JButton text='Button' + constraints='BorderLayout.SOUTH' + onActionPerformed='dispose()'/> + + </Application> + +Si vous lancez l'application, le boutton est toujours valide. + +.. image::alwaysEnabledButton.png + +Nous allons donc le modifier et lui rajouter l'attribut :: + + enabled='{textField.getText().length() != 0}' + +Ce que cela va faire c'est rajouter les listeners adéquats pour qu'à chaque fois +que le résultat de textField.getText() change, la propriété enabled du boutton +est réévaluée. En l'occurence, dès que la taille du texte est différente de 0, +le boutton est activé. Essayez pour voir. + +.. image::disabledButton.png + +.. image::enabledButton.png + +Rajoutons le slider +------------------- + +Nous allons rajouter un slider entre notre textField et notre bouton. On +utilisera pour cela le code suivant :: + + <JSlider maximum='200'/> + +Nous souhaitons que lorsque l'on dépasse la moitié du slider (la valeur 100), la +couleur du fond passe à rouge. Nous allons rajouter cela au style de +l'application grace au data-binding. Dans notre feuille de style, rajoutons (ici +est décrit uniquement le style nous intéressant):: + +JSlider:{object.getValue() > 100} { + background: red; +} + +Cela donne : + +.. image::sliderBefore100.png + +.. image::sliderAfter100.png + +Dans le style, il est possible d'utiliser le data-binding sur object, qui sera +remplacé par l'objet en question dans l'application. Ici, comme pour notre +bouton précédemment, nous changeons une propriété (ici background) lorsque la +propriété value dépasse une certaine valeur. + +Conclusion +---------- + +Vous avez découvert comment créer des interfaces dynamiques en utilisant le +data-binding. Vous avez-vu la simplicité ? Vous sentez votre créativité +augmenter ? Avec les bases que vous venez d'acquérir, vous pouvez simplement +créer des applications au look très évolué et dynamique. Il ne reste plus que +votre patte créative à mettre en route. + + +Sources de ce tutoriel +---------------------- + +Les sources de ce tutoriel sont disponibles au `telechargement ici`_. + +.. _telechargement ici: http://nuiton.org/projects/list_files/jaxx + +Lancer ce tutoriel +------------------ + +.. image::webstart.gif + +Pour lancer ce tutoriel via `Java Web Start`_, suivez `ce lien`_. + +Pour plus de détail sur `webstart`_. + +.. _Java Web Start: http://java.sun.com/products/javawebstart/ + +.. _ce lien: ../jaxx-tutorial-databinding/jnlp/launch.jnlp + +.. _webstart: ../jaxx-tutorial-databinding/jnlp-report.html diff --git a/trunk/src/site/rst/tutos/helloworld.rst b/trunk/src/site/rst/tutos/helloworld.rst new file mode 100644 index 0000000..ce137d3 --- /dev/null +++ b/trunk/src/site/rst/tutos/helloworld.rst @@ -0,0 +1,186 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +=========== +Hello World +=========== + +Dans ce tutoriel, nous allons créer une fenêtre qui affiche le message +"Hello World". Jaxx s'utilise par défaut avec le gestionnaire de +dépendances/projet Maven. Nous supposons dans la suite de ce tutoriel que vous +savez utiliser Maven. + +Créer un projet Maven/configuration de JAXX +------------------------------------------- + +Nous allons commencer par créer un projet Maven simple, qui aura comme unique +source un fichier jaxx. + +Dans le pom.xml, il faut configurer les repository nuiton pour pouvoir +bénéficier de JAXX et de son plugin Maven:: + + <repositories> + + <!-- nuiton releases repository, needed to get jaxx --> + + <repository> + <id>nuiton.release</id> + <name>NuitonReleaseRepository</name> + <url>http://maven.nuiton.org/release</url> + <snapshots> + <enabled>false</enabled> + </snapshots> + <releases> + <enabled>true</enabled> + <checksumPolicy>warn</checksumPolicy> + </releases> + </repository> + + </repositories> + + <pluginRepositories> + + <!-- nuiton plugin releases repository, needed to get jaxx plugin --> + + <pluginRepository> + + <id>nuiton.release</id> + <name>NuitonReleaseRepository</name> + <url>http://maven.nuiton.org/release</url> + <snapshots> + <enabled>false</enabled> + </snapshots> + <releases> + <enabled>true</enabled> + <checksumPolicy>warn</checksumPolicy> + </releases> + </pluginRepository> + + </pluginRepositories> + +Il est aussi nécessaire d'ajouter la dépendance vers la librairie JAXX pour +la compilation et l'exécution:: + + <dependencies> + + <!-- librairie Jaxx --> + <dependency> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-runtime</artifactId> + <version>2.0.1</version> + <scope>compile</scope> + </dependency> + + </dependencies> + +Nous allons configurer aussi le plugin Maven pour la génération depuis les +fichiers JAXX:: + + <build> + <plugins> + + <plugin> + <groupId>org.nuiton.jaxx</groupId> + <artifactId>jaxx-maven-plugin</artifactId> + <version>2.0.1</version> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + + </plugins> + </build> + +Le plugin JAXX doit être dans la même version que jaxx-runtime. Il faut +spécifier l'exécution du goal generate du plugin pour que le fichier JAXX soit +transformé en fichier Java. + +Pour les autres plugins, je vous laisse les configurer seuls, il s'agit juste +de configurer maven-compiler plugins pour compiler les sources en version 1.5, +et maven-jar-plugin et maven-dependency-plugin pour rendre le jar exécutable. +Pour ceux qui ne sauraient pas comment faire cela, je vous laisse regarder un +oeil aux sources disponibles au téléchargement en bas de cette page. + +Le fichier JAXX +--------------- + +Maintenant que le projet est configuré.Nous allons commencer par créer un +fichier JAXX nommé helloworld.jaxx que nous placerons dans le package de notre +choix (dans l'exemple, c'est org.nuiton.jaxx.tutos.helloworld mais libre à vous +d'adapter) :: + + <Application title='Hello World'> + <JLabel text='Hello World'/> + </Application> + +Ce fichier Jaxx est très simple, il va créer une Application helloworld qui +étends une JFrame qui aura pour titre "Hello World" et placera dedans un +JLabel "Hello World". + +Une fois que tout est créé, on se place à la racine du projet et on le build +avec la commande :: + + mvn compile + +Cela aura pour effet de créer notre jar exécutable si tous les plugins ont bien +été configurés. + +On peut alors le lancer et on obtient le résultat suivant: + +.. image::helloworld.png + +Conclusion +---------- + +Ce tutoriel vous a appris comment créer simplement une petite application Swing, +très simple au demeurant, en utilisant seulement 3 lignes de code Jaxx. Dans les +tutoriels suivant vous allez découvrir comment réaliser des applications +dynamiques beaucoup plus complexes. + +Sources de ce tutoriel +---------------------- + +Les sources de ce tutoriel sont disponibles au `telechargement ici`_. + +.. _telechargement ici: http://nuiton.org/projects/list_files/jaxx + +Lancer ce tutoriel +------------------ + +.. image::webstart.gif + +Pour lancer ce tutoriel via `Java Web Start`_, suivez `ce lien`_. + +Pour plus de détail sur `webstart`_. + +.. _Java Web Start: http://java.sun.com/products/javawebstart/ + +.. _ce lien: ../jaxx-tutorial-helloworld/jnlp/launch.jnlp + +.. _webstart: ../jaxx-tutorial-helloworld/jnlp-report.html \ No newline at end of file diff --git a/trunk/src/site/rst/tutos/helloworld2.rst b/trunk/src/site/rst/tutos/helloworld2.rst new file mode 100644 index 0000000..e7280cf --- /dev/null +++ b/trunk/src/site/rst/tutos/helloworld2.rst @@ -0,0 +1,140 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +============= +Hello World 2 +============= + +Dans ce deuxième tutoriel, nous allons un petit peu complexifier les choses et +améliorer l'application réalisée dans le premier Hello World. Nous allons +ajouter un peu de style à notre exemple et ajouter un bouton pour fermer la +fénêtre. + +Donner du style à notre texte +----------------------------- + +Dans le premier tutoriel, le texte était déclaré comme ceci:: + + <JLabel text='Hello World'/> + +Quand l'interface utilisateur est créée, la méthode setText() du JLabel est +appelée avec l'attribut "Hello World". Nous souhaitons maintenant mettre ce +texte en rouge. La méthode correspondant, sur on objet JLabel, est +setForeground(). Donc nous allons ajouter un attribut foreground à notre JLabel +et il aura la valeur red (toutes les couleurs basiques sont implémentées):: + + <JLabel text='Hello World' + foreground='red'/> + +Si nous compilons et exécutons le code, on obtient : + +.. image::helloworld2-red.png + +Si vous souhaitez utiliser une couleur spécifique, vous pouvez aussi très bien +utiliser le code couleur HTML. Par example, en remplaçant red par #FF0000 vous +obtiendrez le même résultat. + +Maintenant, cherchons à augmenter la taille de la police. Nous allons utiliser +l'attribut font-size (ce n'est pas un attribut standard de JLabel) et lui +donner, par example, l'attribut '24':: + + <JLabel text='Hello World' + foreground='red' + font-size='24'/> + +Si nous compilons et exécutons le code, on obtient : + +.. image::helloworld2-red-big.png + +Ajouter un bouton qui ferme la fenêtre +-------------------------------------- + +Nous allons ajouter un bouton avec le texte "Close". Notre code devient:: + + <Application title='Hello World'> + + <JLabel text='Hello World' + foreground='red' + font-size='24' + constraints='BorderLayout.NORTH'/> + + <JButton text='Close' + constraints='BorderLayout.SOUTH'/> + + </Application> + +Si nous compilons et exécutons le code, on obtient : + +.. image::helloworld2-red-big-button.png + +Mais le bouton ne fait rien, il faut appeler la méthode dispose() quand une +action est réalisée sur le bouton pour fermer la fenêtre. Pour le réaliser, +nous allons donner la valeur dispose() à l'attribut onActionPerformed de notre +bouton. :: + + <JButton text='Close' + constraints='BorderLayout.SOUTH' + onActionPerformed='dispose()'/> + +Les attributs commençant par on sont en fait des callbacks qui sont appelés +quand un évènement est lancé par l'objet en question. Ainsi dans notre exemple +la méthode dispose() est appelée quand un évènement ActionPerformed est lancé. + +Nous allons revenir sur l'attribut constraints que l'on a passé à nos JLabel et +JButton. L'attribut constraints spécifie les contraintes de layout à utiliser +quand un composant est ajouté à son parent. Ici, nous utilisons le BorderLayout +pour placer les éléments les uns en dessous des autres. A noter que l'attribut +constraints n'est applicable que sur les composants descendants de la classe +Component. La valeur prise pas l'attribut constraints est forcément du code +Java qui doit retourner un Object ou null. + +Conclusion +---------- + +Dans ce tutoriel vous avez vu comment mettre du style sur vos composants et +créer un bouton qui lance une méthode. Vous avez également vu comment placer +(très rapidement, il est vrai) des éléments dans un conteneur. + +Sources de ce tutoriel +---------------------- + +Les sources de ce tutoriel sont disponibles au `telechargement ici`_. + +.. _telechargement ici: http://nuiton.org/projects/list_files/jaxx + +Lancer ce tutoriel +------------------ + +.. image::webstart.gif + +Pour lancer ce tutoriel via `Java Web Start`_, suivez `ce lien`_. + +Pour plus de détail sur `webstart`_. + +.. _Java Web Start: http://java.sun.com/products/javawebstart/ + +.. _ce lien: ../jaxx-tutorial-helloworld2/jnlp/launch.jnlp + +.. _webstart: ../jaxx-tutorial-helloworld2/jnlp-report.html \ No newline at end of file diff --git a/trunk/src/site/rst/useStylesheets.rst b/trunk/src/site/rst/useStylesheets.rst new file mode 100644 index 0000000..916b75c --- /dev/null +++ b/trunk/src/site/rst/useStylesheets.rst @@ -0,0 +1,169 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +=================== +Utiliser des styles +=================== + +Introduction +------------ + +JAXX vous permet de séparer le contenu de l'apparance, un peu comme en HTML, en +utilisant les feuilles de style CSS. Les feuilles de style JAXX peuvent assigner +n'importe quelle propriété d'un objet, et permettre a n'importe quel nombre +d'objets d'être décorés de la même manière avec des règles simples. De plus, les +feuilles de style vous permettent de créer facilement des comportements +dynamiques. + +Appliquer un style +------------------ + +Pour qu'une application utilise une feuille de style, il lui suffit d'avoir +une balise style à sa racine :: + + <Application title='Example'> + <style source='example.css'/> + ... + </Application> + +Les sélecteurs +-------------- + +Ensuite, la feuille de style en question ressemble à une feuille de style HTML. +Le style d'une classe Java est définit de la manière suivante :: + + JSlider { + paintTicks: true; + minorTickSpacing: 10; + majorTickSpacing: 50; + } + +Ainsi toutes les JSlider de l'application auront ce style. On peut également +définir le style d'une balise ayant un id particulier de cette manière:: + + #red { + background: red; + } + +Ainsi, les balises qui ont un id red auront toute un background rouge. + +Pour résumé, il y a 4 types de sélecteur de style. + ++-----------------+---------------------------+-------------------------------------------------------------------------------+ +| Type | Syntaxe | Description | ++=================+===========================+===============================================================================+ +| classe Java | classname | Sélectionne toutes les instances de la classe (ou ses sous-classes) spécifiée | ++-----------------+---------------------------+-------------------------------------------------------------------------------+ +| ID | #id | Sélectionne les composants ayant l'attribut id='<id>' | ++-----------------+---------------------------+-------------------------------------------------------------------------------+ +| Classe de style | #styleclass | Sélectionne les composants avec l'attribut styleClass='<styleClass>' | ++-----------------+---------------------------+-------------------------------------------------------------------------------+ +| Pseudo-classe | :mouseover, :focused, ... | Sélectionne les composants dynamiquement selon leur état | ++-----------------+---------------------------+-------------------------------------------------------------------------------+ + +Expressions Java +---------------- + +Beaucoup de style Swing ne peut être déclaré qu'en utilisant des expressions +Java. Ces expressions Java peuvent être insérées dans des feuilles de style si +elles sont échappées par des accolades. Par exemple:: + + JSlider { + border: {BorderFactory.createLineBorder(Color.black, 1)}; + } + +Combiner les sélecteurs +----------------------- + +Un sélecteur est une expression spécifique qui peux être vraie ou fausse pour +n'importe quel type de composant. Vrai signifie que le composant est affecté par +la règle, faux signifie qu'il ne l'est pas. Les quatres types de sélecteur +basiques peuvent être combinés pour former des expressions composées: + +* JButton.cancel: S'applique à toutes les instances de JButton (ou une sous-classe) qui a styleClass='cancel'. +* #display:disabled: S'applique au composant ayant l'ID display quand il est dans le statut disabled. +* AbstractButton.large:selected: S'applique a toutes les sous-classes d'AbstractButton ayant styleClass='large' lorsqu'ils sont dans le statut selected. + +Le style +-------- + +Le support des css JAXX est relativement similaire au HTML. La grosse différence +est qu'au lieu d'appliquer des propriétés spécifiques au HTML comme padding +ou color, vous appliquez des propriétés spécifiques comme border ou foreground. +Les mêmes propriétés que vous pouvez spécifier directement sur les tags. JAXX +utilises aussi les pseudo-classe CSS, une fonctionnalité peu utilisée qui vous +permet de changer le style des liens, et étendue pour fonctionner avec tous les +composants permet de répondre à a peu près tous les évènements. + +Les pseudo-classes +------------------ + +Il peut-être intéressant de changer le style d'un composant lorsqu'il est dans +un état particulier. Dans ce cas, il suffit d'utiliser les pseudo-classes. +Par exemple, si on souhaite que notre élément ayant l'ID red ne devienne rouge +que lorsqu'il est survolé par la souris, il suffit de changer le style à:: + + #red:mouseover { + background: #E7ADAD; + } + +JAXX supporte les pseudo-classes suivantes: + +* mouseover +* mouseout +* mousedown +* mouseup +* enabled +* disabled +* focused +* unfocused +* selected +* deselected +* armed +* unarmed + +Pseudo-classes programmatiques +------------------------------ + +Chaque pseudo-classe est, comme tous les sélecteurs, un test vrai/faux. La +souris survole le composant, ou pas ? En plus de toutes les pseudo-classes, +JAXX vous permet de spécifier explicitement un test comme ceci:: + + JSlider#powerLevel:{object.getValue() > 100} { + background: red; + } + +Il apparait au même endroit qu'une pseudo-classe, sauf que c'est une expression +Java échappée par des accolades. Avec ce style, le JSlider avec l'ID powerLevel +deviendra rouge lorsque sa valeur dépassera 100. Cette sorte de pseudo-classe +est appellée pseudo-classe programmatique, et elle vous donne toute la +flexibilité possible pour décider si un style doit être appliqué à un objet. + +Le système de data binding de JAXX est utilisé pour suivre les changements d'une +expression, ainsi les pseudo-classes programmatique supportent les mêmes +propriétés que le data-binding. En interne, la plupart des pseudo-classes JAXX +sont implémentées comme des pseudo-classes programmatiques. Ainsi la +pseudo-classe focused, par example, est exactement équivalente à +{object.hasFocus()}, mais beaucoup plus simple à retenir. \ No newline at end of file diff --git a/trunk/src/site/rst/useSwingObjects.rst b/trunk/src/site/rst/useSwingObjects.rst new file mode 100644 index 0000000..fd08f7e --- /dev/null +++ b/trunk/src/site/rst/useSwingObjects.rst @@ -0,0 +1,69 @@ +.. - +.. * #%L +.. * JAXX +.. * +.. * $Id$ +.. * $HeadURL$ +.. * %% +.. * Copyright (C) 2008 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - + +========================= +Utiliser les objets Swing +========================= + +Dans JAXX, comme nous générons des interfaces Swing, il est possible d'utiliser +directement les objets Swing. Par exemple, si je veux créer un JPanel Swing, +j'utilise le tag <JPanel> si je veux créer un JButton Swing, j'utilise le tag +<JButton>, et ainsi de suite. Tous les objets Swing sont ainsi disponible +aisément sans avoir besoin de déclarer des imports dans le fichier JAXX. + +Pour configurer ces objets Swing, il suffit de leur passer en attribut la valeur +souhaitée. Par exemple, si je veux créer un JButton qui a le texte 'Valider' et +qui appelle une méthode statique MyApplication.validate(), j'écris le code JAXX +suivant :: + + <JButton id='myButton' + text='Valider' + onActionPerformed='{org.my.package.MyApplication.validate()}'/> + </JButton> + +Propriétés +---------- + +Pour généraliser, un attribut myAttribute sera passé en paramètre de la méthode +setMyAttribute. Dans notre cas, le JButton myButton sera créé, puis on +effectuera l'appel de méthode suivant : **myButton.setText("Valider")**. + +Evenements +---------- + +De même, pour les évènements, il est possible de déclarer des méthodes écoutant +les évènements créés par un objet Swing. Ainsi un attribut onMyAction sera +appelé lors d'un appel à la méthode fireMyAction de l'objet Swing. Dans le cas +de notre JButton, la méthode **org.my.package.MyApplication.validate()** sera +appelée lorsqu'un évènement de type ActionEvent sera créé par la méthode +fireActionPerformed du JButton. + +Code Java +--------- + +Dand l'example présenté en début de page, vous avez pu remarquer un appel à du +code java (org.my.package.MyApplication.validate()). Il est possible d'appeler +du code Java dans JAXX depuis un attribut d'un tag en échappant le code Java par +des accolades comme dans l'example précédent. \ No newline at end of file diff --git a/trunk/src/site/site_fr.xml b/trunk/src/site/site_fr.xml new file mode 100644 index 0000000..631922f --- /dev/null +++ b/trunk/src/site/site_fr.xml @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JAXX + + $Id$ + $HeadURL$ + %% + Copyright (C) 2008 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 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 Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <skin> + <groupId>org.apache.maven.skins</groupId> + <artifactId>maven-fluido-skin</artifactId> + <version>1.2.1</version> + </skin> + + <custom> + <fluidoSkin> + <topBarEnabled>false</topBarEnabled> + <googleSearch/> + <sideBarEnabled>true</sideBarEnabled> + <searchEnabled>true</searchEnabled> + <sourceLineNumbersEnabled>true</sourceLineNumbersEnabled> + </fluidoSkin> + </custom> + + <bannerLeft> + <name>${project.name}</name> + <src>http://maven-site.chorem.org/public/images/logos/jaxx-logo.png</src> + <href>index.html</href> + </bannerLeft> + + <bannerRight> + <src>http://www.codelutin.com/images/lutinorange-codelutin.png</src> + <href>http://www.codelutin.com</href> + </bannerRight> + + <publishDate position="right" format="dd/MM/yyyy"/> + <version position="right"/> + + <poweredBy> + <logo href="http://maven.apache.org" name="Maven" + img="http://maven-site.chorem.org/public/images/logos/maven-feather.png"/> + <logo href="http://maven-site.nuiton.org/jrst" name="JRst" + img="http://maven-site.chorem.org/public/images/logos/jrst-logo.png"/> + <logo href="http://docutils.sourceforge.net/rst.html" + name="ReStructuredText" + img="http://maven-site.chorem.org/public/images/logos/restructuredtext-logo.png"/> + </poweredBy> + + <body> + + <links> + <item name="nuiton.org" href="http://www.nuiton.org"/> + <item name="CodeLutin" href="http://codelutin.com"/> + <item name="Libre-Entreprise" href="http://www.libre-entreprise.org/"/> + <item name="original JAXX" + href="http://buix.labs.libre-entreprise.org/original-jaxx"/> + </links> + + <breadcrumbs> + <item name="${project.name}" + href="http://maven-site.nuiton.org/jaxx/index.html"/> + </breadcrumbs> + + <menu ref="modules"/> + + <menu name="Présentation"> + <item name="Accueil" href="index.html"/> + <item name="Présentation/Concept" href="presentation.html"/> + <item name="Qu'est-ce qu'un fichier JAXX ?" href="JAXXFile.html"/> + <item name="Démonstration" href="demo.html"/> + <item name="Tutoriels" href="tutoriels.html"/> + </menu> + + <menu name="Fonctionalités de base"> + <item name="Utiliser les objets Swing" href="useSwingObjects.html"/> + <item name="Les scripts JAXX" href="scripting.html"/> + <item name="Le data-binding" href="dataBinding.html"/> + <item name="Utiliser des styles" href="useStylesheets.html"/> + <!--item name="Le context/cache" href=""/--> + <item name="Java beans" href="javaBeans.html"/> + <!--item name="Actions/Tabs" href=""/--> + </menu> + + <menu name="Fonctionnalités avancées"> + <item name="Internationalisation" href="I18n.html"/> + <!--item name="Arbre de navigation" href=""/> + <item name="Validateurs" href=""/--> + <item name="Programmation par contrat" href="contractProgramming.html"/> + <!--item name="Widgets" href=""/--> + </menu> + + <!--menu name="Démo et Tutoriels"> + <item name="Démo" href="demo.html"/> + <item name="Hello World" href="tutos/helloworld.html"/> + <item name="Hello World 2" href="tutos/helloworld2.html"/> + <item name="Feuilles de style" href="tutos/css.html"/> + <item name="Data-binding" href="tutos/data-binding.html"/> + <item name="ConfigUI" href="tutos/config.html"/> + </menu--> + + <menu name="Ancienne documentation"> + <item name="Migration JAXX 2.0" href="migration.html"/> + <item name="A faire" href="Todo.html"/> + </menu> + + <menu ref="reports"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.developerConnection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> -- To stop receiving notification emails like this one, please contact nuiton.org SCM administrator <admin+scm@nuiton.org>.