Buix-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
March 2009
- 2 participants
- 33 discussions
19 Mar '09
Author: tchemit
Date: 2009-03-19 22:47:05 +0000 (Thu, 19 Mar 2009)
New Revision: 1272
Added:
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-error-validation.xml
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-info-validation.xml
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-warning-validation.xml
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-error-validation.xml
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-info-validation.xml
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-warning-validation.xml
jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/icons/info.png
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator2.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorEvent.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorField.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorListener.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java
jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/SimpleBean.java
jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/XWorkBeanValidatorTest.java
jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-error-validation.xml
jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-info-validation.xml
jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-simple-validation.xml
jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-warning-validation.xml
Removed:
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-validation.xml
jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-validation.xml
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorScope.java
jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/AbstractValidatorTest.java
Modified:
jaxx/trunk/jaxx-example/changelog.txt
jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx
jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationListDemo.jaxx
jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationTableDemo.jaxx
jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties
jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties
jaxx/trunk/jaxx-example/src/main/resources/log4j.properties
jaxx/trunk/jaxx-runtime-validator-swing/changelog.txt
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorListModel.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorModel.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableModel.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableRenderer.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java
jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java
jaxx/trunk/jaxx-runtime-validator/changelog.txt
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/JAXXValidator.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidationUtil.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorEvent.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorListener.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorField.java
jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java
jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/BeanValidatorTest.java
jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java
jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties
Log:
refactor validator, now can deal with scope : one file by scope
no more modification in xworls
improve listener design
TODO remove all classes and bump back the version of xworks
Modified: jaxx/trunk/jaxx-example/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-example/changelog.txt 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/changelog.txt 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,4 +1,5 @@
1.3
+ * 20090319 [chemit] - refactor Validator : now can deal with scopes, improve design
* 20090313 [chemit] - improve demo
1.1 chemit 20090220
Modified: jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx
===================================================================
--- jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx 2009-03-19 22:47:05 UTC (rev 1272)
@@ -3,7 +3,8 @@
org.codelutin.i18n.I18n.init();
-void $afterCompleteSetup() {
+void $afterCompleteSetup() {
+ try { jaxx.runtime.SwingUtil.initNimbusLoookAndFeel(); } catch (Exception e) { log.error(e.getMessage(), e); }
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Modified: jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationListDemo.jaxx
===================================================================
--- jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationListDemo.jaxx 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationListDemo.jaxx 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,6 +1,16 @@
<DemoPanel>
<style source="Validation.css"/>
+<script>
+void $afterCompleteSetup() {
+ validator.setBean(null);
+ validator2.setBean(null);
+ validator3.setBean(null);
+ validator.setBean(model1);
+ validator2.setBean(model2);
+ validator3.setBean(identity);
+}
+</script>
<!-- models -->
<Model id='model1'/>
<Model id='model2'/>
Modified: jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationTableDemo.jaxx
===================================================================
--- jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationTableDemo.jaxx 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/ValidationTableDemo.jaxx 2009-03-19 22:47:05 UTC (rev 1272)
@@ -30,16 +30,17 @@
import static org.codelutin.i18n.I18n.n_;
import jaxx.runtime.SwingUtil;
-static boolean wasinit=false;
-
-errorTable.setDefaultRenderer(Object.class, new jaxx.runtime.validator.swing.SwingValidatorErrorTableRenderer());
-SwingUtil.setI18nTableHeaderRenderer(errorTable, n_("validator.scope"), n_("validator.scope.tip"), n_("validator.field"), n_("validator.field.tip"), n_("validator.message"), n_("validator.message.tip"));
-public void setVisible(boolean value) {
- if (!wasinit) {
- SwingUtil.fixTableColumnWidth(errorTable, 0, 20);
- wasinit=true;
- }
- super.setVisible(value);
+void $afterCompleteSetup() {
+ errorTable.setDefaultRenderer(Object.class, new jaxx.runtime.validator.swing.SwingValidatorErrorTableRenderer());
+ SwingUtil.setI18nTableHeaderRenderer(errorTable, n_("validator.scope"), n_("validator.scope.tip"), n_("validator.field"), n_("validator.field.tip"), n_("validator.message"), n_("validator.message.tip"));
+ SwingUtil.fixTableColumnWidth(errorTable, 0, 25);
+
+ validator.setBean(null);
+ validator2.setBean(null);
+ validator3.setBean(null);
+ validator.setBean(model1);
+ validator2.setBean(model2);
+ validator3.setBean(identity);
}
]]></script>
Modified: jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties 2009-03-19 22:47:05 UTC (rev 1272)
@@ -89,6 +89,7 @@
button\ B=
button\ C=
button\ C\ (full\ block)=
+button\ D\ (full\ block\ 2)=
button\ with\ layer=
cancel=
close=
Modified: jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties 2009-03-19 22:47:05 UTC (rev 1272)
@@ -89,6 +89,7 @@
button\ B=
button\ C=
button\ C\ (full\ block)=
+button\ D\ (full\ block\ 2)=
button\ with\ layer=
cancel=
close=
Added: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-error-validation.xml
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-error-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-error-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,49 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+ <field name="firstName">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a firstName.</message>
+ </field-validator>
+ </field>
+ <field name="lastName">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a lastName.</message>
+ </field-validator>
+ </field>
+
+ <field name="email">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a value for email.</message>
+ </field-validator>
+ <field-validator type="email" short-circuit="true">
+ <message>Not a valid e-mail.</message>
+ </field-validator>
+ </field>
+
+ <field name="config">
+ <field-validator type="requiredFile" short-circuit="true">
+ <message>You must enter a value for config.</message>
+ </field-validator>
+ <field-validator type="existingFile" short-circuit="true">
+ <message>The configuration file ${config} does not exist.</message>
+ </field-validator>
+ </field>
+
+ <field name="dir">
+ <field-validator type="requiredFile" short-circuit="true">
+ <message>You must enter a value for dir.</message>
+ </field-validator>
+ <field-validator type="existingDirectory" short-circuit="true">
+ <message>The directory ${dir} does not exist.</message>
+ </field-validator>
+ </field>
+
+ <field name="age">
+ <field-validator type="int">
+ <param name="min">18</param>
+ <message>Your are too young (min ${min} )</message>
+ </field-validator>
+ </field>
+</validators>
\ No newline at end of file
Copied: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-info-validation.xml (from rev 1250, jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-validation.xml)
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-info-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-info-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,49 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+ <!--field name="firstName">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a firstName.</message>
+ </field-validator>
+ </field>
+ <field name="lastName">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a lastName.</message>
+ </field-validator>
+ </field>
+
+ <field name="email">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a value for email.</message>
+ </field-validator>
+ <field-validator type="email" short-circuit="true">
+ <message>Not a valid e-mail.</message>
+ </field-validator>
+ </field>
+
+ <field name="config">
+ <field-validator type="requiredFile" short-circuit="true">
+ <message>You must enter a value for config.</message>
+ </field-validator>
+ <field-validator type="existingFile" short-circuit="true">
+ <message>The configuration file ${config} does not exist.</message>
+ </field-validator>
+ </field>
+
+ <field name="dir">
+ <field-validator type="requiredFile" short-circuit="true">
+ <message>You must enter a value for dir.</message>
+ </field-validator>
+ <field-validator type="existingDirectory" short-circuit="true">
+ <message>The directory ${dir} does not exist.</message>
+ </field-validator>
+ </field-->
+
+ <field name="age">
+ <field-validator type="int">
+ <param name="min">25</param>
+ <message>You are still young ( old ${min} ) </message>
+ </field-validator>
+ </field>
+</validators>
\ No newline at end of file
Deleted: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-validation.xml
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-validation.xml 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,50 +0,0 @@
-<!DOCTYPE validators PUBLIC
- "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
- "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-<validators>
- <field name="firstName">
- <field-validator type="requiredstring" short-circuit="true">
- <message>You must enter a firstName.</message>
- </field-validator>
- </field>
- <field name="lastName">
- <field-validator type="requiredstring" short-circuit="true">
- <message>You must enter a lastName.</message>
- </field-validator>
- </field>
-
- <field name="email">
- <field-validator type="requiredstring" short-circuit="true">
- <message>You must enter a value for email.</message>
- </field-validator>
- <field-validator type="email" short-circuit="true">
- <message>Not a valid e-mail.</message>
- </field-validator>
- </field>
-
- <field name="config">
- <field-validator type="requiredFile" short-circuit="true">
- <message>You must enter a value for config.</message>
- </field-validator>
- <field-validator type="existingFile" short-circuit="true">
- <message>The configuration file ${config} does not exist.</message>
- </field-validator>
- </field>
-
- <field name="dir">
- <field-validator type="requiredFile" short-circuit="true">
- <message>You must enter a value for dir.</message>
- </field-validator>
- <field-validator type="existingDirectory" short-circuit="true">
- <message>The directory ${dir} does not exist.</message>
- </field-validator>
- </field>
-
- <field name="age">
- <field-validator type="int">
- <param name="min">18</param>
- <param name="max">88</param>
- <message>Age needs to be between ${min} and ${max}</message>
- </field-validator>
- </field>
-</validators>
\ No newline at end of file
Added: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-warning-validation.xml
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-warning-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Identity-warning-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,49 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+ <!--field name="firstName">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a firstName.</message>
+ </field-validator>
+ </field>
+ <field name="lastName">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a lastName.</message>
+ </field-validator>
+ </field>
+
+ <field name="email">
+ <field-validator type="requiredstring" short-circuit="true">
+ <message>You must enter a value for email.</message>
+ </field-validator>
+ <field-validator type="email" short-circuit="true">
+ <message>Not a valid e-mail.</message>
+ </field-validator>
+ </field>
+
+ <field name="config">
+ <field-validator type="requiredFile" short-circuit="true">
+ <message>You must enter a value for config.</message>
+ </field-validator>
+ <field-validator type="existingFile" short-circuit="true">
+ <message>The configuration file ${config} does not exist.</message>
+ </field-validator>
+ </field>
+
+ <field name="dir">
+ <field-validator type="requiredFile" short-circuit="true">
+ <message>You must enter a value for dir.</message>
+ </field-validator>
+ <field-validator type="existingDirectory" short-circuit="true">
+ <message>The directory ${dir} does not exist.</message>
+ </field-validator>
+ </field-->
+
+ <field name="age">
+ <field-validator type="int">
+ <param name="max">88</param>
+ <message>Info : Your are older than ${max} !</message>
+ </field-validator>
+ </field>
+</validators>
\ No newline at end of file
Copied: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-error-validation.xml (from rev 1250, jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-validation.xml)
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-error-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-error-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,35 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.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
Property changes on: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-error-validation.xml
___________________________________________________________________
Name: svn:mergeinfo
+
Added: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-info-validation.xml
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-info-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-info-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,13 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.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
Deleted: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-validation.xml
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-validation.xml 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,41 +0,0 @@
-<!DOCTYPE validators PUBLIC
- "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
- "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-<validators>
- <!-- Field 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-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-validator type="email" short-circuit="true">
- <message>Not a valid e-mail 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
Added: jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-warning-validation.xml
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-warning-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-example/src/main/resources/jaxx/demo/Model-warning-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,18 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.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
Modified: jaxx/trunk/jaxx-example/src/main/resources/log4j.properties
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/log4j.properties 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-example/src/main/resources/log4j.properties 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,9 +1,9 @@
# Global logging configuration
-log4j.rootLogger=INFO, stdout
+log4j.rootLogger=ERROR, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) %M - %m%n
-#log4j.logger.org.codelutin.jaxx=DEBUG
log4j.logger.examples=DEBUG
+log4j.logger.jaxx=INFO
Modified: jaxx/trunk/jaxx-runtime-validator/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/changelog.txt 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/changelog.txt 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,3 +1,6 @@
+1.3 ??? 200903??
+ * 20090319 [chemit] - refactor Validator : now can deal with scopes, improve design
+
1.1 chemit 20090220
* 20090203 [chemit] - move swing specific code to jaxx-runtime-validator-swing module
* 20090202 [chemit] - rename Util to ValidationUtil
Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/JAXXValidator.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/JAXXValidator.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/JAXXValidator.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,8 +1,8 @@
package jaxx.runtime;
-import jaxx.runtime.validator.BeanValidator;
import java.util.List;
+import jaxx.runtime.validator.BeanValidator2;
/**
* The contract of a validator-able object.
@@ -17,7 +17,7 @@
* @param validatorId validator id
* @return the associated validator, or <code>null</code> if not find
*/
- BeanValidator<?> getValidator(String validatorId);
+ BeanValidator2<?> getValidator(String validatorId);
/** @return the list of ids of all registred validator */
List<String> getValidatorIds();
Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -12,6 +12,7 @@
import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.Validator;
import com.opensymphony.xwork2.validator.ValidatorScope;
+import java.beans.EventSetDescriptor;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.logging.Log;
@@ -22,7 +23,6 @@
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
@@ -31,7 +31,18 @@
import java.util.Map.Entry;
import java.util.TreeMap;
-/** @author chemit */
+/**
+ *
+ * A customized validator for a given bean.
+ *
+ * <b>Note:</b> The bean must be listenable on properyChange events (means
+ * must have public addPropertychangeListener and removePropertyChangeListener methods).
+ *
+ * @param <B> type of the bean to validate.
+ *
+ * @author chemit
+ */
+@Deprecated
public class BeanValidator<B> {
/** la nom de la propriété bean */
@@ -90,7 +101,12 @@
protected transient ActionValidatorManager validator;
protected ActionContext context;
+ protected EventSetDescriptor beanEventDescriptor;
+
public BeanValidator(Class<B> beanClass, String contextName) {
+ // check that the bean is listenable, otherwise, can't use the validator on it
+ beanEventDescriptor = ValidationUtil.getPropertyChangeListenerDescriptor(beanClass);
+
this.beanClass = beanClass;
this.contextName = contextName;
pcs = new PropertyChangeSupport(this);
@@ -114,6 +130,7 @@
conversionErrors = new TreeMap<String, String>();
l = new PropertyChangeListener() {
+ @Override
public void propertyChange(PropertyChangeEvent evt) {
validate();
setValid(!hasErrors());
@@ -209,15 +226,17 @@
// clean conversions of previous bean
conversionErrors.clear();
- if (oldBean != null) {
+ if (oldBean != null) {
try {
- Method method = this.bean.getClass().getMethod("removePropertyChangeListener", PropertyChangeListener.class);
- method.invoke(oldBean, l);
+ beanEventDescriptor.getRemoveListenerMethod().invoke(oldBean, l);
+ //Method method = this.bean.getClass().getMethod("removePropertyChangeListener", PropertyChangeListener.class);
+ //method.invoke(oldBean, l);
} catch (Exception eee) {
- log.info("Can't register as listener", eee);
+ log.info("Can't register as listener for bean "+beanClass+" for reason "+eee.getMessage(), eee);
}
}
this.bean = bean;
+
if (bean == null) {
// must remove all errors from this validator on errorListModel
validationSupport.clearErrorsAndMessages();
@@ -226,10 +245,11 @@
dispatchErrorsToFields();
} else {
try {
- Method method = this.bean.getClass().getMethod("addPropertyChangeListener", PropertyChangeListener.class);
- method.invoke(bean, l);
+ beanEventDescriptor.getAddListenerMethod().invoke(bean, l);
+ //Method method = this.bean.getClass().getMethod("addPropertyChangeListener", PropertyChangeListener.class);
+ //method.invoke(bean, l);
} catch (Exception eee) {
- log.info("Can't register as listener", eee);
+ log.info("Can't register as listener for bean "+beanClass+" for reason "+eee.getMessage(), eee);
}
validate();
}
@@ -296,6 +316,7 @@
* <p/>
* If an error occurs, then add an error in validator.
*
+ * @param <T> the type of conversion
* @param fieldName the name of the bean property
* @param value the value to convert
* @param valueClass the type of converted value
Added: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator2.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator2.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidator2.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,458 @@
+package jaxx.runtime.validator;
+
+import java.beans.EventSetDescriptor;
+import org.apache.commons.beanutils.ConversionException;
+import org.apache.commons.beanutils.Converter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codelutin.util.ConverterUtil;
+
+import java.beans.Introspector;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import javax.swing.event.EventListenerList;
+
+/**
+ *
+ * A customized validator for a given bean.
+ *
+ * <b>Note:</b> The bean must be listenable on properyChange events (means
+ * must have public addPropertychangeListener and removePropertyChangeListener methods).
+ *
+ * @param <B> type of the bean to validate.
+ *
+ * @author chemit
+ */
+public class BeanValidator2<B> {
+
+ /** la nom de la propriété bean */
+ static public final String BEAN_PROERTY = "bean";
+ /** la nom de la propriété contextName */
+ static public final String CONTEXT_NAME_PROPERTY = "contextName";
+ /** la nom de l'état valid */
+ static public final String VALID_PROERTY = "valid";
+ /** la nom de l'état changed */
+ static public final String CHANGED_PROERTY = "changed";
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static protected final Log log = LogFactory.getLog(BeanValidator2.class);
+ /** the type of bean to watch */
+ protected final Class<B> beanClass;
+ /** the validation named context (can be null) */
+ protected String contextName;
+ /** to chain to a prent validator */
+ protected BeanValidator2<?> parentValidator;
+ /** state to indicate that validator has changed since the last time bean was setted */
+ protected boolean changed = false;
+ /** state of the validator (is true if no errors of error scope is found) */
+ protected boolean valid = true;
+ /** bean to be watched */
+ protected B bean = null;
+ /** to add and remove PropertyChangeListener on watched beans */
+ protected EventSetDescriptor beanEventDescriptor;
+ /** list of fields watched by this validator */
+ protected Set<BeanValidatorField<B>> fields;
+ /** map of conversion errors detected by this validator */
+ protected Map<String, String> conversionErrors;
+ /** xworks scope validator **/
+ protected EnumMap<BeanValidatorScope, XWorkBeanValidator<B>> validators;
+ /** listener that listens on bean modification */
+ protected PropertyChangeListener l;
+ /** delegate property change support */
+ protected PropertyChangeSupport pcs;
+ /** A list of event listeners for this validators */
+ protected EventListenerList listenerList = new EventListenerList();
+
+ public BeanValidator2(Class<B> beanClass, String contextName) {
+ this.beanClass = beanClass;
+ this.pcs = new PropertyChangeSupport(this);
+ this.conversionErrors = new TreeMap<String, String>();
+ this.validators = new EnumMap<BeanValidatorScope, XWorkBeanValidator<B>>(BeanValidatorScope.class);
+
+ setContextName(contextName);
+
+ l = new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ validate();
+ setValid(!hasErrors());
+ setChanged(true);
+ }
+ };
+ }
+
+ public Class<B> getBeanClass() {
+ return beanClass;
+ }
+
+ public BeanValidator2<?> getParentValidator() {
+ return parentValidator;
+ }
+
+ public String getContextName() {
+ return contextName;
+ }
+
+ public Set<BeanValidatorField<B>> getFields() {
+ return fields;
+ }
+
+ /**
+ * Retourne vrai si l'objet bean a ete modifie depuis le dernier
+ * {@link #setBean}
+ *
+ * @return <code>true</code> if bean was modify since last {@link #setBean(Object)} invocation
+ */
+ public boolean isChanged() {
+ return changed;
+ }
+
+ public boolean isValid() {
+ return valid;
+ }
+
+ public B getBean() {
+ return bean;
+ }
+
+ public BeanValidatorField<B> getField(String fieldName) {
+ for (BeanValidatorField<B> field : fields) {
+ if (fieldName.equals(field.getName())) {
+ return field;
+ }
+ }
+ return null;
+ }
+
+ public boolean hasErrors() {
+ for (BeanValidatorField<B> field : fields) {
+ if (field.hasErrors()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasWarnings() {
+ for (BeanValidatorField<B> field : fields) {
+ if (field.hasWarnings()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasInfos() {
+ for (BeanValidatorField<B> field : fields) {
+ if (field.hasInfos()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test a the validator contains the field given his name
+ *
+ * @param fieldName the name of the searched field
+ * @return <code>true</code> if validator contaisn this field, <code>false</code> otherwise
+ */
+ public boolean containsField(String fieldName) {
+ BeanValidatorField<B> field = getField(fieldName);
+ return field != null;
+ }
+
+ public boolean isValid(String fieldName) {
+ BeanValidatorField<B> field = getField(fieldName);
+ if (field == null) {
+ throw new IllegalArgumentException("could not find a validator field " + fieldName);
+ }
+ return field.isValid();
+ }
+
+ /**
+ * Permet de force la remise a false de l'etat de changement du bean
+ *
+ * @param changed flag to force reset of property {@link #changed}
+ */
+ public void setChanged(boolean changed) {
+ this.changed = changed;
+ // force the property to be fired (never pass the older value)
+ pcs.firePropertyChange(CHANGED_PROERTY, null, changed);
+ }
+
+ public void setValid(boolean valid) {
+ this.valid = valid;
+ // force the property to be fired (never pass the older value)
+ pcs.firePropertyChange(VALID_PROERTY, null, valid);
+ }
+
+ public void setBean(B bean) {
+ B oldBean = this.bean;
+ if (log.isDebugEnabled()) {
+ log.debug(this + " : " + bean);
+ }
+
+ // clean conversions of previous bean
+ conversionErrors.clear();
+
+ if (oldBean != null) {
+ try {
+ getBeanEventDescriptor(oldBean).getRemoveListenerMethod().invoke(oldBean, l);
+ } catch (Exception eee) {
+ log.info("Can't register as listener for bean " + beanClass + " for reason " + eee.getMessage(), eee);
+ }
+ }
+ this.bean = bean;
+
+ if (bean == null) {
+
+ // remove all messages for all fields of the validator
+
+ for (BeanValidatorField<B> f : fields) {
+
+ f.updateMessages(this, null, null);
+ }
+
+ } else {
+ try {
+ getBeanEventDescriptor(bean).getAddListenerMethod().invoke(bean, l);
+ } catch (Exception eee) {
+ log.info("Can't register as listener for bean " + beanClass + " for reason " + eee.getMessage(), eee);
+ }
+ validate();
+ }
+ setChanged(false);
+ setValid(!hasErrors());
+ pcs.firePropertyChange(BEAN_PROERTY, oldBean, bean);
+ }
+
+ public void setContextName(String contextName) {
+ String oldValidationContextName = this.contextName;
+ this.contextName = contextName;
+ // changing contextName could change fields definition
+ // so dettach bean, must rebuild the fields
+ if (bean != null) {
+ setBean(null);
+ }
+ // rebuild the fields
+ initFields();
+ pcs.firePropertyChange(CONTEXT_NAME_PROPERTY, oldValidationContextName, contextName);
+ }
+
+ public void setParentValidator(BeanValidator2<?> parentValidator) {
+ this.parentValidator = parentValidator;
+ }
+
+ /**
+ * Convert a value.
+ * <p/>
+ * If an error occurs, then add an error in validator.
+ *
+ * @param <T> the type of conversion
+ * @param fieldName the name of the bean property
+ * @param value the value to convert
+ * @param valueClass the type of converted value
+ * @return the converted value, or null if conversion was not ok
+ */
+ @SuppressWarnings({"unchecked"})
+ public <T> T convert(String fieldName, String value, Class<T> valueClass) {
+ if (fieldName == null) {
+ throw new IllegalArgumentException("fieldName can not be null");
+ }
+ if (valueClass == null) {
+ throw new IllegalArgumentException("valueClass can not be null");
+ }
+
+ // on ne convertit pas si il y a un bean et que le resultat de la validation
+ // pourra etre affiche quelque part
+ if (!canValidate() || value == null) {
+ return null;
+ }
+
+ // remove the previous conversion error for the field
+ conversionErrors.remove(fieldName);
+
+ T result;
+ try {
+ Converter converter = ConverterUtil.getConverter(valueClass);
+ if (converter == null) {
+ throw new RuntimeException("could not find converter for the type " + valueClass);
+ }
+ result = (T) converter.convert(valueClass, value);
+ /* Why this test ? if (result != null && !value.equals(result.toString())) {
+ conversionErrors.put(fieldName, "error.convertor." + Introspector.decapitalize(valueClass.getSimpleName()));
+ result = null;
+ validate();
+ }*/
+ } catch (ConversionException e) {
+ // get
+ conversionErrors.put(fieldName, "error.convertor." + Introspector.decapitalize(valueClass.getSimpleName()));
+ result = null;
+ validate();
+ }
+ return result;
+ }
+
+ /**
+ * il faut eviter le code re-intrant (durant une validation, une autre est
+ * demandee). Pour cela on fait la validation dans un thread, et tant
+ * que la premiere validation n'est pas fini, on ne repond pas aux
+ * solicitations.
+ * Cette method est public pour permettre de force une validation par
+ * programmation, ce qui est utile par exemple si le bean ne supporte
+ * pas les {@link PropertyChangeListener}
+ */
+ public void validate() {
+
+ // on ne valide que si il y a un bean et que le resultat de la validation
+ // pourra etre affiche quelque part
+ if (!canValidate()) {
+ return;
+ }
+
+ for (BeanValidatorScope scope : validators.keySet()) {
+
+ XWorkBeanValidator<B> validator = validators.get(scope);
+
+ Map<String, List<String>> newMessages = validator.validate(bean);
+
+ if (scope == BeanValidatorScope.ERROR) {
+ // treate conversion errors
+ // reinject them
+ for (Entry<String, String> entry : conversionErrors.entrySet()) {
+ // remove from validation, errors occurs on this field
+ List<String> errors = newMessages.get(entry.getKey());
+ String conversionError = entry.getValue();
+ if (errors != null) {
+ errors.clear();
+ errors.add(conversionError);
+ } else {
+ errors = java.util.Collections.singletonList(conversionError);
+ // add the concrete conversion error
+ newMessages.put(entry.getKey(), errors);
+ }
+ }
+ }
+
+ // for each field, update his list of messages
+ for (BeanValidatorField<B> field : fields) {
+ List<String> messagesForField = newMessages.get(field.getName());
+ if (field.getScopes().contains(scope)) {
+ field.updateMessages(this, scope, messagesForField);
+ }
+ }
+ }
+
+ if (parentValidator != null) {
+ // chained validation
+ parentValidator.l.propertyChange(null);
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "<beanClass:" + beanClass + ", contextName:" + contextName + ">";
+ }
+
+ public void addBeanValidatorListener(BeanValidatorListener listener) {
+ listenerList.add(BeanValidatorListener.class, listener);
+ }
+
+ public void removeBeanValidatorListener(BeanValidatorListener listener) {
+ listenerList.remove(BeanValidatorListener.class, listener);
+ }
+
+ public BeanValidatorListener[] getBeanValidatorListeners() {
+ return listenerList.getListeners(BeanValidatorListener.class);
+ }
+
+ 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);
+ }
+
+ /** @return <code>true</code> if validation is enabled, <code>false</code> otherwise. */
+ protected boolean canValidate() {
+ return !(bean == null || fields.isEmpty());
+ }
+
+ protected void fireFieldChanged(BeanValidatorField<B> field, BeanValidatorScope scope, String[] toAdd, String[] toDelete) {
+
+ BeanValidatorEvent evt = new BeanValidatorEvent(this, field, scope, toAdd, toDelete);
+
+ for (BeanValidatorListener listener : listenerList.getListeners(BeanValidatorListener.class)) {
+ listener.onFieldChanged(evt);
+ }
+ }
+
+ protected synchronized void initFields() {
+
+ Set<String> detectedFieldNames = new java.util.HashSet<String>();
+ EnumMap<BeanValidatorScope, Set<String>> tmp = new EnumMap<BeanValidatorScope, Set<String>>(BeanValidatorScope.class);
+ Set<BeanValidatorField<B>> detectedFields = new java.util.HashSet<BeanValidatorField<B>>();
+
+ validators.clear();
+
+ for (BeanValidatorScope scope : BeanValidatorScope.values()) {
+ String scopeContext = (contextName == null ? "" : contextName + "-") + scope.name().toLowerCase();
+
+ XWorkBeanValidator<B> newValidator = new XWorkBeanValidator<B>(beanClass, scopeContext, false);
+ Set<String> fieldNames = newValidator.getFieldNames();
+ if (log.isDebugEnabled()) {
+ log.debug("detected validators for scope " + scopeContext + " : " + fieldNames);
+ }
+ if (!fieldNames.isEmpty()) {
+ // fields detected in this validator, keep it
+ validators.put(scope, newValidator);
+ detectedFieldNames.addAll(fieldNames);
+ tmp.put(scope, fieldNames);
+ }
+ }
+
+ List<BeanValidatorScope> scopes = new ArrayList<BeanValidatorScope>();
+ for (String fieldName : detectedFieldNames) {
+ scopes.clear();
+ // detect scopes for the field
+ for (BeanValidatorScope scope : BeanValidatorScope.values()) {
+ if (tmp.containsKey(scope) && tmp.get(scope).contains(fieldName)) {
+ scopes.add(scope);
+ }
+ }
+ BeanValidatorField<B> f = new BeanValidatorField<B>(beanClass, fieldName, scopes);
+ detectedFields.add(f);
+ }
+ tmp.clear();
+ detectedFieldNames.clear();
+
+ this.fields = java.util.Collections.unmodifiableSet(detectedFields);
+ }
+
+ protected EventSetDescriptor getBeanEventDescriptor(B bean) {
+ if (beanEventDescriptor == null) {
+ // check that the bean is listenable, otherwise, can't use the validator on it
+ this.beanEventDescriptor = ValidationUtil.getPropertyChangeListenerDescriptor(bean.getClass());
+ }
+ return beanEventDescriptor;
+ }
+}
Added: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorEvent.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorEvent.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorEvent.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,52 @@
+package jaxx.runtime.validator;
+
+/**
+ * The definition of an event on {@link BeanValidatorListener}
+ * to be fired by a {@link BeanValidator}.
+ *
+ * @author chemit
+ * @since 1.3
+ */
+public class BeanValidatorEvent extends java.util.EventObject {
+
+ private static final long serialVersionUID = 1L;
+ /** the field impacted by the validator */
+ BeanValidatorField<?> field;
+ /** the scope impacted by the event */
+ BeanValidatorScope scope;
+ String[] messagestoAdd;
+ String[] messagestoDelete;
+
+ public BeanValidatorEvent(BeanValidator2 source, BeanValidatorField<?> field, BeanValidatorScope scope, String[] toAdd, String[] toDelete) {
+ super(source);
+ this.field = field;
+ this.scope = scope;
+ this.messagestoAdd = toAdd;
+ this.messagestoDelete = toDelete;
+ }
+
+ @Override
+ public BeanValidator2 getSource() {
+ return (BeanValidator2) super.getSource();
+ }
+
+ public String getFieldName() {
+ return field.getName();
+ }
+
+ public String[] getMessagesToAdd() {
+ return messagestoAdd;
+ }
+
+ public String[] getMessagesToDelete() {
+ return messagestoDelete;
+ }
+
+ public BeanValidatorScope getScope() {
+ return scope;
+ }
+
+ public BeanValidatorField getField() {
+ return field;
+ }
+}
Added: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorField.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorField.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorField.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,239 @@
+package jaxx.runtime.validator;
+
+import static org.codelutin.i18n.I18n._;
+
+import javax.swing.event.EventListenerList;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * Definition of a field to be handled in a {@link BeanValidator}.
+ * <p/>
+ * A such class is only registred in {@link BeanValidator } when the field of the bean
+ * was found in validator xml configuration file for a {@link com.opensymphony.xwork2.validator.FieldValidator} only.
+ * <p/>
+ * This class use properties {@link #beanClass}, {@link #name} to define
+ * his naturel order.
+ *
+ * @author chemit
+ * @param <B> the type of the bean handled by the validator and this field of validation.
+ * @since 1.3
+ */
+public class BeanValidatorField<B> {
+
+ /** the class of bean */
+ protected final Class<B> beanClass;
+ /** name of field in bean */
+ protected final String name;
+ protected EnumMap<BeanValidatorScope, Set<String>> messages;
+ /** A list of event listeners for this validators */
+ protected EventListenerList listenerList = new EventListenerList();
+
+ public BeanValidatorField(Class<B> beanClass, String name, List<BeanValidatorScope> scopes) {
+ this.beanClass = beanClass;
+ this.name = name;
+ messages = new EnumMap<BeanValidatorScope, Set<String>>(BeanValidatorScope.class);
+ for (BeanValidatorScope scope : scopes) {
+ messages.put(scope, new HashSet<String>());
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Class<B> getBeanClass() {
+ return beanClass;
+ }
+
+ /**
+ * @return <code>true</code> if this field is valid (says is in error
+ * scope and has errors), <code>false</code> otherwise.
+ */
+ public boolean isValid() {
+ return !hasErrors();
+ }
+
+ public BeanValidatorScope getScope() {
+ if (hasErrors()) {
+ return BeanValidatorScope.ERROR;
+ }
+ if (hasWarnings()) {
+ return BeanValidatorScope.WARNING;
+ }
+ if (hasInfos()) {
+ return BeanValidatorScope.INFO;
+ }
+ return null;
+ }
+
+ public Set<BeanValidatorScope> getScopes() {
+ return messages.keySet();
+ }
+
+ public boolean hasErrors() {
+ return hasMessages(BeanValidatorScope.ERROR);
+ }
+
+ public boolean hasWarnings() {
+ return hasMessages(BeanValidatorScope.WARNING);
+ }
+
+ public boolean hasInfos() {
+ return hasMessages(BeanValidatorScope.INFO);
+ }
+
+ public Set<String> getErrors() {
+ return getMessages(BeanValidatorScope.ERROR);
+ }
+
+ public Set<String> getWarnings() {
+ return getMessages(BeanValidatorScope.WARNING);
+ }
+
+ public Set<String> getInfos() {
+ return getMessages(BeanValidatorScope.INFO);
+ }
+
+ public boolean hasMessages(BeanValidatorScope scope) {
+ return messages.containsKey(scope) && !getMessages(scope).isEmpty();
+ }
+
+ public Set<String> getMessages(BeanValidatorScope scope) {
+ return messages.get(scope);
+ }
+
+ public void updateMessages(BeanValidator2<B> validator, BeanValidatorScope scope, List<String> messages) {
+
+ if (scope == null) {
+
+ // special case to reset all messages from all scopes
+
+ for (BeanValidatorScope s : getScopes()) {
+
+ clearMessages(s, validator);
+ }
+ return;
+ }
+
+ if (!this.messages.containsKey(scope)) {
+ throw new IllegalArgumentException("the scope " + scope + " was not registred for " + this);
+ }
+
+ if (messages == null || messages.isEmpty()) {
+
+ // no incoming message for this scope
+
+ clearMessages(scope, validator);
+ return;
+ }
+
+ // build the diff of messages (the one to delete, the one to add)
+
+ boolean hasChanged = false;
+
+ Set<String> currentMessages = getMessages(scope);
+
+ // detect messages to delete
+ Set<String> toDelete = new java.util.HashSet<String>(currentMessages);
+ toDelete.removeAll(messages);
+
+ if (!toDelete.isEmpty()) {
+ // apply delete
+ currentMessages.removeAll(toDelete);
+ hasChanged = true;
+ }
+
+ // detect messages to add
+ Set<String> toAdd = new java.util.HashSet<String>(messages);
+ toAdd.removeAll(currentMessages);
+
+ if (!toAdd.isEmpty()) {
+ // apply add
+ currentMessages.addAll(toAdd);
+ hasChanged = true;
+ }
+
+ if (hasChanged) {
+
+ // something has changed, fire notifications
+ String[] del = toDelete.toArray(new String[toDelete.size()]);
+ String[] add = toAdd.toArray(new String[toAdd.size()]);
+
+ validator.fireFieldChanged(this, scope, add, del);
+ }
+ toAdd.clear();
+ toDelete.clear();
+
+ }
+
+ public String getI18nError(String error) {
+ String text;
+ if (error.indexOf("##") == -1) {
+ text = _(error);
+ } else {
+ StringTokenizer stk = new StringTokenizer(error, "##");
+ String errorName = stk.nextToken();
+ List<String> args = new ArrayList<String>();
+ while (stk.hasMoreTokens()) {
+ args.add(stk.nextToken());
+ }
+ text = _(errorName, args.toArray());
+ }
+ return text;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof BeanValidatorField)) {
+ return false;
+ }
+
+ BeanValidatorField that = (BeanValidatorField) o;
+ return beanClass.equals(that.beanClass) && name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = beanClass.hashCode();
+ result = 31 * result + name.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("<").append(super.toString());
+ sb.append(" beanClass:").append(beanClass);
+ sb.append(", name:").append(name);
+ sb.append(", scopes:").append(messages == null ? "[]" : messages.keySet());
+ sb.append(", scope:").append(getScope());
+ //sb.append(", errors:").append(errors);
+ sb.append('>');
+ return sb.toString();
+ }
+
+ protected void clearMessages(BeanValidatorScope scope, BeanValidator2<B> validator) {
+ // remove all messages
+ Set<String> toDelete = getMessages(scope);
+
+ if (!toDelete.isEmpty()) {
+
+ // there is some messages to delete
+ String[] toDel = toDelete.toArray(new String[toDelete.size()]);
+
+ // apply deletion
+ toDelete.clear();
+
+ // fire
+ validator.fireFieldChanged(this, scope, null, toDel);
+ }
+ }
+}
Added: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorListener.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorListener.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorListener.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,32 @@
+package jaxx.runtime.validator;
+
+/**
+ * The listener contract to be used on {@link BeanValidator]
+ *
+ * @author chemit
+ * @since 1.3
+ */
+public interface BeanValidatorListener extends java.util.EventListener {
+
+ /**
+ * Invoked when a validator detects some changes on a field.
+ *
+ * @param event the event
+ */
+ void onFieldChanged(BeanValidatorEvent event);
+
+ /**
+ * Invoked when a validator detects a new message on a field.
+ *
+ * @param event the event
+ */
+ //void onNewMessages(BeanValidatorEvent event);
+
+ /**
+ * Invoked when a validator detetcs that a previously message is
+ * no more exisitng.
+ *
+ * @param event the event
+ */
+ //void onResolvedMessages(BeanValidatorEvent event);
+}
Copied: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java (from rev 1250, jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorScope.java)
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,34 @@
+package jaxx.runtime.validator;
+
+/**
+ * The differents levels of messages in validation process.
+ * <p/>
+ * The order of the enum defines the severity of validation.
+ * <p/>
+ * Always begin with error, then if no error found, try warning, then info...
+ *
+ * @author chemit
+ */
+public enum BeanValidatorScope {
+ /**
+ * the error scope level.
+ *
+ * When a message of a such scope is found on a validator, then the validator
+ * is invalid and modified.
+ */
+ ERROR,
+ /**
+ * the warning scope level.
+ *
+ * When a message of a such scope is found on a validator, then the validator
+ * is still valid but modified.
+ */
+ WARNING,
+ /**
+ * the information scope level.
+ *
+ * When a message of a sucg scope is found on a validator, then the
+ * validator is still valid and not modified.
+ */
+ INFO
+}
Property changes on: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/BeanValidatorScope.java
___________________________________________________________________
Name: svn:mergeinfo
+
Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidationUtil.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidationUtil.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidationUtil.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -6,6 +6,7 @@
import org.apache.commons.logging.LogFactory;
import java.beans.BeanInfo;
+import java.beans.EventSetDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
@@ -50,7 +51,7 @@
}
}
for (String validatorId : validatorIds) {
- BeanValidator beanValidator = jaxxValidator.getValidator(validatorId);
+ BeanValidator2 beanValidator = jaxxValidator.getValidator(validatorId);
if (bean == null || beanValidator.getBeanClass().isAssignableFrom(bean.getClass())) {
// touch validator, only if fits the bean type (or bean is null)
beanValidator.setBean(bean);
@@ -81,7 +82,7 @@
}
}
for (String validatorId : validatorIds) {
- BeanValidator beanValidator = jaxxValidator.getValidator(validatorId);
+ BeanValidator2 beanValidator = jaxxValidator.getValidator(validatorId);
beanValidator.setChanged(newValue);
}
}
@@ -120,4 +121,33 @@
// otherwise, bean value has not changed,...
}
}
+
+ static EventSetDescriptor getPropertyChangeListenerDescriptor(Class beanClass) {
+ try {
+ // check that the bean is listenable, otherwise, can't use
+ // the validator on it
+ BeanInfo infos = Introspector.getBeanInfo(beanClass);
+ EventSetDescriptor[] events = infos.getEventSetDescriptors();
+ for (EventSetDescriptor event : events) {
+ if ("propertyChange".equals(event.getName())) {
+
+ if (event.getAddListenerMethod() == null) {
+ // no property event listener, so can not use the validator
+ throw new IllegalStateException("no addPropertyChangeListener method found for " + beanClass);
+ }
+ if (event.getRemoveListenerMethod() == null) {
+ // no property event listener, so can not use the validator
+ throw new IllegalStateException("no removePropertyChangeListener method found for " + beanClass);
+ }
+ return event;
+ }
+ }
+
+ // no property event listener, so can not use the validator
+ throw new IllegalStateException("no PropertyChangeListener access method found for " + beanClass);
+ } catch (IntrospectionException ex) {
+ throw new IllegalStateException("could not acquire PropertyChangeListener bean info for " + beanClass + " for reason " + ex.getMessage(), ex);
+ }
+ }
+
}
Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorEvent.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorEvent.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorEvent.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -10,6 +10,7 @@
*
* @author chemit
*/
+@Deprecated
public class ValidatorErrorEvent {
/** the source of the event */
Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorListener.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorListener.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorErrorListener.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -5,6 +5,7 @@
*
* @author chemit
*/
+@Deprecated
public interface ValidatorErrorListener extends java.util.EventListener {
/**
* Invoked when a validator detects a error on a field.
Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorField.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorField.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorField.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -23,6 +23,7 @@
* @author chemit
* @param <B> the type of the bean handled by the validator and this field of validation.
*/
+@Deprecated
public class ValidatorField<B> {
/** the class of bean */
Deleted: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorScope.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorScope.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/ValidatorScope.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,16 +0,0 @@
-package jaxx.runtime.validator;
-
-/**
- * The differents levels of validation.
- * <p/>
- * The order of the enum defines the severity of validation.
- * <p/>
- * Always begin with error, then if no error found, try warning, ...
- *
- * @author chemit
- */
-public enum ValidatorScope {
- ERROR,
- WARNING,
- INFO
-}
Added: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/XWorkBeanValidator.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,230 @@
+package jaxx.runtime.validator;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ValidationAwareSupport;
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationManager;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import com.opensymphony.xwork2.validator.ActionValidatorManager;
+import com.opensymphony.xwork2.validator.DelegatingValidatorContext;
+import com.opensymphony.xwork2.validator.FieldValidator;
+import com.opensymphony.xwork2.validator.ValidationException;
+import com.opensymphony.xwork2.validator.Validator;
+import java.util.Collection;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * A customized validator for a given bean.
+ *
+ * Use the method {@link #validate(java.lang.Object)} to obtain the messages
+ * detected by the validator for the given bean.
+ *
+ * @param <B> type of the bean to validate.
+ *
+ * @author chemit
+ * @since 1.3
+ */
+public class XWorkBeanValidator<B> {
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ private static final Log log = LogFactory.getLog(XWorkBeanValidator.class);
+ private final static Map<String, List<String>> EMPTY_RESULT = Collections.unmodifiableMap(new HashMap<String, List<String>>());
+ /** the type of bean to validate */
+ protected final Class<B> beanClass;
+ /** the validation named context (can be null) */
+ protected String contextName;
+ /** the list of field names detected for this validator */
+ protected Set<String> fieldNames;
+ /** a flag to include or not the default context validators */
+ protected boolean includeDefaultContext;
+ // --
+ // XWorks fields
+ // --
+ protected ValidationAwareSupport validationSupport;
+ protected DelegatingValidatorContext validationContext;
+ protected transient ActionValidatorManager validator;
+ protected ActionContext context;
+
+ public XWorkBeanValidator(Class<B> beanClass, String contextName) {
+ this(beanClass, contextName, true);
+ }
+
+ public XWorkBeanValidator(Class<B> beanClass, String contextName, boolean includeDefaultContext) {
+
+ this.beanClass = beanClass;
+ this.includeDefaultContext = includeDefaultContext;
+ validationSupport = new ValidationAwareSupport();
+ validationContext = new DelegatingValidatorContext(validationSupport);
+
+ // init context
+ ConfigurationManager confManager = new ConfigurationManager();
+ Configuration conf = confManager.getConfiguration();
+
+ ValueStack vs = conf.getContainer().getInstance(ValueStackFactory.class).createValueStack();
+ context = new ActionContext(vs.getContext());
+ ActionContext.setContext(context);
+
+ // init validator
+ validator = conf.getContainer().getInstance(ActionValidatorManager.class, "no-annotations");
+
+ // init context
+ setContextName(contextName);
+ }
+
+ public boolean isIncludeDefaultContext() {
+ return includeDefaultContext;
+ }
+
+ public Class<B> getBeanClass() {
+ return beanClass;
+ }
+
+ public String getContextName() {
+ return contextName;
+ }
+
+ public Set<String> getFieldNames() {
+ return fieldNames;
+ }
+
+ /**
+ * Test a the validator contains the field given his name
+ *
+ * @param fieldName the name of the searched field
+ * @return <code>true</code> if validator contaisn this field, <code>false</code> otherwise
+ */
+ public boolean containsField(String fieldName) {
+ return fieldNames.contains(fieldName);
+ }
+
+ public void setIncludeDefaultContext(boolean includeDefaultContext) {
+ this.includeDefaultContext = includeDefaultContext;
+ if (contextName != null) {
+ // reload context
+ setContextName(contextName);
+ }
+ }
+
+ public void setContextName(String contextName) {
+ this.contextName = contextName;
+ // changing contextName may change fields definition
+ // so reload fields
+ initFields();
+ }
+
+ /**
+ * Valide le bean donné et retourne les messages produits.
+ *
+ * @param bean le bean a valider (il doit etre non null)
+ *
+ * @return le dictionnaire des messages produits par la validation indexées
+ * par le nom du champs du bean impacté.
+ */
+ public Map<String, List<String>> validate(B bean) {
+
+ if (bean == null) {
+ throw new NullPointerException("bean can not be null in method validate");
+ }
+
+ Map<String, List<String>> result = EMPTY_RESULT;
+
+ // on lance la validation uniquement si des champs sont a valider
+ if (!fieldNames.isEmpty()) {
+
+ try {
+
+ //TC - 20081024 : since context is in a ThreadLocal variable, we must do the check
+ if (ActionContext.getContext() == null) {
+ ActionContext.setContext(context);
+ }
+
+ validator.validate(bean, contextName, validationContext);
+
+ if (log.isTraceEnabled()) {
+ log.trace("Action errors: " + validationContext.getActionErrors());
+ log.trace("Action messages: " + validationContext.getActionMessages());
+ log.trace("Field errors: " + validationContext.getFieldErrors());
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug(this + " : " + validationContext.getFieldErrors());
+ }
+
+ if (validationContext.hasFieldErrors()) {
+ Map messages = validationContext.getFieldErrors();
+ result = new HashMap<String, List<String>>(messages.size());
+ for (Object fieldName : messages.keySet()) {
+ Collection c = (Collection) messages.get(fieldName);
+ List<String> mm = new java.util.ArrayList<String>(c.size());
+ for (Object message : c) {
+ mm.add(message + "");
+ }
+ result.put(fieldName + "", mm);
+ }
+ }
+
+ } catch (ValidationException eee) {
+ log.warn("Error during validation on " + beanClass + " for reason : " + eee.getMessage(), eee);
+
+ } finally {
+ // on nettoye toujours le validateur apres operation
+ validationSupport.clearErrorsAndMessages();
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "<beanClass:" + beanClass + ", contextName:" + contextName + ">";
+ }
+
+ /**
+ * update the property {@link #fieldNames}, says search in XWorks
+ */
+ protected synchronized void initFields() {
+
+ if (fieldNames != null) {
+ fieldNames = null;
+ }
+
+ Set<String> detectedFieldNames = new java.util.HashSet<String>();
+
+ int skip = 0;
+ if (contextName != null && !includeDefaultContext) {
+ // count the number of validator to skip
+ for (Validator v : validator.getValidators(beanClass, null)) {
+ // we only work on FieldValidator at the moment
+ if (v instanceof FieldValidator) {
+ skip++;
+ }
+ }
+ }
+
+ for (Validator v : validator.getValidators(beanClass, contextName)) {
+ // we only work on FieldValidator at the moment
+ if (v instanceof FieldValidator) {
+ if (skip > 0) {
+ skip--;
+ continue;
+ }
+ FieldValidator fieldValidator = (FieldValidator) v;
+ log.debug("context " + contextName + " - field " + fieldValidator.getFieldName());
+ String fName = fieldValidator.getFieldName();
+ detectedFieldNames.add(fName);
+ }
+ }
+
+ fieldNames = Collections.unmodifiableSet(detectedFieldNames);
+ }
+}
Modified: jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field/CollectionFieldExpressionValidator.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -12,8 +12,8 @@
*/
public class CollectionFieldExpressionValidator extends FieldExpressionValidator {
-
public enum Mode {
+
/** au moins une entrée de la collection doit etre valide */
AT_LEAST_ONE,
/** exactement une entrée dela collection doit être valide */
@@ -23,7 +23,6 @@
/** aucune valeur de la collection doivent etre valides */
NONE
}
-
/** le mode de validation sur la liste */
protected Mode mode;
@@ -35,10 +34,6 @@
this.mode = mode;
}
- public void setMode(String mode) {
- this.mode = Mode.valueOf(mode);
- }
-
@Override
public void validate(Object object) throws ValidationException {
if (mode == null) {
@@ -188,5 +183,4 @@
public String getValidatorType() {
return "collectionFieldExpression";
}
-
}
Deleted: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/AbstractValidatorTest.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/AbstractValidatorTest.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/AbstractValidatorTest.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,44 +0,0 @@
-package jaxx.runtime.validator;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-
-import java.io.File;
-
-/**
- * Abstract class of this module.
- *
- * @author chemit
- */
-public abstract class AbstractValidatorTest extends Assert {
-
- static protected BeanValidator<ValidatorBean> validator;
-
- static protected File basedir;
-
- protected ValidatorBean bean;
-
- @BeforeClass
- public static void initValidator() throws Exception {
-
- String b = System.getenv("basedir");
- if (b == null) {
- b = new File("").getAbsolutePath();
- }
- basedir = new File(b);
- validator = new BeanValidator<ValidatorBean>(ValidatorBean.class, null);
- }
-
- protected void assertFieldInError(String fieldName, String error, boolean required) {
- ValidatorField<ValidatorBean> field = validator.getField(fieldName);
-
- for (String o : field.getErrors()) {
- if (o.equals(error)) {
- assertTrue(required);
- return;
- }
- }
- // error was not found
- assertFalse(required);
- }
-}
\ No newline at end of file
Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/BeanValidatorTest.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/BeanValidatorTest.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/BeanValidatorTest.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,33 +1,198 @@
package jaxx.runtime.validator;
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
/**
- * Une classe pour tester {@link BeanValidator}
*
- * @author chemit
+ * @author tony
*/
-public class BeanValidatorTest extends AbstractValidatorTest {
+public class BeanValidatorTest {
- //TODO do other tests :)
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ static protected final Log log = LogFactory.getLog(BeanValidator2.class);
+ protected BeanValidator2<SimpleBean> validator;
+ protected SimpleBean bean;
+ BeanValidatorListenerImpl errorListener;
+ BeanValidatorListenerImpl warningListener;
+ BeanValidatorListenerImpl infoListener;
+ @Before
+ public void setUp() {
+ bean = new SimpleBean();
+ validator = new BeanValidator2<SimpleBean>(SimpleBean.class, null);
+ validator.addBeanValidatorListener(errorListener = new BeanValidatorListenerImpl(BeanValidatorScope.ERROR));
+ validator.addBeanValidatorListener(warningListener = new BeanValidatorListenerImpl(BeanValidatorScope.WARNING));
+ validator.addBeanValidatorListener(infoListener = new BeanValidatorListenerImpl(BeanValidatorScope.INFO));
+ }
+
+ @After
+ public void tearDown() {
+ bean = null;
+ if (validator != null) {
+ validator.setBean(null);
+ validator = null;
+ }
+ }
+ private static final String STRING_VALUE_ERROR = "stringValue.error";
+ private static final String STRING_VALUE_WARNING = "stringValue.warning";
+ private static final String INT_VALUE_ERROR = "intValue.error";
+ private static final String INT_VALUE_INFO = "intValue.info";
+
@Test
- public void testSetBean() {
- bean = new ValidatorBean();
+ public void testValidate() {
- assertNull(bean.getStringValue());
+ assertMessages(errorListener);
+ assertMessages(warningListener);
+ assertMessages(infoListener);
- // no bean on validator
- assertNull(validator.getBean());
- assertTrue(validator.isValid());
+ log.info("-----------------------------------------------");
+ validator.setBean(bean);
- // add bean to validator
+ assertMessages(errorListener, STRING_VALUE_ERROR, INT_VALUE_ERROR);
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
+ bean.setStringValue("one");
+
+ assertMessages(errorListener, INT_VALUE_ERROR);
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
+ bean.setStringValue("oneone");
+
+ assertMessages(errorListener, INT_VALUE_ERROR);
+ assertMessages(warningListener);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
+ bean.setIntValue(1);
+
+ assertMessages(errorListener);
+ assertMessages(warningListener);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
+ bean.setIntValue(10);
+
+ assertMessages(errorListener);
+ assertMessages(warningListener);
+ assertMessages(infoListener);
+
+ log.info("-----------------------------------------------");
+
+ bean.setStringValue(null);
+ bean.setIntValue(0);
+
+ assertMessages(errorListener, STRING_VALUE_ERROR, INT_VALUE_ERROR);
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+
+ log.info("-----------------------------------------------");
+ }
+
+ @Test
+ public void testConvert() {
+
+
+ assertMessages(errorListener);
+ assertMessages(warningListener);
+ assertMessages(infoListener);
+
+ log.info("-----------------------------------------------");
+
validator.setBean(bean);
- assertFieldInError("stringValue", "stringValue.required", true);
- validator.setBean(null);
- // validator is valid, no more errors should be in validator
- assertTrue(validator.isValid());
+ assertMessages(errorListener, STRING_VALUE_ERROR, INT_VALUE_ERROR);
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+
+ log.info("-----------------------------------------------");
+
+ Object value = validator.convert("intValue", "abc", Class.class);
+
+ Assert.assertNull(value);
+
+ assertMessages(errorListener, STRING_VALUE_ERROR, "error.convertor.class");
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
+ bean.setStringValue("one");
+
+ assertMessages(errorListener, "error.convertor.class");
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
+
+ value = validator.convert("intValue", "3", Integer.class);
+
+ bean.setIntValue((Integer) value);
+
+ assertMessages(errorListener);
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
+
+ bean.setIntValue(-1);
+ assertMessages(errorListener, INT_VALUE_ERROR);
+ assertMessages(warningListener, STRING_VALUE_WARNING);
+ assertMessages(infoListener, INT_VALUE_INFO);
+
+ log.info("-----------------------------------------------");
}
-}
+ void assertMessages(BeanValidatorListenerImpl listener, String... expected) {
+ List<String> actual = listener.getMessages();
+ Assert.assertEquals(" shoudl have " + java.util.Arrays.toString(expected) + " but had " + actual, expected.length, actual.size());
+ for (String m : expected) {
+ Assert.assertEquals("could not find " + m + " in " + actual, true, actual.contains(m));
+ }
+ }
+
+ class BeanValidatorListenerImpl implements BeanValidatorListener {
+
+ final BeanValidatorScope scope;
+
+ public BeanValidatorListenerImpl(BeanValidatorScope scope) {
+ this.scope = scope;
+ }
+ java.util.List<String> messages = new java.util.ArrayList<String>();
+
+ public List<String> getMessages() {
+ return messages;
+ }
+
+ @Override
+ public void onFieldChanged(BeanValidatorEvent event) {
+ if (scope != event.getScope()) {
+ return;
+ }
+ String[] messagesToDelete = event.getMessagesToDelete();
+ if (messagesToDelete != null && messagesToDelete.length > 0) {
+ log.info(event.getScope() + " messages to delete : " + java.util.Arrays.toString(messagesToDelete));
+ for (String m : messagesToDelete) {
+ messages.remove(m);
+ }
+ }
+ String[] messagesToAdd = event.getMessagesToAdd();
+ if (messagesToAdd != null && messagesToAdd.length > 0) {
+ log.info(event.getScope() + " messages to add : " + java.util.Arrays.toString(messagesToAdd));
+ for (String m : messagesToAdd) {
+ messages.add(m);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Added: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/SimpleBean.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/SimpleBean.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/SimpleBean.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,51 @@
+package jaxx.runtime.validator;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+
+public class SimpleBean {
+
+ protected int intValue;
+ protected String stringValue;
+ final PropertyChangeSupport p;
+
+ public SimpleBean() {
+ p = new PropertyChangeSupport(this);
+ }
+
+ public int getIntValue() {
+ return intValue;
+ }
+
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ public void setStringValue(String stringValue) {
+ String old = this.stringValue;
+ this.stringValue = stringValue;
+ p.firePropertyChange("stringValue", old, stringValue);
+ }
+
+ public void setIntValue(int intValue) {
+ int old = this.intValue;
+ this.intValue = intValue;
+ p.firePropertyChange("intValue", old, intValue);
+ }
+
+ 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);
+ }
+}
\ No newline at end of file
Added: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/XWorkBeanValidatorTest.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/XWorkBeanValidatorTest.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/XWorkBeanValidatorTest.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,156 @@
+package jaxx.runtime.validator;
+
+import java.util.List;
+import java.util.Map;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ * @author tony
+ * @since 1.3
+ */
+public class XWorkBeanValidatorTest {
+
+ protected XWorkBeanValidator<SimpleBean> validator;
+ protected SimpleBean bean;
+ protected Map<String, List<String>> messages;
+
+ @Before
+ public void setUp() {
+ bean = new SimpleBean();
+ validator = new XWorkBeanValidator<SimpleBean>(SimpleBean.class, "simple");
+ }
+
+ @After
+ public void tearDown() {
+ bean = null;
+ messages = null;
+ }
+
+ @Test
+ public void testUnknownField() {
+ Assert.assertEquals(false, validator.containsField("fake_" + System.nanoTime()));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testValidateNPE() {
+ validator.validate(null);
+ }
+
+ @Test
+ public void testValidate() {
+
+
+ messages = validator.validate(bean);
+
+ assertFieldInError("stringValue", "stringValue.null", true, messages);
+ assertFieldInError("intValue", "intValue.null", true, messages);
+
+ bean.setStringValue("notnull");
+ messages = validator.validate(bean);
+
+ assertFieldInError("stringValue", "stringValue.null", false, messages);
+ assertFieldInError("intValue", "intValue.null", true, messages);
+
+ bean.setIntValue(1);
+ messages = validator.validate(bean);
+
+ assertFieldInError("stringValue", "stringValue.null", false, messages);
+ assertFieldInError("intValue", "intValue.null", false, messages);
+
+ }
+
+ @Test
+ public void testSetContextName() {
+
+
+ String expected = "simple";
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(true, validator.containsField("stringValue"));
+ Assert.assertEquals(true, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "error");
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(true, validator.containsField("stringValue"));
+ Assert.assertEquals(true, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "warning");
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(true, validator.containsField("stringValue"));
+ Assert.assertEquals(false, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "info");
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(false, validator.containsField("stringValue"));
+ Assert.assertEquals(true, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "fake_" + System.nanoTime());
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(false, validator.containsField("stringValue"));
+ Assert.assertEquals(false, validator.containsField("intValue"));
+
+ }
+
+ @Test
+ public void testSetIncludeDefaultContext() {
+
+ validator.setIncludeDefaultContext(false);
+
+ String expected = "simple";
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(true, validator.containsField("stringValue"));
+ Assert.assertEquals(true, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "error");
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(true, validator.containsField("stringValue"));
+ Assert.assertEquals(true, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "warning");
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(true, validator.containsField("stringValue"));
+ Assert.assertEquals(false, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "info");
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(false, validator.containsField("stringValue"));
+ Assert.assertEquals(true, validator.containsField("intValue"));
+
+ validator.setContextName(expected = "fake_" + System.nanoTime());
+
+ Assert.assertEquals(expected, validator.getContextName());
+ Assert.assertEquals(false, validator.containsField("stringValue"));
+ Assert.assertEquals(false, validator.containsField("intValue"));
+
+ }
+
+ protected void assertFieldInError(String fieldName, String error, boolean required, Map<String, List<String>> messages) {
+
+ Assert.assertEquals(true, validator.containsField(fieldName));
+ List<String> fieldMessages = messages.get(fieldName);
+ //Assert.assertEquals(true,validator.containsField(fieldName));
+ if (fieldMessages != null) {
+ for (String o : fieldMessages) {
+ if (o.equals(error)) {
+ Assert.assertTrue(required);
+ return;
+ }
+ }
+ }
+
+ // error was not found
+ Assert.assertFalse(required);
+ }
+}
\ No newline at end of file
Modified: jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/java/jaxx/runtime/validator/field/AbstractFieldValidatorTest.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,11 +1,15 @@
package jaxx.runtime.validator.field;
-import jaxx.runtime.validator.AbstractValidatorTest;
+import java.io.File;
+import jaxx.runtime.validator.BeanValidator;
import jaxx.runtime.validator.ValidatorBean;
+import jaxx.runtime.validator.ValidatorField;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
+import org.junit.BeforeClass;
/**
* Abstract class to test a specific validator.
@@ -15,10 +19,13 @@
*
* @author chemit
*/
-public abstract class AbstractFieldValidatorTest extends AbstractValidatorTest {
+public abstract class AbstractFieldValidatorTest extends Assert {
/** to use log facility, just put in your code: log.info(\"...\"); */
static private final Log log = LogFactory.getLog(AbstractFieldValidatorTest.class);
+ static protected BeanValidator<ValidatorBean> validator;
+ static protected File basedir;
+ protected ValidatorBean bean;
/**
* the moethod to implements testing the given validator on the given bean.
@@ -29,7 +36,7 @@
@Before
public void setUp() throws Exception {
- log.info("start test " + getClass().getSimpleName());
+ log.debug("start test " + getClass().getSimpleName());
validator.setBean(bean = new ValidatorBean());
}
@@ -38,4 +45,27 @@
validator.setBean(null);
}
+ @BeforeClass
+ public static void initValidator() throws Exception {
+
+ String b = System.getenv("basedir");
+ if (b == null) {
+ b = new File("").getAbsolutePath();
+ }
+ basedir = new File(b);
+ validator = new BeanValidator<ValidatorBean>(ValidatorBean.class, null);
+ }
+
+ protected void assertFieldInError(String fieldName, String error, boolean required) {
+ ValidatorField<ValidatorBean> field = validator.getField(fieldName);
+
+ for (String o : field.getErrors()) {
+ if (o.equals(error)) {
+ assertTrue(required);
+ return;
+ }
+ }
+ // error was not found
+ assertFalse(required);
+ }
}
\ No newline at end of file
Added: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-error-validation.xml
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-error-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-error-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,19 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+
+ <field name="stringValue">
+ <field-validator type="requiredstring">
+ <message>stringValue.error</message>
+ </field-validator>
+ </field>
+
+ <field name="intValue">
+ <field-validator type="int">
+ <param name="min">1</param>
+ <message>intValue.error</message>
+ </field-validator>
+ </field>
+
+</validators>
\ No newline at end of file
Added: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-info-validation.xml
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-info-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-info-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,13 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+
+ <field name="intValue">
+ <field-validator type="int">
+ <param name="min">10</param>
+ <message>intValue.info</message>
+ </field-validator>
+ </field>
+
+</validators>
\ No newline at end of file
Added: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-simple-validation.xml
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-simple-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-simple-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,19 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+
+ <field name="stringValue">
+ <field-validator type="requiredstring">
+ <message>stringValue.null</message>
+ </field-validator>
+ </field>
+
+ <field name="intValue">
+ <field-validator type="int">
+ <param name="min">1</param>
+ <message>intValue.null</message>
+ </field-validator>
+ </field>
+
+</validators>
\ No newline at end of file
Added: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-warning-validation.xml
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-warning-validation.xml (rev 0)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/SimpleBean-warning-validation.xml 2009-03-19 22:47:05 UTC (rev 1272)
@@ -0,0 +1,13 @@
+<!DOCTYPE validators PUBLIC
+ "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
+ "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
+<validators>
+
+ <field name="stringValue">
+ <field-validator type="fieldexpression">
+ <param name="expression"><![CDATA[ stringValue != null && stringValue.length() > 5]]></param>
+ <message>stringValue.warning</message>
+ </field-validator>
+ </field>
+
+</validators>
\ No newline at end of file
Modified: jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/log4j.properties 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,5 +1,5 @@
# Global logging configuration
-log4j.rootLogger=INFO, stdout
+log4j.rootLogger=ERROR, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
Modified: jaxx/trunk/jaxx-runtime-validator-swing/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/changelog.txt 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/changelog.txt 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,2 +1,5 @@
+1.3 ??? 200903??
+ * 20090319 [chemit] - refactor Validator : now can deal with scopes, improve design
+
1.1 chemit 20090220
* 20090203 [chemit] - introduce this module specific to swing
\ No newline at end of file
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidator.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,8 +1,6 @@
package jaxx.runtime.validator.swing;
-import jaxx.runtime.validator.BeanValidator;
-import jaxx.runtime.validator.ValidatorErrorListener;
-import jaxx.runtime.validator.ValidatorField;
+
import jaxx.runtime.validator.swing.ui.AbstractBeanValidatorUI;
import jaxx.runtime.validator.swing.ui.IconValidationUI;
import org.apache.commons.logging.Log;
@@ -14,12 +12,13 @@
import java.awt.Container;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import jaxx.runtime.validator.BeanValidator2;
+import jaxx.runtime.validator.BeanValidatorField;
+
/**
* La surcharge de {@link jaxx.runtime.validator.BeanValidator} pour les ui swing
* <p/>
@@ -92,14 +91,12 @@
* }
* </pre>
*
+ * @param <B> le type de bean a valider
* @author poussin
* @author chemit
- * @version 1.0
- * <p/>
- * Last update: $Date: 3 févr. 2009 $
- * By : $Author: chatellier $
+ * @version 1.0
*/
-public class SwingValidator<B> extends BeanValidator<B> {
+public class SwingValidator<B> extends BeanValidator2<B> {
/** to use log facility, just put in your code: log.info(\"...\"); */
static private final Log log = LogFactory.getLog(SwingValidator.class);
@@ -154,9 +151,8 @@
@Override
public void setContextName(String contextName) {
- Map<ValidatorField<B>, List<ValidatorErrorListener>> oldListeners = new HashMap<ValidatorField<B>, List<ValidatorErrorListener>>();
+ /*Map<ValidatorField<B>, List<ValidatorErrorListener>> oldListeners = new HashMap<ValidatorField<B>, List<ValidatorErrorListener>>();
-
for (ValidatorField<B> field : fields) {
ValidatorErrorListener[] listeners = field.getValidatorErrorListeners();
List<ValidatorErrorListener> toReinject = new ArrayList<ValidatorErrorListener>();
@@ -168,18 +164,18 @@
toReinject.add(listener);
}
oldListeners.put(field, toReinject);
- }
+ }*/
super.setContextName(contextName);
// must reinstall ui
installUIs();
// reinject none ui listeners
- for (Entry<ValidatorField<B>, List<ValidatorErrorListener>> entry : oldListeners.entrySet()) {
+ /*for (Entry<ValidatorField<B>, List<ValidatorErrorListener>> entry : oldListeners.entrySet()) {
ValidatorField<B> field = getField(entry.getKey().getName());
for (ValidatorErrorListener listener : entry.getValue()) {
field.addValidatorErrorListener(listener);
}
}
- oldListeners.clear();
+ oldListeners.clear();*/
}
/**
@@ -190,7 +186,7 @@
* @param c the editor component for the field
*/
public void setFieldRepresentation(String fieldname, JComponent c) {
- ValidatorField<B> field = getField(fieldname);
+ BeanValidatorField<B> field = getField(fieldname);
if (field == null) {
// no field registred in the validator
log.warn("the field '" + fieldname + "' is not defined in validator (no rules on it)");
@@ -240,7 +236,7 @@
// same component, nothing to do
return;
}
- ValidatorField<B> field = getField(fieldname);
+ BeanValidatorField<B> field = getField(fieldname);
if (field == null) {
// this case should not appear since fieldName has already been check in method addFieldRepresentation
@@ -253,8 +249,10 @@
JXLayer<?> jx = (JXLayer<?>) container;
Object ui = jx.getUI();
if (ui != null && ui instanceof AbstractBeanValidatorUI) {
- field.removeValidatorErrorListener((AbstractBeanValidatorUI) ui);
+ removeBeanValidatorListener((AbstractBeanValidatorUI)ui);
+ //field.removeValidatorErrorListener((AbstractBeanValidatorUI) ui);
}
+
jx.setUI(null);
}
}
@@ -262,11 +260,12 @@
// ajout du jxlayer sous ce composant
Container container = c.getParent();
if (container instanceof JXLayer) {
- Constructor<? extends AbstractBeanValidatorUI> cons = uiClass.getConstructor(ValidatorField.class);
+ Constructor<? extends AbstractBeanValidatorUI> cons = uiClass.getConstructor(BeanValidatorField.class);
AbstractBeanValidatorUI ui = cons.newInstance(field);
ui.setEnabled(true);
JXLayer<JComponent> jx = (JXLayer<JComponent>) container;
- field.addValidatorErrorListener(ui);
+ addBeanValidatorListener(ui);
+ //field.addValidatorErrorListener(ui);
jx.setUI(ui);
}
}
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorListModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorListModel.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorListModel.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,73 +1,151 @@
package jaxx.runtime.validator.swing;
-import jaxx.runtime.validator.BeanValidator;
-import jaxx.runtime.validator.ValidatorErrorEvent;
-import jaxx.runtime.validator.ValidatorErrorListener;
-import jaxx.runtime.validator.ValidatorField;
+import jaxx.runtime.validator.BeanValidatorEvent;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
-import java.util.Set;
+import jaxx.runtime.validator.BeanValidatorField;
+import jaxx.runtime.validator.BeanValidatorListener;
+import jaxx.runtime.validator.BeanValidatorScope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* The model of the list of errors
*
* @author chemit
*/
-public class SwingValidatorErrorListModel extends DefaultListModel implements ValidatorErrorListener {
+public class SwingValidatorErrorListModel extends DefaultListModel implements BeanValidatorListener {
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ private static Log log = LogFactory.getLog(SwingValidatorErrorListModel.class);
private static final long serialVersionUID = 1L;
-
/** list of registred validators */
- protected transient List<BeanValidator<?>> validators;
+ protected transient List<SwingValidator<?>> validators;
-
public SwingValidatorErrorListModel() {
- validators = new ArrayList<BeanValidator<?>>();
+ validators = new ArrayList<SwingValidator<?>>();
}
- public void registerValidator(BeanValidator<?> validator) {
+ 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);
// the model listen on each field of the validator
- for (ValidatorField<?> field : validator.getFields()) {
- field.addValidatorErrorListener(this);
- }
+ /*for (ValidatorField<?> field : validator.getFields()) {
+ field.addValidatorErrorListener(this);
+ }*/
}
-
- /**
- * Invoked when a validator detects a error on a field.
- *
- * @param event the event
- */
@Override
- public void onNewError(ValidatorErrorEvent event) {
- ValidatorField field = event.getField();
+ public void onFieldChanged(BeanValidatorEvent event) {
+ String[] toDelete = event.getMessagesToDelete();
+ String[] toAdd = event.getMessagesToAdd();
+ BeanValidatorScope scope = event.getScope();
SwingValidator validator = (SwingValidator) event.getSource();
- Set<String> errors = event.getErrors();
+ BeanValidatorField field = event.getField();
- // must remove all previously error for this field and validator
- List<SwingValidatorErrorModel> newErrors = new ArrayList<SwingValidatorErrorModel>();
- JComponent editor = validator.getFieldRepresentation(field.getName());
+ if (log.isTraceEnabled()) {
+ log.trace("----------------------------------------------------------");
+ log.trace(field + " - (" + getSize() + ") toAdd " + (toAdd == null ? null : toAdd.length));
+ log.trace(field + " - (" + getSize() + ") toDelete " + (toDelete == null ? null : toDelete.length));
+ }
+
+ if ((toAdd == null || toAdd.length == 0) && (toDelete == null || toDelete.length == 0)) {
+ // no data to add nor remove, so nothing to do
+ return;
+ }
+
+ if (toAdd == null || toAdd.length == 0) {
+
+ if (log.isTraceEnabled()) {
+ log.trace(field + " - toDelete : just delete some datas!");
+ }
+
+ // no add, no need to resort the datas, can direclty delete
+ // messages we do not want any longer
+
+ // delete some messages for the given field and given scope
+ List<String> ids = new java.util.ArrayList<String>(java.util.Arrays.asList(toDelete));
+ List<Integer> indexs = new java.util.ArrayList<Integer>(toDelete.length);
+
+ Enumeration enumeration = elements();
+ int index = 0;
+ while (enumeration.hasMoreElements()) {
+ SwingValidatorErrorModel error = (SwingValidatorErrorModel) enumeration.nextElement();
+
+ if (error.getValidator() == validator && error.getField() == field && ids.contains(error.getError())) {
+ indexs.add(index);
+ }
+ index++;
+ }
+
+ java.util.Collections.reverse(indexs);
+
+ for (Integer i : indexs) {
+ removeElementAt(i);
+ }
+
+ return;
+ }
+
+ if (log.isTraceEnabled()) {
+ log.trace(field + " - add and delete !");
+ }
+
+ List<SwingValidatorErrorModel> newMessages = new ArrayList<SwingValidatorErrorModel>();
+
+
+
+ // obtain all messages not to delete
+
+ List<String> ids = new java.util.ArrayList<String>(java.util.Arrays.asList(toDelete));
+
Enumeration enumeration = elements();
while (enumeration.hasMoreElements()) {
SwingValidatorErrorModel error = (SwingValidatorErrorModel) enumeration.nextElement();
- if (error.getValidator() == validator && error.getField() == field) {
- // this error can be skipped
- continue;
+
+ if (error.getValidator() != validator || error.getField() != field || !ids.contains(error.getError())) {
+ // keep this row
+ newMessages.add(error);
}
- newErrors.add(error);
}
+
+ if (toAdd != null && toAdd.length > 0) {
+ JComponent editor = validator.getFieldRepresentation(field.getName());
+ // add new messages
+ for (String error : toAdd) {
+ newMessages.add(new SwingValidatorErrorModel(validator, field, error, editor));
+ }
+ }
+
+ // sort datas
+
+ java.util.Collections.sort(newMessages);
+
+ // clean model and reinject new errors
+ removeAllElements();
+
+ // reinject in list model, all the errors
+ for (SwingValidatorErrorModel error : newMessages) {
+ addElement(error);
+ }
+
+ /*
+ List<SwingValidatorErrorModel> newErrors = new ArrayList<SwingValidatorErrorModel>();
+
+ JComponent editor = validator.getFieldRepresentation(field.getName());
// add new errors
- for (String error : errors) {
- newErrors.add(new SwingValidatorErrorModel(validator, field, error, editor));
+ for (String error : toAdd) {
+ newErrors.add(new SwingValidatorErrorModel(validator, field, error, editor));
}
+
+
java.util.Collections.sort(newErrors);
// clean model and reinject new errors
@@ -75,43 +153,79 @@
// reinject in list model, all the errors
for (SwingValidatorErrorModel error : newErrors) {
- addElement(error);
- }
- //FIXME, this is not performant, prefer use a isValueAdjusting property on SwingValidator
- // notify that the model has changed
+ addElement(error);
+ }*/
}
+ /**
+ * Invoked when a validator detects a error on a field.
+ *
+ * @param event the event
+ */
+ /*@Override
+ public void onNewError(ValidatorErrorEvent event) {
+ ValidatorField field = event.getField();
+ SwingValidator validator = (SwingValidator) event.getSource();
+ Set<String> errors = event.getErrors();
+ // must remove all previously error for this field and validator
+ List<SwingValidatorErrorModel> newErrors = new ArrayList<SwingValidatorErrorModel>();
+ JComponent editor = validator.getFieldRepresentation(field.getName());
+ Enumeration enumeration = elements();
+ while (enumeration.hasMoreElements()) {
+ SwingValidatorErrorModel error = (SwingValidatorErrorModel) enumeration.nextElement();
+ if (error.getValidator() == validator && error.getField() == field) {
+ // this error can be skipped
+ continue;
+ }
+ newErrors.add(error);
+ }
+ // add new errors
+ for (String error : errors) {
+ newErrors.add(new SwingValidatorErrorModel(validator, field, error, editor));
+ }
+ java.util.Collections.sort(newErrors);
+
+ // clean model and reinject new errors
+ removeAllElements();
+
+ // reinject in list model, all the errors
+ for (SwingValidatorErrorModel error : newErrors) {
+ addElement(error);
+ }
+ //FIXME, this is not performant, prefer use a isValueAdjusting property on SwingValidator
+ // notify that the model has changed
+ }*/
/**
* Invoked when a validator detetcs that a previously error is
* no more exisitng.
*
* @param event the event
*/
- @Override
+ /*@Override
public void onResolvedError(ValidatorErrorEvent event) {
- SwingValidator validator = (SwingValidator) event.getSource();
- ValidatorField field = event.getField();
- // must remove all previously error for this field
+ SwingValidator validator = (SwingValidator) event.getSource();
+ ValidatorField field = event.getField();
+ // must remove all previously error for this field
- boolean somethingChange = false;
- Enumeration enumeration = elements();
- List<SwingValidatorErrorModel> newList = new ArrayList<SwingValidatorErrorModel>();
- while (enumeration.hasMoreElements()) {
- SwingValidatorErrorModel error = (SwingValidatorErrorModel) enumeration.nextElement();
- if (error.getValidator() == validator && error.getField() == field) {
- // this error can be skipped
- somethingChange = true;
- } else {
- newList.add(error);
- }
- }
- // clean model and reinject new errors
- removeAllElements();
+ boolean somethingChange = false;
+ Enumeration enumeration = elements();
+ List<SwingValidatorErrorModel> newList = new ArrayList<SwingValidatorErrorModel>();
+ while (enumeration.hasMoreElements()) {
+ SwingValidatorErrorModel error = (SwingValidatorErrorModel) enumeration.nextElement();
+ if (error.getValidator() == validator && error.getField() == field) {
+ // this error can be skipped
+ somethingChange = true;
+ } else {
+ newList.add(error);
+ }
+ }
+ // clean model and reinject new errors
+ removeAllElements();
- if (somethingChange) {
- for (SwingValidatorErrorModel errorModel : newList) {
- addElement(errorModel);
- }
- }
+ if (somethingChange) {
+ for (SwingValidatorErrorModel errorModel : newList) {
+ addElement(errorModel);
}
-}
\ No newline at end of file
+ }
+ }*/
+}
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorModel.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorModel.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,17 +1,17 @@
package jaxx.runtime.validator.swing;
-import jaxx.runtime.validator.ValidatorField;
import javax.swing.JComponent;
+import jaxx.runtime.validator.BeanValidatorField;
/** @author chemit */
public class SwingValidatorErrorModel implements Comparable<SwingValidatorErrorModel> {
protected SwingValidator validator;
- protected ValidatorField field;
+ protected BeanValidatorField field;
protected String error;
protected JComponent editor;
- public SwingValidatorErrorModel(SwingValidator validator, ValidatorField field, String error, JComponent editor) {
+ public SwingValidatorErrorModel(SwingValidator validator, BeanValidatorField field, String error, JComponent editor) {
this.field = field;
this.validator = validator;
this.error = error;
@@ -26,7 +26,7 @@
return validator;
}
- public ValidatorField getField() {
+ public BeanValidatorField getField() {
return field;
}
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableModel.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableModel.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,32 +1,32 @@
package jaxx.runtime.validator.swing;
-import jaxx.runtime.validator.ValidatorErrorEvent;
-import jaxx.runtime.validator.ValidatorErrorListener;
-import jaxx.runtime.validator.ValidatorField;
+import jaxx.runtime.validator.BeanValidatorEvent;
import javax.swing.JComponent;
import javax.swing.table.DefaultTableModel;
import java.util.ArrayList;
import java.util.Comparator;
-import java.util.Iterator;
+import java.util.Enumeration;
import java.util.List;
-import java.util.Set;
import java.util.Vector;
+import jaxx.runtime.validator.BeanValidatorField;
+import jaxx.runtime.validator.BeanValidatorListener;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* The model of the list of errors
*
* @author chemit
*/
-public class SwingValidatorErrorTableModel extends DefaultTableModel implements ValidatorErrorListener {
+public class SwingValidatorErrorTableModel extends DefaultTableModel implements BeanValidatorListener {
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ private static Log log = LogFactory.getLog(SwingValidatorErrorTableMouseListener.class);
private static final long serialVersionUID = 1L;
-
public static final String[] columnNames = {"validator.scope", "validator.field", "validator.message"};
-
/** list of registred validators */
protected transient List<SwingValidator<?>> validators;
-
/** comporator of errors */
protected transient Comparator<SwingValidatorErrorModel> comparator;
@@ -50,80 +50,109 @@
throw new IllegalArgumentException("the validator " + validator + " is already registred in " + this);
}
validators.add(validator);
- // the model listen on each field of the validator
- for (ValidatorField<?> field : validator.getFields()) {
- field.addValidatorErrorListener(this);
- }
+ validator.addBeanValidatorListener(this);
}
- /**
- * Invoked when a validator detects a error on a field.
- *
- * @param event the event
- */
@Override
- public void onNewError(ValidatorErrorEvent event) {
- ValidatorField field = event.getField();
+ public void onFieldChanged(BeanValidatorEvent event) {
+ String[] toDelete = event.getMessagesToDelete();
+ String[] toAdd = event.getMessagesToAdd();
+ BeanValidatorField field = event.getField();
+
+ if (log.isTraceEnabled()) {
+ log.trace("----------------------------------------------------------");
+ log.trace(field + " - (" + getRowCount() + ") toAdd " + (toAdd == null ? null : toAdd.length));
+ log.trace(field + " - (" + getRowCount() + ") toDelete " + (toDelete == null ? null : toDelete.length));
+ }
+ if ((toAdd == null || toAdd.length == 0) && (toDelete == null || toDelete.length == 0)) {
+ // no data to add nor remove, so nothing to do
+ return;
+ }
+
SwingValidator validator = (SwingValidator) event.getSource();
- Set<String> errors = event.getErrors();
- // must remove all previously error for this field and validator
+
+
int errorColumn = getErrorColumn();
- List<SwingValidatorErrorModel> newErrors = new ArrayList<SwingValidatorErrorModel>();
- JComponent editor = validator.getFieldRepresentation(field.getName());
- for (Object o : getDataVector()) {
- Vector row = (Vector) o;
+ if (toAdd == null || toAdd.length == 0) {
+
+
+ if (log.isTraceEnabled()) {
+ log.trace(field + " - toDelete : just delete some datas!");
+ }
+
+ // no add, no need to resort the datas, can direclty delete
+ // messages we do not want any longer
+
+ // delete some messages for the given field and given scope
+ List<String> ids = new java.util.ArrayList<String>(java.util.Arrays.asList(toDelete));
+ List<Integer> indexs = new java.util.ArrayList<Integer>(toDelete.length);
+
+ Enumeration enumeration = getDataVector().elements();
+
+ int index = 0;
+ while (enumeration.hasMoreElements()) {
+ Vector row = (Vector) enumeration.nextElement();
+ SwingValidatorErrorModel error = (SwingValidatorErrorModel) row.get(errorColumn);
+ if (error.getValidator() == validator && error.getField() == field && ids.contains(error.getError())) {
+ // remo the message
+ indexs.add(index);
+ }
+ index++;
+ }
+ java.util.Collections.reverse(indexs);
+
+ for (Integer i : indexs) {
+ removeRow(i);
+ }
+
+ return;
+ }
+
+ if (log.isTraceEnabled()) {
+ log.trace(field + " - add and delete !");
+ }
+
+ // rebuild all the data (since we are some adding data and we ensure
+ // an order on datas)
+
+ List<SwingValidatorErrorModel> newMessages = new ArrayList<SwingValidatorErrorModel>();
+
+ // delete some messages for the given field and given scope
+ List<String> ids = new java.util.ArrayList<String>(java.util.Arrays.asList(toDelete));
+
+ Enumeration enumeration = getDataVector().elements();
+
+ while (enumeration.hasMoreElements()) {
+ Vector row = (Vector) enumeration.nextElement();
SwingValidatorErrorModel error = (SwingValidatorErrorModel) row.get(errorColumn);
- if (error.getValidator() == validator && error.getField() == field) {
- // this error can be skipped
- continue;
+ if (error.getValidator() != validator || error.getField() != field || !ids.contains(error.getError())) {
+ // keep this row
+ newMessages.add(error);
}
- newErrors.add(error);
}
- // add new errors
- for (String error : errors) {
- newErrors.add(new SwingValidatorErrorModel(validator, field, error, editor));
+
+ if (toAdd != null && toAdd.length > 0) {
+ JComponent editor = validator.getFieldRepresentation(field.getName());
+ // add new errors
+ for (String error : toAdd) {
+ SwingValidatorErrorModel errorModel = new SwingValidatorErrorModel(validator, field, error, editor);
+ newMessages.add(errorModel);
+ }
}
- java.util.Collections.sort(newErrors);
- // clean table model and reinject new errors
+ // sort datas
+
+ java.util.Collections.sort(newMessages);
+
+ // clean table model and reinject new messages
getDataVector().clear();
+
// reinject in list model, all the errors
- for (SwingValidatorErrorModel error : newErrors) {
+ for (SwingValidatorErrorModel error : newMessages) {
addRow(new Object[]{error.getField().getScope(), error.getField().getName(), error});
}
- //FIXME, this is not performant, prefer use a isValueAdjusting property on SwingValidator
- // notify that the model has changed
+
fireTableDataChanged();
}
-
- /**
- * Invoked when a validator detetcs that a previously error is
- * no more exisitng.
- *
- * @param event the event
- */
- @Override
- public void onResolvedError(ValidatorErrorEvent event) {
- SwingValidator validator = (SwingValidator) event.getSource();
- ValidatorField field = event.getField();
- // must remove all previously error for this field
- int errorColumn = getErrorColumn();
- boolean somethingChange = false;
- for (Iterator it = getDataVector().iterator(); it.hasNext();) {
- Object o = it.next();
- Vector row = (Vector) o;
- SwingValidatorErrorModel error = (SwingValidatorErrorModel) row.get(errorColumn);
- if (error.getValidator() == validator && error.getField() == field) {
- // this error can be skipped
- it.remove();
- somethingChange = true;
- }
- }
- if (somethingChange) {
- // notify that the model has changed
- fireTableDataChanged();
- }
- }
-
}
\ No newline at end of file
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableRenderer.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableRenderer.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/SwingValidatorErrorTableRenderer.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,32 +1,35 @@
package jaxx.runtime.validator.swing;
-import com.opensymphony.xwork2.validator.ValidatorScope;
-
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.Component;
+import jaxx.runtime.validator.BeanValidatorScope;
/** @author chemit */
public class SwingValidatorErrorTableRenderer extends DefaultTableCellRenderer {
+ private static final long serialVersionUID = 1L;
ImageIcon errorIcon;
ImageIcon warningIcon;
+ ImageIcon infoIcon;
public SwingValidatorErrorTableRenderer() {
errorIcon = jaxx.runtime.Util.createImageIcon("error.png");
warningIcon = jaxx.runtime.Util.createImageIcon("warning.png");
+ infoIcon = jaxx.runtime.Util.createImageIcon("info.png");
}
+ @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;
- if (value instanceof ValidatorScope) {
+ if (value instanceof BeanValidatorScope) {
- ValidatorScope scope = (ValidatorScope) value;
+ BeanValidatorScope scope = (BeanValidatorScope) value;
switch (scope) {
case ERROR:
icon = errorIcon;
@@ -34,6 +37,9 @@
case WARNING:
icon = warningIcon;
break;
+ case INFO:
+ icon = infoIcon;
+ break;
}
} else if (value instanceof SwingValidatorErrorModel) {
SwingValidatorErrorModel model = (SwingValidatorErrorModel) value;
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/AbstractBeanValidatorUI.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,8 +1,8 @@
package jaxx.runtime.validator.swing.ui;
-import jaxx.runtime.validator.ValidatorErrorEvent;
-import jaxx.runtime.validator.ValidatorErrorListener;
-import jaxx.runtime.validator.ValidatorField;
+import jaxx.runtime.validator.BeanValidatorEvent;
+import jaxx.runtime.validator.BeanValidatorField;
+import jaxx.runtime.validator.BeanValidatorListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;
@@ -12,15 +12,14 @@
*
* @author chemit
*/
-public abstract class AbstractBeanValidatorUI extends AbstractLayerUI<javax.swing.JComponent> implements ValidatorErrorListener {
+public abstract class AbstractBeanValidatorUI extends AbstractLayerUI<javax.swing.JComponent> implements BeanValidatorListener {
/** to use log facility, just put in your code: log.info(\"...\"); */
private static final Log log = LogFactory.getLog(AbstractBeanValidatorUI.class);
-
/** the field to render */
- protected ValidatorField field;
+ protected BeanValidatorField field;
- public AbstractBeanValidatorUI(ValidatorField field) {
+ public AbstractBeanValidatorUI(BeanValidatorField field) {
this.field = field;
if (log.isDebugEnabled()) {
log.debug("install " + this + "<field:" + field + ">");
@@ -28,22 +27,11 @@
}
@Override
- public void onNewError(ValidatorErrorEvent event) {
- dispatchValidatorErrorEvent(event);
- }
-
- @Override
- public void onResolvedError(ValidatorErrorEvent event) {
- dispatchValidatorErrorEvent(event);
- }
-
- protected void dispatchValidatorErrorEvent(ValidatorErrorEvent event) {
- // check if event occurs to this field
- if (!field.equals(event.getField())) {
- return;
+ public void onFieldChanged(BeanValidatorEvent event) {
+ if (field.equals(event.getField())) {
+ // ask to repaint the layer
+ setDirty(true);
}
- // repaint the layer
- setDirty(true);
}
}
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/IconValidationUI.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,6 +1,5 @@
package jaxx.runtime.validator.swing.ui;
-import jaxx.runtime.validator.ValidatorField;
import org.jdesktop.jxlayer.JXLayer;
import javax.swing.BorderFactory;
@@ -9,6 +8,8 @@
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
+import jaxx.runtime.validator.BeanValidatorField;
+import jaxx.runtime.validator.BeanValidatorScope;
/** @author chemit */
public class IconValidationUI extends AbstractBeanValidatorUI {
@@ -16,9 +17,19 @@
// The icon to be shown at the layer's corner
protected static BufferedImage errorIcon;
protected static BufferedImage warningIcon;
+ protected static BufferedImage infoIcon;
- public IconValidationUI(ValidatorField field) {
+ public IconValidationUI(BeanValidatorField field) {
super(field);
+ if (errorIcon == null) {
+ errorIcon = prepareIcon(Color.RED);
+ }
+ if (warningIcon == null) {
+ warningIcon = prepareIcon(Color.ORANGE);
+ }
+ if (infoIcon == null) {
+ infoIcon = prepareIcon(Color.GREEN);
+ }
}
@Override
@@ -37,34 +48,26 @@
protected void paintLayer(Graphics2D g2, JXLayer<JComponent> l) {
super.paintLayer(g2, l);
// There is no need to take insets into account for this painter
- switch (field.getScope()) {
- case ERROR:
- if (field.hasErrors()) {
- g2.drawImage(getErrorIcon(), l.getWidth() - errorIcon.getWidth() - 1, 0, null);
- }
- break;
- case WARNING:
- if (field.hasWarnings()) {
- g2.drawImage(getWarningIcon(), l.getWidth() - warningIcon.getWidth() - 1, 0, null);
- }
- break;
+ BeanValidatorScope scope = field.getScope();
+ if (scope != null) {
+ BufferedImage icon = null;
+ switch (scope) {
+ case ERROR:
+ icon = errorIcon;
+ break;
+ case WARNING:
+ icon = warningIcon;
+ break;
+ case INFO:
+ icon = infoIcon;
+ break;
+ }
+ if (icon != null) {
+ g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null);
+ }
}
}
- protected static BufferedImage getErrorIcon() {
- if (errorIcon == null) {
- errorIcon = prepareIcon(Color.RED);
- }
- return errorIcon;
- }
-
- protected static BufferedImage getWarningIcon() {
- if (warningIcon == null) {
- warningIcon = prepareIcon(Color.YELLOW);
- }
- return warningIcon;
- }
-
protected static BufferedImage prepareIcon(Color color) {
int width = 7;
int height = 8;
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/ImageValidationUI.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,6 +1,5 @@
package jaxx.runtime.validator.swing.ui;
-import jaxx.runtime.validator.ValidatorField;
import org.jdesktop.jxlayer.JXLayer;
import javax.swing.BorderFactory;
@@ -9,15 +8,27 @@
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
+import jaxx.runtime.validator.BeanValidatorField;
+import jaxx.runtime.validator.BeanValidatorScope;
/** @author chemit */
public class ImageValidationUI extends AbstractBeanValidatorUI {
protected static BufferedImage errorIcon;
protected static BufferedImage warningIcon;
+ protected static BufferedImage infoIcon;
- public ImageValidationUI(ValidatorField field) {
+ public ImageValidationUI(BeanValidatorField field) {
super(field);
+ if (errorIcon == null) {
+ errorIcon = prepareIcon(jaxx.runtime.Util.createImageIcon("error.png"));
+ }
+ if (warningIcon == null) {
+ warningIcon = prepareIcon(jaxx.runtime.Util.createImageIcon("warning.png"));
+ }
+ if (infoIcon == null) {
+ infoIcon = prepareIcon(jaxx.runtime.Util.createImageIcon("info.png"));
+ }
}
protected static BufferedImage prepareIcon(ImageIcon image) {
@@ -45,31 +56,23 @@
@Override
protected void paintLayer(Graphics2D g2, JXLayer<JComponent> l) {
super.paintLayer(g2, l);
- switch (field.getScope()) {
- case ERROR:
- if (field.hasErrors()) {
- g2.drawImage(getErrorIcon(), l.getWidth() - errorIcon.getWidth() - 1, 0, null);
- }
- break;
- case WARNING:
- if (field.hasWarnings()) {
- g2.drawImage(getWarningIcon(), l.getWidth() - warningIcon.getWidth() - 1, 0, null);
- }
- break;
+ BeanValidatorScope scope = field.getScope();
+ if (scope != null) {
+ BufferedImage icon = null;
+ switch (scope) {
+ case ERROR:
+ icon = errorIcon;
+ break;
+ case WARNING:
+ icon = warningIcon;
+ break;
+ case INFO:
+ icon = infoIcon;
+ break;
+ }
+ if (icon != null) {
+ g2.drawImage(icon, l.getWidth() - icon.getWidth() - 1, 0, null);
+ }
}
}
-
- protected static BufferedImage getErrorIcon() {
- if (errorIcon == null) {
- errorIcon = prepareIcon(jaxx.runtime.Util.createImageIcon("error.png"));
- }
- return errorIcon;
- }
-
- protected static BufferedImage getWarningIcon() {
- if (warningIcon == null) {
- warningIcon = prepareIcon(jaxx.runtime.Util.createImageIcon("warning.png"));
- }
- return warningIcon;
- }
}
\ No newline at end of file
Modified: jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java 2009-03-18 18:17:16 UTC (rev 1271)
+++ jaxx/trunk/jaxx-runtime-validator-swing/src/main/java/jaxx/runtime/validator/swing/ui/TranslucentValidationUI.java 2009-03-19 22:47:05 UTC (rev 1272)
@@ -1,6 +1,6 @@
package jaxx.runtime.validator.swing.ui;
-import jaxx.runtime.validator.ValidatorField;
+import jaxx.runtime.validator.BeanValidatorScope;
import org.jdesktop.jxlayer.JXLayer;
import javax.swing.JComponent;
@@ -9,17 +9,20 @@
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
+import jaxx.runtime.validator.BeanValidatorField;
/** @author chemit */
public class TranslucentValidationUI extends AbstractBeanValidatorUI {
protected Color errorHightlight;
protected Color warningHightlight;
+ protected Color infoHightlight;
- public TranslucentValidationUI(ValidatorField field) {
+ public TranslucentValidationUI(BeanValidatorField field) {
super(field);
errorHightlight = Color.RED;
warningHightlight = Color.YELLOW;
+ infoHightlight = Color.GREEN;
}
@Override
@@ -38,23 +41,24 @@
view.getWidth() - insets.left - insets.right,
view.getHeight() - insets.top - insets.bottom));
- switch (field.getScope()) {
+ BeanValidatorScope scope = field.getScope();
- case ERROR:
- if (field.hasErrors()) {
+ if (scope == null) {
+ g2.setColor(Color.WHITE);
+ } else {
+ switch (scope) {
+ case ERROR:
g2.setColor(errorHightlight);
- } else {
- g2.setColor(Color.WHITE);
- }
- break;
- case WARNING:
- if (field.hasErrors()) {
+ break;
+ case WARNING:
g2.setColor(warningHightlight);
- } else {
- g2.setColor(Color.WHITE);
- }
- break;
+ break;
+ case INFO:
+ g2.setColor(infoHightlight);
+ break;
+ }
}
+
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .2f));
g2.fillRect(0, 0, l.getWidth(), l.getHeight());
}
Added: jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/icons/info.png
===================================================================
(Binary files differ)
Property changes on: jaxx/trunk/jaxx-runtime-validator-swing/src/main/resources/icons/info.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
1
0
r1271 - in jaxx/trunk: jaxx-example/src/main/java/jaxx/demo jaxx-runtime-swing jaxx-runtime-swing/src/main/java/jaxx/runtime/swing
by tchemit@users.labs.libre-entreprise.org 18 Mar '09
by tchemit@users.labs.libre-entreprise.org 18 Mar '09
18 Mar '09
Author: tchemit
Date: 2009-03-18 18:17:16 +0000 (Wed, 18 Mar 2009)
New Revision: 1271
Added:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java
Modified:
jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx
jaxx/trunk/jaxx-runtime-swing/changelog.txt
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java
Log:
introduce BlockingLayerUI2
Modified: jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx
===================================================================
--- jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx 2009-03-18 08:46:51 UTC (rev 1270)
+++ jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx 2009-03-18 18:17:16 UTC (rev 1271)
@@ -11,22 +11,38 @@
accept(e, "from icon of layer");
}
}}' />
+ <jaxx.runtime.swing.BlockingLayerUI2 id='layerUI2'
+ blockIcon='{SwingUtil.createImageIcon("action-block.png")}'
+ acceptIcon='{SwingUtil.createImageIcon("action-accept.png")}'
+ acceptAction='{new AbstractAction() { private static final long serialVersionUID = 1L;
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ accept(e, "from icon of layer");
+ }
+ }}' />
<script><![CDATA[
import jaxx.runtime.SwingUtil;
void $afterCompleteSetup() {
for (JComponent boxed : SwingUtil.getLayeredComponents(this)) {
+ if (boxed == d) {
+ SwingUtil.getLayer(boxed).setUI(layerUI2);
+ continue;
+ }
+
jaxx.runtime.swing.BlockingLayerUI ui = layerUI.clone();
if ( boxed == c) {
ui.setBlock(true);
}
SwingUtil.getLayer(boxed).setUI(ui);
- //ui.setDirty(true);
}
}
public void setLayer(boolean active) {
for (JComponent boxed : SwingUtil.getLayeredComponents(this)) {
+ if (boxed == d) {
+ continue;
+ }
jaxx.runtime.swing.BlockingLayerUI ui = (jaxx.runtime.swing.BlockingLayerUI)SwingUtil.getLayer(boxed).getUI();
if ( boxed == c) {
ui.setBlock(active);
@@ -59,6 +75,8 @@
onActionPerformed='accept(event, "from button (no layer)")'/>
<JButton id='c' text='button C (full block)' decorator='boxed' _clickedText='"button C was clicked"'
onActionPerformed='accept(event, "from button (no layer)");'/>
+ <JButton id='d' text='button D (full block 2)' decorator='boxed' _clickedText='"button D was clicked"'
+ onActionPerformed='accept(event, "from button (no layer)");'/>
</JPanel>
</cell>
</row>
Modified: jaxx/trunk/jaxx-runtime-swing/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/changelog.txt 2009-03-18 08:46:51 UTC (rev 1270)
+++ jaxx/trunk/jaxx-runtime-swing/changelog.txt 2009-03-18 18:17:16 UTC (rev 1271)
@@ -1,4 +1,5 @@
1.3 ?? 200903??
+ * 20090318 [chemit] - introduce the BlockingLayerUI2 class (should be merge with BlockingLayerUI)
* 20090318 [chemit] - introduce the CardLayout2Ext class
* 20090312 [chemit] - add some usefull code from ObServe (load Nimbus L&F, load ui configuration)
* 20090309 [chemit] - in BlockingLayerUI, add a new state 'block' to enable/disable blocking mode with a blockingColor
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java 2009-03-18 08:46:51 UTC (rev 1270)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI.java 2009-03-18 18:17:16 UTC (rev 1271)
@@ -4,9 +4,7 @@
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
-import java.awt.Insets;
import java.awt.Point;
-import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/BlockingLayerUI2.java 2009-03-18 18:17:16 UTC (rev 1271)
@@ -0,0 +1,206 @@
+package jaxx.runtime.swing;
+
+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 javax.swing.Action;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import org.jdesktop.jxlayer.JXLayer;
+
+/**
+ *
+ * A JXLayer ui implementation that permits to block a component but still
+ * allow an action when clicking everywhere on the layer.
+ *
+ * Moreover, an icon can be added on the right-top icon painted and changed
+ * when the mouse is over the layer.
+ *
+ * You can change the blocking and accepting icon.
+ *
+ * To hook an click on the layer's icon, you can :
+ *
+ * <ul><li>pass an Action via method {@link #setAcceptAction(Action)}</li>
+ * <li>override the method {@link #acceptEvent(java.awt.event.MouseEvent, org.jdesktop.jxlayer.JXLayer)}</li>
+ * </ul>
+ *
+ * @author tony
+ * @since 1.3
+ */
+public class BlockingLayerUI2 extends org.jdesktop.jxlayer.plaf.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";
+ 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;
+ /**
+ * 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 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.setCanClick(false);
+ return clone;
+ }
+
+ @Override
+ protected void processKeyEvent(KeyEvent e, JXLayer<JComponent> l) {
+
+ e.consume();
+
+ }
+
+ @Override
+ protected void processMouseMotionEvent(MouseEvent e, JXLayer<JComponent> l) {
+
+ e.consume();
+
+ }
+
+ @Override
+ protected void processMouseEvent(MouseEvent e, JXLayer<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<JComponent> l) {
+ 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));
+ */
+
+ if (getCurrentIcon() != null) {
+ g2.drawImage(getCurrentIcon(), l.getWidth() - getCurrentIcon().getWidth() - 1, 0, null);
+ }
+ }
+
+ protected void acceptEvent(MouseEvent e, JXLayer<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);
+ }
+}
1
0
18 Mar '09
Author: tchemit
Date: 2009-03-18 08:46:51 +0000 (Wed, 18 Mar 2009)
New Revision: 1270
Modified:
jaxx/trunk/jaxx-runtime-swing/changelog.txt
Log:
introduce CardLayout2Ext + improve wizard framework
Modified: jaxx/trunk/jaxx-runtime-swing/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/changelog.txt 2009-03-18 08:45:58 UTC (rev 1269)
+++ jaxx/trunk/jaxx-runtime-swing/changelog.txt 2009-03-18 08:46:51 UTC (rev 1270)
@@ -1,4 +1,5 @@
1.3 ?? 200903??
+ * 20090318 [chemit] - introduce the CardLayout2Ext class
* 20090312 [chemit] - add some usefull code from ObServe (load Nimbus L&F, load ui configuration)
* 20090309 [chemit] - in BlockingLayerUI, add a new state 'block' to enable/disable blocking mode with a blockingColor
* 20090303 [chemit] - in BlockingLayerUI, add a new state 'useIcon' to enable/disable use of the action icon
1
0
r1269 - in jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing: . wizard
by tchemit@users.labs.libre-entreprise.org 18 Mar '09
by tchemit@users.labs.libre-entreprise.org 18 Mar '09
18 Mar '09
Author: tchemit
Date: 2009-03-18 08:45:58 +0000 (Wed, 18 Mar 2009)
New Revision: 1269
Added:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java
Modified:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
Log:
introduce CardLayout2Ext + improve wizard framework
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/CardLayout2Ext.java 2009-03-18 08:45:58 UTC (rev 1269)
@@ -0,0 +1,99 @@
+package jaxx.runtime.swing;
+
+import java.awt.Container;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import jaxx.runtime.JAXXObject;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Une extension de {@link CardLayout2} pour pouvoir automatiquement afficher un
+ * contenu à partir de la propriété {@link #selected}.
+ *
+ * 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 tony
+ * @since 1.3
+ * @see CardLayout2
+ */
+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) {
+ this.selected = selected;
+ show(getContainer(), 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);
+ }
+ }
+}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-16 18:44:15 UTC (rev 1268)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-18 08:45:58 UTC (rev 1269)
@@ -195,6 +195,17 @@
}
}
+ public void validate() {
+ if (step == null) {
+ // pas de validation quand aucune etape n'est sélectionnée
+ return;
+ }
+ boolean validate = validate(step);
+ this.validStep = validate;
+ // toujours forcer la propagation
+ firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep);
+ }
+
protected Class<E> getStepClass() {
return stepClass;
}
@@ -210,17 +221,6 @@
validate();
}
- protected void validate() {
- if (step == null) {
- // pas de validation quand aucune etape n'est sélectionnée
- return;
- }
- boolean validate = validate(step);
- this.validStep = validate;
- // toujours forcer la propagation
- firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep);
- }
-
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
pcs.firePropertyChange(propertyName, oldValue, newValue);
}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2009-03-16 18:44:15 UTC (rev 1268)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2009-03-18 08:45:58 UTC (rev 1269)
@@ -34,6 +34,18 @@
return operation;
}
+ public Exception getError() {
+ return error;
+ }
+
+ public void setError(Exception e) {
+ error = e;
+ }
+
+ public void sendMessage(String msg) {
+ firePropertyChange("message", null, msg);
+ }
+
public abstract void start(JAXXContext context);
public abstract void beforeAction(JAXXContext context, M model) throws Exception;
@@ -44,8 +56,6 @@
public abstract WizardOperationState onCancel(M model, Exception e);
- public abstract void afterAction(M model, WizardOperationState result, Exception error);
-
protected abstract M getModel();
public WizardOperationState getOperationState() {
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2009-03-16 18:44:15 UTC (rev 1268)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2009-03-18 08:45:58 UTC (rev 1269)
@@ -49,44 +49,42 @@
}
public void cancel() {
- if (currentAction != null) {
- log.debug("cancel action " + currentAction);
- // on a une action en cours, on l'annule
- currentAction.cancel(true);
- }
- // on annule aussi le modele
+ log.info("cancel " + this);
+ this.canceled = true;
+
+ // on annule le modele
getModel().cancel();
- this.canceled = true;
+
// on rend la main au thread
setWaiting(false);
}
@SuppressWarnings("unchecked")
- public void launchOperation(E operation) {
+ public A launchOperation(E operation) {
- if (currentAction != null) {
+ if (currentAction != null && (!currentAction.isDone() || currentAction.operationState == WizardOperationState.RUNNING)) {
// on ne peut traiter qu'une seule opération à la fois
throw new IllegalStateException("can not add a operation when thread is busy, or has another operation to be done");
}
- try {
- currentAction = (A) operation.getActionClass().newInstance();
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
+ currentAction = (A) getModel().getOperationAction(operation);
+
// on libere le thread pour qu'il execute l'opération
setWaiting(false);
+
+ return currentAction;
}
+ public A getCurrentAction() {
+ return currentAction;
+ }
+
@Override
public void propertyChange(PropertyChangeEvent evt) {
log.trace(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">");
if ("state".equals(evt.getPropertyName())) {
- //@SuppressWarnings("unchecked")
- //A action = (A) evt.getSource();
StateValue state = (StateValue) evt.getNewValue();
if (state == StateValue.DONE) {
// on rend la main au thread pour qu'il attende une prochaine operation
- //getModel().setOperationState(action.getOperation(), action.getOperationState());
setWaiting(false);
}
}
@@ -137,13 +135,17 @@
// est terminée ou a été annulée, on passera alors
// dans la méthode onPropertyChanged
- getModel().setOperationState(currentAction.getOperationState());
+ if (canceled) {
+ getModel().setOperationState(WizardOperationState.CANCELED);
+ } else {
+ getModel().setOperationState(currentAction.getOperationState());
+ }
// le thread n'écoute plus l'action car elle est terminée
// ou annulée
currentAction.removePropertyChangeListener(this);
// suppression de l'action
- currentAction = null;
+ //currentAction = null;
}
}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2009-03-16 18:44:15 UTC (rev 1268)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2009-03-18 08:45:58 UTC (rev 1269)
@@ -1,9 +1,12 @@
package jaxx.runtime.swing.wizard;
+import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.swing.SwingWorker.StateValue;
/**
* Un modèle de wizard avec des opérations.
@@ -18,11 +21,8 @@
public static final String OPERATION_STATE_PROPERTY_NAME = "operationState";
public static final String MODEL_STATE_PROPERTY_NAME = "modelState";
public static final String WAS_STARTED_PROPERTY_NAME = "wasStarted";
+
/**
- * le type d'une opération
- */
-// protected Class<O> operationClass;
- /**
* La liste des opérations à effectuer
*/
protected Set<E> operations;
@@ -30,6 +30,7 @@
* Pour conserver les états des opérations
*/
protected Map<E, WizardOperationState> operationStates;
+ protected Map<E, WizardOperationAction> operationActions;
/**
* L'état générale du modèle
*/
@@ -45,6 +46,7 @@
Class<T> k = (Class) stepClass;
this.operationStates = (Map) new EnumMap(k);
this.operations = (Set<E>) EnumSet.noneOf(k);
+ this.operationActions = (Map) new EnumMap(k);
}
public Set<E> getOperations() {
@@ -73,6 +75,19 @@
return operationStates.get(operation);
}
+ public WizardOperationAction getOperationAction(E operation) {
+ WizardOperationAction action = operationActions.get(operation);
+ if (action == null) {
+ try {
+ action = operation.getActionClass().newInstance();
+ operationActions.put(operation, action);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return action;
+ }
+
public void setOperationState(WizardOperationState operationState) {
E operation = getOperation();
setOperationState(operation, operationState);
@@ -90,7 +105,7 @@
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
@@ -106,7 +121,7 @@
(!previousStep.isOperation() || getOperationState(previousStep) == WizardOperationState.SUCCESSED));
}
}
- System.out.println("accessibles steps -------- " + java.util.Arrays.toString(result));
+ //System.out.println("accessibles steps -------- " + java.util.Arrays.toString(result));
return result;
}
@@ -121,12 +136,24 @@
}
public void cancel() {
+
for (E op : operations) {
if (getOperationState(op) == WizardOperationState.PENDING) {
// on annule l'opération à venir
setOperationState(op, WizardOperationState.CANCELED);
}
}
+ setModelState(WizardOperationState.CANCELED);
+ if (getStep() != null && getStep().isOperation()) {
+ WizardOperationAction action = getOperationAction(getStep());
+ if (action != null) {
+ if (!action.isCancelled() && !action.isDone() && action.getState() == StateValue.STARTED) {
+ System.out.println("cancel action " + action);
+ // on annule l'action
+ action.cancel(true);
+ }
+ }
+ }
}
public WizardOperationModel<E> addOperation(E operation) {
@@ -152,6 +179,10 @@
super.setSteps(steps);
// on force la propagation de la nouvelle liste
firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ updateOperationStates(Arrays.asList(steps));
+ }
+
+ public void updateOperationStates(List<E> steps) {
int index = 0;
for (E e : steps) {
fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, index++, null, getOperationState(e));
@@ -185,7 +216,7 @@
case CANCELED:
//le modele devient annulé
setModelState(WizardOperationState.CANCELED);
- break;
+ return;
case PENDING:
//le modele est en attente
setModelState(WizardOperationState.PENDING);
@@ -210,6 +241,7 @@
}
break;
}
+ updateOperationStates(steps);
}
@Override
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-16 18:44:15 UTC (rev 1268)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-18 08:45:58 UTC (rev 1269)
@@ -1,6 +1,7 @@
package jaxx.runtime.swing.wizard;
-import javax.swing.JFrame;
+import java.awt.Window;
+import javax.swing.ImageIcon;
import jaxx.runtime.JAXXContext;
import jaxx.runtime.JAXXInitialContext;
import jaxx.runtime.JAXXObject;
@@ -20,85 +21,37 @@
protected UI ui;
- @SuppressWarnings("unchecked")
- public WizardUILancher(JAXXContext context, JFrame mainUI, Class<UI> uiClass, M model) {
- super();
+ 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 {
- // instanciate ui parent context
- JAXXInitialContext uiContext = new JAXXInitialContext();
- uiContext.add(mainUI == null ? context : mainUI);
- // parent context model
- uiContext.add(model);
- // apply action
- uiContext.add("apply", new Runnable() {
-
- @Override
- public void run() {
- doAction(ui);
- }
- });
- // cancel action
- uiContext.add("cancel", new Runnable() {
-
- @Override
- public void run() {
- doCancel(ui);
- }
- });
-
- // instanciate ui
- ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext}, new Class[]{JFrame.class, JAXXContext.class});
-
+ ui = createUI(context, uiClass, modelClass, model, title, tip, icon);
} catch (Exception ex) {
throw new RuntimeException("could not instanciate launcher for reason " + ex.getMessage(), ex);
}
}
- @SuppressWarnings("unchecked")
- public WizardUILancher(JAXXContext context, JFrame mainUI, Class<UI> uiClass, Class<M> modelClass) {
- super();
+ public WizardUILancher(JAXXContext context, Window mainUI, Class<UI> uiClass, Class<M> modelClass, M model) {
try {
- // instanciate ui parent context
- JAXXInitialContext uiContext = new JAXXInitialContext();
- uiContext.add(mainUI == null ? context : mainUI);
- // parent context model
- uiContext.add(modelClass.newInstance());
- // apply action
- uiContext.add("apply", new Runnable() {
-
- @Override
- public void run() {
- doAction(ui);
- }
- });
- // cancel action
- uiContext.add("cancel", new Runnable() {
-
- @Override
- public void run() {
- doCancel(ui);
- }
- });
-
- // instanciate ui
- ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext}, new Class[]{JFrame.class, JAXXContext.class});
-
+ 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() {
- try {
- init(ui);
- ui.start();
- } finally {
- dispose();
- }
+ init(ui);
+ start(ui);
}
- public void dispose() {
- // par defaut, on ne fait rien
+ protected void start(UI ui) {
+ ui.start();
}
public <T> T getContextValue(Class<T> clazz, String name) {
@@ -124,4 +77,86 @@
protected void doCancel(UI ui) {
}
+
+ protected void doClose(UI ui, boolean wasCanceld) {
+ }
+
+ @SuppressWarnings("unchecked")
+ 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("incoming", model);
+ }
+ // apply action
+ uiContext.add("apply", new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ doAction(ui);
+ } finally {
+ doClose(ui,false);
+ }
+ }
+ });
+ // cancel action
+ uiContext.add("cancel", new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ doCancel(ui);
+ } finally {
+ doClose(ui,true);
+ }
+ }
+ });
+
+ // instanciate ui
+
+ UI newUI = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext}, new Class[]{Window.class, JAXXContext.class});
+ return newUI;
+ }
+
+ @SuppressWarnings("unchecked")
+ 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("incoming", model);
+ }
+ // apply action
+ uiContext.add("apply", new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ doAction(ui);
+ } finally {
+ doClose(ui,false);
+ }
+ }
+ });
+ // cancel action
+ uiContext.add("cancel", new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ doCancel(ui);
+ } finally {
+ doClose(ui,true);
+ }
+ }
+ });
+
+ // instanciate ui
+ UI newUI = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{uiContext, title, tip, icon}, new Class[]{JAXXContext.class, String.class, String.class, ImageIcon.class});
+ return newUI;
+ }
}
1
0
r1268 - in jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime: . swing/wizard
by tchemit@users.labs.libre-entreprise.org 16 Mar '09
by tchemit@users.labs.libre-entreprise.org 16 Mar '09
16 Mar '09
Author: tchemit
Date: 2009-03-16 18:44:15 +0000 (Mon, 16 Mar 2009)
New Revision: 1268
Added:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/package.html
Removed:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java
Modified:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
Log:
wizard framework done
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -29,6 +29,7 @@
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.NoSuchElementException;
import java.util.Properties;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
@@ -413,6 +414,7 @@
public int size() {
return tabs.getTabCount();
}
+
public TabbedPaneIterator<O> reverse() {
setReverse(!reverse);
return this;
@@ -430,9 +432,9 @@
@Override
public O next() {
if (!hasNext()) {
- throw new IllegalStateException("no next objet! for " + this);
+ throw new NoSuchElementException();
}
- Component next = tabs.getComponent(index);
+ Component next = tabs.getComponentAt(index);
O result = get(index, next);
index += increment;
return result;
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -2,17 +2,21 @@
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
-import java.util.List;
/**
* Un modèle de wizard.
*
- * @param <E> le type de l'énumération contenant les etapes.
*
+ * <b>Note:</b> le type des étapes doit être uné énumération qui implante
+ * {@link WizardStep}.
+ *
+ * @param <E> le type des étapes.
+ *
* @author tony
* @since 1.3
+ * @see WizardStep
*/
-public class WizardModel<E extends Enum<E>> {
+public class WizardModel<E extends WizardStep> {
public static final String STEPS_PROPERTY_NAME = "steps";
public static final String STEP_PROPERTY_NAME = "step";
@@ -26,7 +30,7 @@
/**
* Toutes les étapes à passer
*/
- protected List<E> steps;
+ protected java.util.List<E> steps;
/**
* L'étape courante
*/
@@ -36,11 +40,20 @@
*/
protected boolean validStep;
/**
+ * 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;
this.pcs = new PropertyChangeSupport(this);
this.steps = new java.util.ArrayList<E>();
@@ -79,7 +92,7 @@
throw new NullPointerException("step can not be null");
}
if (!steps.contains(e)) {
- throw new IllegalStateException("step " + e + " is not in universe of steps (" + steps + ")");
+ throw new IllegalStateException("step " + e.toString() + " is not in universe of steps (" + steps + ")");
}
setStep(e);
}
@@ -98,6 +111,11 @@
}
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
@@ -106,6 +124,15 @@
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) {
@@ -115,10 +142,14 @@
return steps.get(index + 1);
}
- public List<E> getSteps() {
+ public java.util.List<E> getSteps() {
return steps;
}
+ public boolean isValueAdjusting() {
+ return valueAdjusting;
+ }
+
/**
* Change l'univers des etapes.
*
@@ -127,13 +158,17 @@
* @param steps le nouvel univers des etapes
*/
public void setSteps(E... steps) {
- List<E> oldValue = this.steps;
+ java.util.List<E> oldValue = this.steps;
this.steps = java.util.Collections.unmodifiableList(java.util.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 boolean validate(E s) {
return step != null;
}
@@ -194,6 +229,10 @@
pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue);
}
+ protected E[] updateStepUniverse() {
+ return null;
+ }
+
protected void updateUniverse() {
}
}
Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -1,20 +0,0 @@
-package jaxx.runtime.swing.wizard;
-
-/**
- *
- * @param <Action>
- * @author tony
- * @since 1.3
- */
-public interface WizardOperation<Action extends WizardOperationAction> {
-
- String name();
-
- int ordinal();
-
- String getLabel();
-
- String getDescription();
-
- public Action newAction();
-}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -6,27 +6,31 @@
import org.apache.commons.logging.LogFactory;
/**
+ * La classe de base a implanter pour definir l'action d'une operation
+ * dans un wizard.
*
* @author tony
* @param <E> le type d'étapes
- * @param <O> le type d'opérations
* @param <M> le type de modèle
* @since 1.3
*/
-public abstract class WizardOperationAction<E extends Enum<E>, O extends Enum<O>, M extends WizardOperationModel<E, O>> extends SwingWorker<WizardOperationState, String> {
+public abstract class WizardOperationAction<E extends WizardOperationStep, M extends WizardOperationModel<E>> extends SwingWorker<WizardOperationState, String> {
/** to use log facility, just put in your code: log.info(\"...\"); */
private static final Log log = LogFactory.getLog(WizardOperationAction.class);
- O operation;
+ E operation;
WizardOperationState operationState;
Exception error;
- public WizardOperationAction(O operation) {
+ public WizardOperationAction(E operation) {
super();
+ if (!operation.isOperation()) {
+ throw new IllegalArgumentException("the step " + operation + " has no operation defined");
+ }
this.operation = operation;
}
- public O getOperation() {
+ public E getOperation() {
return operation;
}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -2,7 +2,6 @@
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
import java.util.Date;
import javax.swing.SwingWorker.StateValue;
import jaxx.runtime.JAXXContext;
@@ -18,14 +17,13 @@
* Note: Pour bloquer (ou débloquer) le thread, on utilise la méthode {@link #setWaiting(boolean)}
*
* @param <E> le type des etapes
- * @param <O> le type des operations
* @param <M> le type de modele
* @param <A> le type d'action d'operation
*
* @author tony
* @since 1.3
*/
-public abstract class WizardOperationActionThread<E extends Enum<E>, O extends Enum<O>, M extends WizardOperationModel<E, O>, A extends WizardOperationAction<E, O, M>> extends Thread implements PropertyChangeListener {
+public abstract class WizardOperationActionThread<E extends WizardOperationStep, M extends WizardOperationModel<E>, A extends WizardOperationAction<E, M>> extends Thread implements PropertyChangeListener {
/** to use log facility, just put in your code: log.info(\"...\"); */
private static final Log log = LogFactory.getLog(WizardOperationActionThread.class);
@@ -33,8 +31,6 @@
* l'état du thread si annulé
*/
private boolean canceled;
- /** suport of modification propagation */
- protected PropertyChangeSupport pcs;
protected Class<M> modelClass;
protected A currentAction;
/**
@@ -50,7 +46,6 @@
public WizardOperationActionThread(Class<M> modelClass) throws IllegalArgumentException {
super(WizardOperationActionThread.class.getSimpleName() + " " + new Date());
this.modelClass = modelClass;
- this.pcs = new PropertyChangeSupport(this);
}
public void cancel() {
@@ -66,20 +61,25 @@
setWaiting(false);
}
- public void launchOperation(A action) {
+ @SuppressWarnings("unchecked")
+ public void launchOperation(E operation) {
if (currentAction != null) {
// on ne peut traiter qu'une seule opération à la fois
throw new IllegalStateException("can not add a operation when thread is busy, or has another operation to be done");
}
- currentAction = action;
+ try {
+ currentAction = (A) operation.getActionClass().newInstance();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
// on libere le thread pour qu'il execute l'opération
setWaiting(false);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
- log.info(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">");
+ log.trace(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">");
if ("state".equals(evt.getPropertyName())) {
//@SuppressWarnings("unchecked")
//A action = (A) evt.getSource();
@@ -166,39 +166,6 @@
log.trace(this);
}
- // PropertyChanged support
- 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 firePropertyChange(String propertyName, Object oldValue, Object newValue) {
- pcs.firePropertyChange(propertyName, oldValue, newValue);
- }
-
protected void setWaiting(boolean waiting) {
if (waiting && !canceled) {
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -2,16 +2,17 @@
import java.util.EnumMap;
import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
/**
* Un modèle de wizard avec des opérations.
*
* @param <E> le type des étapes.
- * @param <O> le type des opérations.
* @author tony
* @since 1.3
*/
-public class WizardOperationModel<E extends Enum<E>, O extends Enum<O>> extends WizardModel<E> {
+public class WizardOperationModel<E extends WizardOperationStep> extends WizardModel<E> {
public static final String OPERATIONS_PROPERTY_NAME = "operations";
public static final String OPERATION_STATE_PROPERTY_NAME = "operationState";
@@ -20,15 +21,15 @@
/**
* le type d'une opération
*/
- protected Class<O> operationClass;
+// protected Class<O> operationClass;
/**
* La liste des opérations à effectuer
*/
- protected EnumSet<O> operations;
+ protected Set<E> operations;
/**
* Pour conserver les états des opérations
*/
- protected EnumMap<O, WizardOperationState> operationStates;
+ protected Map<E, WizardOperationState> operationStates;
/**
* L'état générale du modèle
*/
@@ -38,16 +39,15 @@
*/
protected boolean wasStarted;
- public WizardOperationModel(Class<E> stepClass, Class<O> operationClass, E... steps) {
+ @SuppressWarnings("unchecked")
+ public <T extends Enum<T>> WizardOperationModel(Class<E> stepClass, E... steps) {
super(stepClass, steps);
- this.operationClass = operationClass;
- this.operationStates = new EnumMap<O, WizardOperationState>(operationClass);
+ Class<T> k = (Class) stepClass;
+ this.operationStates = (Map) new EnumMap(k);
+ this.operations = (Set<E>) EnumSet.noneOf(k);
}
- public EnumSet<O> getOperations() {
- if (operations == null) {
- operations = EnumSet.noneOf(operationClass);
- }
+ public Set<E> getOperations() {
return operations;
}
@@ -60,43 +60,68 @@
}
@SuppressWarnings("unchecked")
- public O getOperation() {
- return ((WizardOperationStep<O>) getStep()).getOperation();
+ public E getOperation() {
+ return getStep() != null && getStep().isOperation() ? getStep() : null;
}
public WizardOperationState getOperationState() {
- O operation = getOperation();
+ E operation = getOperation();
return getOperationState(operation);
}
- public WizardOperationState getOperationState(O operation) {
+ public WizardOperationState getOperationState(E operation) {
return operationStates.get(operation);
}
public void setOperationState(WizardOperationState operationState) {
- O operation = getOperation();
+ E operation = getOperation();
setOperationState(operation, operationState);
}
- public void setOperationState(O operation, WizardOperationState operationState) {
+ public void setOperationState(E operation, WizardOperationState operationState) {
WizardOperationState oldValue = getOperationState(operation);
this.operationStates.put(operation, operationState);
- firePropertyChange(OPERATION_STATE_PROPERTY_NAME, oldValue, operationState);
- //fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, getOperationIndex(operation), oldValue, operationStates);
+ fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, getSteps().indexOf(operation), oldValue, operationState);
updateModelState(operation, operationState);
validate();
}
+ public boolean[] getAccessibleSteps() {
+ 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 == WizardOperationState.SUCCESSED ||
+ (result[i - 1] &&
+ validate(previousStep) &&
+ (!previousStep.isOperation() || getOperationState(previousStep) == WizardOperationState.SUCCESSED));
+ }
+ }
+ System.out.println("accessibles steps -------- " + java.util.Arrays.toString(result));
+ return result;
+ }
+
@Override
public void start() {
super.start();
+ updateUniverse();
+ //setSteps(steps.toArray((E[]) Array.newInstance(stepClass, steps.size())));
+
// le modèle n'est pas démarré
setModelState(WizardOperationState.PENDING);
- firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
}
public void cancel() {
- for (O op : operations) {
+ for (E op : operations) {
if (getOperationState(op) == WizardOperationState.PENDING) {
// on annule l'opération à venir
setOperationState(op, WizardOperationState.CANCELED);
@@ -104,10 +129,8 @@
}
}
- public WizardOperationModel<E, O> addOperation(O operation) {
- getOperations().add(operation);
- // on force la propagation de la nouvelle liste
- firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ public WizardOperationModel<E> addOperation(E operation) {
+ operations.add(operation);
// mis a jour de l'univers des etapes et operations
updateUniverse();
// validation
@@ -115,16 +138,27 @@
return this;
}
- public void removeOperation(O operation) {
- getOperations().remove(operation);
- // on force la propagation de la nouvelle liste
- firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ public void removeOperation(E operation) {
+ 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);
+ // on force la propagation de la nouvelle liste
+ firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ int index = 0;
+ for (E e : steps) {
+ fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, index++, null, getOperationState(e));
+ }
+ firePropertyChange(MODEL_STATE_PROPERTY_NAME, null, modelState);
+ }
+
protected void setModelState(WizardOperationState modelState) {
WizardOperationState oldValue = this.modelState;
this.modelState = modelState;
@@ -137,33 +171,33 @@
}
}
- protected void updateModelState(O operation, WizardOperationState operationState) {
+ protected void updateModelState(E operation, WizardOperationState operationState) {
switch (operationState) {
case RUNNING:
- //le model est occupé
+ //le modele est occupé
setModelState(WizardOperationState.RUNNING);
break;
case FAILED:
- //le model est en attente
- setModelState(WizardOperationState.PENDING);
+ //le modele est en erreur
+ setModelState(WizardOperationState.FAILED);
break;
case CANCELED:
- //le model devient annulé
+ //le modele devient annulé
setModelState(WizardOperationState.CANCELED);
break;
case PENDING:
- //le model est en attente
+ //le modele est en attente
setModelState(WizardOperationState.PENDING);
break;
case NEED_FIX:
- //le model est en attente
+ //le modele est en attente
setModelState(WizardOperationState.PENDING);
break;
case SUCCESSED:
// on regarde si on peut passer le model a l'état success
boolean valid = true;
- for (O o : operations) {
+ for (E o : operations) {
if (getOperationState(o) != WizardOperationState.SUCCESSED) {
valid = false;
break;
@@ -178,9 +212,15 @@
}
}
- protected int getOperationIndex(O operation) {
+ @Override
+ protected void updateUniverse() {
+ E[] newSteps = updateStepUniverse();
+ setSteps(newSteps);
+ }
+
+ protected int getOperationIndex(E operation) {
int index = 0;
- for (O o : operations) {
+ for (E o : operations) {
if (operation == o) {
return index;
}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -2,19 +2,33 @@
/**
*
- * @param <Operation>
+ * Le contrat a implanter pour une etapes dans le modèle de wizard avec
+ * opérations.
+ *
* @author tony
* @since 1.3
*/
-public interface WizardOperationStep<Operation extends Enum<Operation>> {
+public interface WizardOperationStep extends WizardStep {
- String name();
+ /**
+ * @return le label de l'opération
+ */
+ String getOperationLabel();
- int ordinal();
+ /**
+ * @return la description de l'opération
+ */
+ String getOperationDescription();
- String getLabel();
+ /**
+ * @return le type de l'action associée à l'étape ou <code>null</code> si
+ * l'étape n'a pas d'opération associée.
+ */
+ Class<? extends WizardOperationAction> getActionClass();
- String getDescription();
-
- Operation getOperation();
+ /**
+ * @return <code>true</code> si l'étape a une opération associée,
+ * <code>false</code> sinon.
+ */
+ boolean isOperation();
}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStep.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -0,0 +1,20 @@
+package jaxx.runtime.swing.wizard;
+
+import java.io.Serializable;
+
+/**
+ * le contrat d'une étape d'un wizard.
+ *
+ * @author tony
+ * @since 1.3
+ */
+public interface WizardStep extends Serializable {
+
+ String name();
+
+ int ordinal();
+
+ String getLabel();
+
+ String getDescription();
+}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardStepUI.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -0,0 +1,14 @@
+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 tony
+ * @since 1.3
+ */
+public interface WizardStepUI<E extends WizardStep, M extends WizardModel<E>> {
+
+ E getStep();
+}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -12,13 +12,27 @@
* @author tony
* @since 1.3
*/
-public interface WizardUI<E extends Enum<E>, M extends WizardModel<E>> {
+public interface WizardUI<E extends WizardStep, M extends WizardModel<E>> {
- public E getSelectedStep();
-
M getModel();
+ E getSelectedStep();
+
+ WizardStepUI<E, M> getSelectedStepUI();
+
+ WizardStepUI<E, M> getStepUI(E step);
+
+ WizardStepUI<E, M> getStepUI(int stepIndex);
+
void start();
JTabbedPane getTabs();
+
+ void onStepsChanged(E[] steps);
+
+ void onStepChanged(E newStep);
+
+ void onModelStateChanged(WizardOperationState newState);
+
+ void onOperationStateChanged(E step,WizardOperationState newState) ;
}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-15 11:23:33 UTC (rev 1267)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -8,7 +8,7 @@
/**
*
- * Une classe pour lancer une ui avec wizard.
+ * Une classe pour lancer une ui de wizard.
*
* @param <E> le type des etapes
* @param <M> le type de modele
@@ -16,11 +16,45 @@
* @author tony
* @since 1.3
*/
-public abstract class WizardUILancher<E extends Enum<E>, M extends WizardModel<E>, UI extends WizardUI<E, M>> {
+public abstract class WizardUILancher<E extends WizardStep, M extends WizardModel<E>, UI extends WizardUI<E, M>> {
protected UI ui;
@SuppressWarnings("unchecked")
+ public WizardUILancher(JAXXContext context, JFrame mainUI, Class<UI> uiClass, M model) {
+ super();
+ try {
+ // instanciate ui parent context
+ JAXXInitialContext uiContext = new JAXXInitialContext();
+ uiContext.add(mainUI == null ? context : mainUI);
+ // parent context model
+ uiContext.add(model);
+ // apply action
+ uiContext.add("apply", new Runnable() {
+
+ @Override
+ public void run() {
+ doAction(ui);
+ }
+ });
+ // cancel action
+ uiContext.add("cancel", new Runnable() {
+
+ @Override
+ public void run() {
+ doCancel(ui);
+ }
+ });
+
+ // instanciate ui
+ ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext}, new Class[]{JFrame.class, JAXXContext.class});
+
+ } catch (Exception ex) {
+ throw new RuntimeException("could not instanciate launcher for reason " + ex.getMessage(), ex);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
public WizardUILancher(JAXXContext context, JFrame mainUI, Class<UI> uiClass, Class<M> modelClass) {
super();
try {
@@ -64,7 +98,7 @@
}
public void dispose() {
- ui = null;
+ // par defaut, on ne fait rien
}
public <T> T getContextValue(Class<T> clazz, String name) {
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUtil.java 2009-03-16 18:44:15 UTC (rev 1268)
@@ -0,0 +1,93 @@
+package jaxx.runtime.swing.wizard;
+
+import java.beans.IndexedPropertyChangeEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.lang.reflect.Array;
+import org.apache.commons.logging.Log;
+
+/**
+ * Classe de méthodes utiles sur les wizard.
+ *
+ * @author tony
+ * @since 1.3
+ */
+public class WizardUtil {
+
+ protected WizardUtil() {
+ }
+
+ public static boolean acceptStates(WizardOperationState state, WizardOperationState... accepted) {
+ for (WizardOperationState s : accepted) {
+ if (s == state) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean rejectStates(WizardOperationState state, WizardOperationState... rejected) {
+ for (WizardOperationState 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 (WizardModel.STEPS_PROPERTY_NAME.equals(propertyName)) {
+ java.util.List<E> steps = (java.util.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 (WizardOperationModel.MODEL_STATE_PROPERTY_NAME.equals(propertyName)) {
+ //TODO should be unicast : only for good stepUI ?
+ ui.onModelStateChanged((WizardOperationState) evt.getNewValue());
+ return;
+ }
+ if (WizardOperationModel.OPERATION_STATE_PROPERTY_NAME.equals(propertyName)) {
+ IndexedPropertyChangeEvent e = (IndexedPropertyChangeEvent) evt;
+ int stepIndex = e.getIndex();
+ E step = ui.getModel().getSteps().get(stepIndex);
+ ui.onOperationStateChanged(step, (WizardOperationState) evt.getNewValue());
+ return;
+ }
+ }
+ });
+ }
+}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/package.html
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/package.html (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/package.html 2009-03-16 18:44:15 UTC (rev 1268)
@@ -0,0 +1,9 @@
+<html>
+ <body>
+ <h1>JAXX - Wizard framework</h1>
+
+ This package contains all the classes of the wizard framework.
+
+ TODO
+ </body>
+</html>
\ No newline at end of file
1
0
r1267 - jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard
by tchemit@users.labs.libre-entreprise.org 15 Mar '09
by tchemit@users.labs.libre-entreprise.org 15 Mar '09
15 Mar '09
Author: tchemit
Date: 2009-03-15 11:23:33 +0000 (Sun, 15 Mar 2009)
New Revision: 1267
Modified:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
Log:
rendre publique les m?\195?\169thode d'acces au context
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-14 19:24:14 UTC (rev 1266)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-15 11:23:33 UTC (rev 1267)
@@ -67,16 +67,7 @@
ui = null;
}
- protected void init(UI ui) {
- }
-
- protected void doAction(UI ui) {
- }
-
- protected void doCancel(UI ui) {
- }
-
- protected <T> T getContextValue(Class<T> clazz, String name) {
+ public <T> T getContextValue(Class<T> clazz, String name) {
if (ui == null) {
throw new NullPointerException("ui can not be null");
}
@@ -87,7 +78,16 @@
return ((JAXXObject) ui).getContextValue(clazz, name);
}
- protected <T> T getContextValue(Class<T> clazz) {
+ 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) {
+ }
}
1
0
r1266 - in jaxx/trunk: jaxx-compiler-api/src/main/java/jaxx/compiler jaxx-runtime-swing/src/main/java/jaxx/runtime jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard
by tchemit@users.labs.libre-entreprise.org 14 Mar '09
by tchemit@users.labs.libre-entreprise.org 14 Mar '09
14 Mar '09
Author: tchemit
Date: 2009-03-14 19:24:14 +0000 (Sat, 14 Mar 2009)
New Revision: 1266
Added:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java
Removed:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java
Modified:
jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
Log:
wizard framework done
Modified: jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java
===================================================================
--- jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -20,75 +20,61 @@
import java.util.List;
import java.util.Map;
-
/**
* Represents an object in the <code>.java</code> file being generated during compilation. There is
* a <code>CompiledObject</code> for each class tag encountered, and certain tags may generate
* additional objects for various reasons.
*/
public class CompiledObject {
+
/** The object's id. */
private String id;
-
/** Java code referring to the object. */
private String javaCode;
-
/** The object's class. */
private ClassDescriptor objectClass;
-
/** The style class. */
private String styleClass;
-
/** The container containing this CompiledObject. */
private CompiledObject parent;
-
/** true if this object overrides an object of the same id in a superclass of the object being compiled */
private boolean override;
-
/**
* Comma-separated Java code snippets representing the parameters that should be passed to the object's
* constructor.
*/
private String constructorParams;
-
/**
* Java code snippet which performs basic initialization of the object (after it has already been constructed).
* Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other
* CompiledObjects from initializationCode -- you must refer to them from additionCode instead.
*/
private StringBuffer initializationCode = new StringBuffer();
-
/**
* Java code snippet which completes setup by adding any child objects, or otherwise manipulates any refererenced
* objects. Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other
* CompiledObjects from initializationCode -- you must refer to them from additionCode instead.
*/
private StringBuffer additionCode = new StringBuffer();
-
/** List of all registered event handlers. */
private List<EventHandler> eventHandlers = new ArrayList<EventHandler>();
-
/** All properties that have been applied to this CompiledObject. */
private Map<String, String> properties = new HashMap<String, String>();
-
/** generic types of the compiled object */
private String[] genericTypes;
-
/** a flag to indicate if javaBean full support must be support for this object by root object */
private boolean javaBean;
-
/** code to initialize the bean (can be null) */
private String javaBeanInitCode;
-
/** the type of the override object (can be null if no oveeride) */
private ClassDescriptor overrideType;
-
/**
* the decorator (if null will use {@link DefaultCompiledObjectDecorator}).
*/
private CompiledObjectDecorator decorator;
-
+
public class ChildRef {
+
CompiledObject child;
String constraints;
String childJavaCode;
@@ -142,7 +128,6 @@
buffer.append(JAXXCompiler.getLineSeparator());
}
}
-
private List<ChildRef> childs;
/**
@@ -158,7 +143,6 @@
this(id, objectClass, compiler, false);
}
-
/**
* Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a
* <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}.
@@ -173,7 +157,6 @@
this(id, id, objectClass, compiler, force);
}
-
/**
* Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a
* <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}.
@@ -202,7 +185,6 @@
this.childs = new ArrayList<ChildRef>();
}
-
public static boolean isValidID(String id) {
boolean valid = true;
if (id.length() == 0) {
@@ -224,7 +206,6 @@
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
@@ -237,7 +218,6 @@
return override;
}
-
/**
* Sets whether this class overrides an identically-named object in the parent class.
*
@@ -248,7 +228,6 @@
this.override = override;
}
-
/**
* Returns this object's CSS style class.
*
@@ -258,7 +237,6 @@
return styleClass;
}
-
/**
* Sets this object's CSS style class.
*
@@ -268,7 +246,6 @@
this.styleClass = styleClass;
}
-
/**
* Returns this object's parent container. Non-visual components (and the root container) return <code>null</code>.
*
@@ -278,7 +255,6 @@
return parent;
}
-
/**
* Sets this object's parent container.
*
@@ -291,7 +267,6 @@
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.
@@ -302,7 +277,6 @@
return "create" + org.apache.commons.lang.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.
@@ -313,7 +287,6 @@
return "addChildrenTo" + org.apache.commons.lang.StringUtils.capitalize(getId());
}
-
/**
* Returns the type of this object.
*
@@ -323,7 +296,6 @@
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.
@@ -334,7 +306,6 @@
return id;
}
-
/**
* Returns Java code used to refer to this object in the compiled Java file. This is usually the same as its
* id.
@@ -382,7 +353,6 @@
return constructorParams;
}
-
/**
* Sets the parameters to pass to this object's constructor.
*
@@ -393,7 +363,6 @@
this.constructorParams = constructorParams;
}
-
/**
* Returns the code that performs basic initialization of this object, after it has already been constructed.
* This basic code should not reference any other <code>CompiledObjects</code> as they may not have
@@ -411,7 +380,6 @@
return result.toString();
}
-
protected String getInitializationCode(EventHandler handler, JAXXCompiler compiler) {
MethodDescriptor addMethod = handler.getAddMethod();
ClassDescriptor listenerClass = addMethod.getParameterTypes()[0];
@@ -421,7 +389,6 @@
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.
@@ -432,7 +399,6 @@
return additionCode.toString();
}
-
/**
* Appends code to the initialization code block. A line separator is automatically appended to the end.
*
@@ -444,7 +410,6 @@
this.initializationCode.append(JAXXCompiler.getLineSeparator());
}
-
/**
* Appends code to the addition code block. A line separator is automatically appended to the end.
*
@@ -456,7 +421,6 @@
this.additionCode.append(JAXXCompiler.getLineSeparator());
}
-
/**
* Stores a property for this object. The only effect of calling this method is that the property will
* be returned by <code>getProperties()</code>.
@@ -469,7 +433,6 @@
properties.put(property, value);
}
-
/**
* Returns all properties which have been set for this object.
*
@@ -480,7 +443,6 @@
return properties;
}
-
// TODO: remove this temporary method and complete switchover to MethodDescriptors
public void addEventHandler(String eventId, Method addMethod, Method listenerMethod, String code, JAXXCompiler compiler) {
try {
@@ -490,13 +452,11 @@
MethodDescriptor addMethodDescriptor = descriptor.getMethodDescriptor(addMethod.getName(), listenerDescriptor);
MethodDescriptor listenerMethodDescriptor = listenerDescriptor.getMethodDescriptor(listenerMethod.getName(), ClassDescriptorLoader.getClassDescriptor(listenerMethod.getParameterTypes()[0].getName()));
addEventHandler(eventId, addMethodDescriptor, listenerMethodDescriptor, code, compiler);
- }
- catch (Exception e) {
+ } catch (Exception e) {
throw new RuntimeException(e);
}
}
-
/**
* Adds an event listener to this object. The generated code will appear in the initialization block.
*
@@ -517,7 +477,6 @@
}
}
-
/**
* Adds a child component to this container. The child is added without layout constraints.
*
@@ -530,7 +489,6 @@
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.
@@ -546,8 +504,7 @@
if (constraints != null) {
constraints = compiler.checkJavaCode(constraints);
}
- }
- catch (CompilerException e) {
+ } catch (CompilerException e) {
compiler.reportError("While parsing 'constraints' attribute: " + e.getMessage());
}
@@ -561,7 +518,7 @@
String delegateCode = containerDelegate != null ? "." + containerDelegate + "()" : "";
child.setParent(this);
-
+
childs.add(new ChildRef(child, constraints, child.getJavaCode(), delegateCode));
}
}
@@ -571,7 +528,6 @@
return getObjectClass().getName() + "[id='" + id + "']";
}
-
public void registerDataBinding(String src, String property, String assignment, JAXXCompiler compiler) throws CompilerException {
compiler.registerDataBinding(src, getId() + "." + property, assignment);
}
@@ -584,7 +540,7 @@
for (int i = 0, j = getGenericTypesLength(); i < j; i++) {
result += ", " + genericTypes[i];
}
- return "< " + result.substring(1) + " >";
+ return "< " + result.substring(2) + " >";
}
public void setGenericTypes(String[] genericTypes) {
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -409,7 +409,10 @@
public void reset() {
setReverse(reverse);
}
-
+
+ public int size() {
+ return tabs.getTabCount();
+ }
public TabbedPaneIterator<O> reverse() {
setReverse(!reverse);
return this;
Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -1,94 +0,0 @@
-package jaxx.runtime.swing.wizard;
-
-import javax.swing.SwingWorker;
-import jaxx.runtime.JAXXContext;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- *
- * @author tony
- * @param <E>
- * @param <O>
- * @param <R>
- * @param <M>
- * @since 1.3
- */
-public abstract class WizardAbstractOperationAction<E extends Enum<E>,O extends Enum<O>, R extends Enum<R>, M extends WizardModelWithOperations<E,O,R>> extends SwingWorker<R, String> {
-
- /** to use log facility, just put in your code: log.info(\"...\"); */
- private static final Log log = LogFactory.getLog(WizardAbstractOperationAction.class);
- O operation;
- Exception error;
-
- public WizardAbstractOperationAction(O operation) {
- super();
- this.operation = operation;
- }
-
- public O getOperation() {
- return operation;
- }
-
- public abstract void start(JAXXContext context);
-
- public abstract void beforeAction(JAXXContext context, M model) throws Exception;
-
- public abstract R doAction(M model) throws Exception;
-
- public abstract R onError(M model, Exception e);
-
- public abstract R onCancel(M model, Exception e);
-
- public abstract void afterAction(M model, R result, Exception error);
-
- protected abstract M getModel();
-
- protected abstract JAXXContext getContext();
-
- @Override
- public String toString() {
- return super.toString() + " < operation: " + operation + ", state: " + getState() + " >";
- }
-
- @Override
- protected R doInBackground() throws Exception {
- R result;
- M model = getModel();
- try {
- log.info(this);
- beforeAction(getContext(), model);
- result = doAction(model);
- } catch (Exception e) {
- error = e;
- result = onError(model, e);
- }
- return result;
- }
-
- @Override
- protected void done() {
- R result = null;
- log.info(this);
- M model = getModel();
- try {
- if (isCancelled()) {
-
- result = onCancel(model, error);
- } else {
- result = get();
- }
- } catch (Exception e) {
- // ne devrait jamais arrivé ?
- log.error(e.getMessage(), e);
- throw new RuntimeException(e);
- } finally {
- // on enregistre le resultat de l'opération
-
- model.setOperationResult(operation, result);
-
- // on notifie le resultat de l'action
- firePropertyChange(WizardModelWithOperations.OPERATION_RESULT_PROPERTY_NAME, null, result);
- }
- }
-}
Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -1,265 +0,0 @@
-package jaxx.runtime.swing.wizard;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.Date;
-import jaxx.runtime.JAXXContext;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Thread qui réalise les opérations.
- *
- * Pour exécuter une nouvelle opération, on utilise la méthode
- * {@link #launchOperation(SynchroActionWorker)}.
- *
- * Le thread possède 2 états internes :
- *
- * - busy lorsqu'il exécute une opération
- *
- * - canceled lorqu'une annulation a été demandée via la méthode {@link #setCanceled(boolean)}
- *
- * Note: Pour bloquer (ou débloquer) le thread, on utilise la méthode {@link #setwaiting(boolean)}
- * @param <E> le type des etapes
- * @param <O> le type des operations
- * @param <R> le type des resultats d'operation
- * @param <M> le type de modele
- * @param <A> le type d'action d'operation
- *
- * @author tony
- * @since 1.3
- */
-public abstract class WizardAbstractOperationActionThread<E extends Enum<E>, O extends Enum<O>, R extends Enum<R>, M extends WizardModelWithOperations<E, O, R>, A extends WizardAbstractOperationAction<E, O, R, M>> extends Thread implements PropertyChangeListener {
-
- /** to use log facility, just put in your code: log.info(\"...\"); */
- private static final Log log = LogFactory.getLog(WizardAbstractOperationActionThread.class);
- public static final String BUSY_PROPERTY_NAME = "busy";
- public static final String CANCELED_PROPERTY_NAME = "canceled";
- /**
- * l'état du thread pendant les étapes non interactives
- */
- private boolean busy;
- /**
- * l'état du thread si annulé
- */
- private boolean canceled;
- /** suport of modification propagation */
- protected PropertyChangeSupport pcs;
- /** le context applicatif */
- protected JAXXContext cotext;
- protected Class<M> modelClass;
- protected A currentAction;
- /**
- * un lock pour permettre la suspension et la reprise du thread
- * lors du mode interactif.
- */
- private final Object LOCK = new Object();
-
- protected abstract M getModel();
- protected abstract JAXXContext getContext();
-
- public WizardAbstractOperationActionThread(Class<M> modelClass) throws IllegalArgumentException {
- super(WizardAbstractOperationActionThread.class.getSimpleName() + " " + new Date());
- this.modelClass = modelClass;
- this.pcs = new PropertyChangeSupport(this);
- }
-
- public boolean isBusy() {
- return busy;
- }
-
- public boolean isCanceled() {
- return canceled;
- }
-
- public void cancel() {
- setCanceled(true);
- //currentAction = null;
- setBusy(false);
- setWaiting(false);
- }
-
- public void launchOperation(A action) {
-
- if (busy || currentAction != null) {
- // on ne peut traiter qu'une seule opération à la fois
- throw new IllegalStateException("can not add a operation when thread is busy, or has another operation to be done");
- }
- currentAction = action;
- // on libere le thread pour qu'il execute l'opération
- setWaiting(false);
- }
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (WizardModelWithOperations.OPERATION_RESULT_PROPERTY_NAME.equals(evt.getPropertyName())) {
- // on rend la main au thread pour qu'il attende une prochaine operation
- setWaiting(false);
- }
- }
-
- @Override
- public void run() {
- try {
-
- // on vérifie que le context contient bien le modèle
- if (getModel()==null) {
- throw new NullPointerException("could not find model "+modelClass+" for "+this);
- }
-
- while (!canceled) {
-
- if (canceled) {
- // une annulation a été demandé
- // donc même si une opération est demandée, on ne la traite
- // pas
- break;
- }
-
- // en attente qu'une opération
- // le block est bloqué jusqu'à arrivée d'une opération
- // ou une demande d'annulation
- setWaiting(true);
-
- // le thread a repris la main, donc plus en attente
- log.trace("no more waiting " + this);
-
- if (!canceled) {
- // une opération a été demandée
-
- // le thread passe en éta occupé
- setBusy(true);
- // le thread écoute les modifications de l'action
- currentAction.addPropertyChangeListener(this);
- // démarrage de l'opération
- currentAction.start(getContext());
- // le thread est bloqué jusqu'à la fin de l'opération
- // ou une demande d'annulation
- setWaiting(true);
- // la main a ete rendue, le thread n'est plus actif
- setBusy(false);
- }
-
- // le thread reprend la main des que l'operation
- // est terminée ou a été annulée, on passera alors
- // dans la méthode onPropertyChanged
- if (currentAction != null) {
- // le thread n'écoute plus l'action car elle est terminée
- // ou annulée
- currentAction.removePropertyChangeListener(this);
- // suppression de l'action
- currentAction = null;
- }
-
- }
-
- } catch (Exception e) {
- throw new RuntimeException(e);
- } finally {
- if (busy) {
- setBusy(false);
- setWaiting(false);
- }
-
- log.info(this + " will close...");
- close();
- }
- }
-
- /**
- * La méthode pour nettoyer le thread, a la fermeture.
- *
- */
- protected void close() {
- // par defaut, on ne fait rien
- log.info(this);
- }
-
- // PropertyChanged support
- 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 firePropertyChange(String propertyName, Object oldValue, Object newValue) {
- pcs.firePropertyChange(propertyName, oldValue, newValue);
- }
-
- protected void setBusy(boolean busy) {
- boolean oldValue = this.busy;
- this.busy = busy;
- firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy);
- }
-
- protected void setCanceled(boolean canceled) {
- boolean oldValue = this.canceled;
- this.canceled = canceled;
- if (currentAction != null) {
- log.info("cancel action " + currentAction);
- // on a une action en cours, on l'annule
- currentAction.cancel(true);
- }
- // on annule aussi le model
- getModel().cancel();
- //on notifie les écouteur que le thread est annulé
- firePropertyChange(CANCELED_PROPERTY_NAME, oldValue, canceled);
- }
-
- protected void setWaiting(boolean waiting) {
-
- if (waiting && !canceled) {
- // locking thread
- try {
- lockThread();
- } catch (InterruptedException ex) {
- log.error(ex.getMessage(), ex);
- canceled = true;
- }
- }
-
- if (!waiting) {
- // release lock
- unlockThread();
- }
- }
-
- protected void lockThread() throws InterruptedException {
- synchronized (LOCK) {
- log.trace(this);
- // lock
- LOCK.wait();
- }
- }
-
- protected void unlockThread() {
- synchronized (LOCK) {
- log.trace(this);
- // unlock
- LOCK.notify();
- }
- }
-}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -19,7 +19,6 @@
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";
-
/**
* le type d'une etape du model (doit etre une enumeration)
*/
@@ -134,7 +133,7 @@
// la propriete nextStep peut avoir changee
firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep());
}
-
+
public boolean validate(E s) {
return step != null;
}
@@ -160,6 +159,7 @@
pcs.removePropertyChangeListener(l);
}
}
+
protected Class<E> getStepClass() {
return stepClass;
}
@@ -190,7 +190,10 @@
pcs.firePropertyChange(propertyName, oldValue, newValue);
}
+ protected void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
+ pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue);
+ }
+
protected void updateUniverse() {
-
}
}
Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -1,96 +0,0 @@
-package jaxx.runtime.swing.wizard;
-
-import java.util.EnumMap;
-import java.util.EnumSet;
-
-/**
- * Un modèle de wizard.
- *
- * @param <E> le type de l'énumération contenant les etapes.
- *
- * @param <O> le type de l'énumeration des opérations
- * @param <R> le type de l'énumération des résultats d'opération
- * @author tony
- * @since 1.3
- */
-public abstract class WizardModelWithOperations<E extends Enum<E>, O extends Enum<O>, R extends Enum<R>> extends WizardModel<E> {
-
- public static final String OPERATIONS_PROPERTY_NAME = "operations";
- public static final String OPERATION_RESULT_PROPERTY_NAME = "operationResult";
- /**
- * La liste des opérations à effectuer
- */
- protected EnumSet<O> operations;
- /**
- * Pour conserver les résultats des opérations
- */
- protected EnumMap<O, R> operationResults;
- protected Class<O> operationClass;
- protected Class<R> operationResultClass;
-
- public abstract void cancel();
-
- //protected abstract boolean isCancelResult(R operationResult);
- //protected abstract boolean isErrorResult(R operationResult);
-
- public WizardModelWithOperations(Class<E> stepClass, Class<O> operationClass, Class<R> operationResultClass, E... steps) {
- super(stepClass, steps);
- this.operationClass = operationClass;
- this.operationResultClass = operationResultClass;
- operationResults = new EnumMap<O, R>(operationClass);
- }
-
- public EnumSet<O> getOperations() {
- if (operations == null) {
- operations = EnumSet.noneOf(operationClass);
- }
- return operations;
- }
-
- public R getOperationResult(O operation) {
- return operationResults.get(operation);
- }
-
- public void setOperationResult(O operation, R operationResult) {
- R oldValue = getOperationResult(operation);
- operationResults.put(operation, operationResult);
- firePropertyChange(OPERATION_RESULT_PROPERTY_NAME, oldValue, operationResult);
- }
-
- @Override
- public void start() {
- super.start();
- firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
- }
-
- public WizardModelWithOperations<E, O, R> addOperation(O operation) {
- getOperations().add(operation);
- /*if (operation == SynchroOperation.EXPORT_DATA) {
- // pour exporter les données utilisateurs
- // les operations synchronisation de référentiel et validation
- // sont necessaires
- getOperations().add(SynchroOperation.SYNCHRONIZE_REFERENTIEL);
- getOperations().add(SynchroOperation.VALIDATION);
- }*/
- // on force la propagation de la nouvelle liste
- firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
-
- updateUniverse();
- validate();
- return this;
- }
-
- public void removeOperation(O operation) {
- getOperations().remove(operation);
- /*if (operation == SynchroOperation.SYNCHRONIZE_REFERENTIEL || operation == SynchroOperation.VALIDATION) {
- // pour exporter les données utilisateurs
- // les operations synchronisation de référentiel et validation
- // sont necessaires
- getOperations().remove(SynchroOperation.EXPORT_DATA);
- }*/
- // on force la propagation de la nouvelle liste
- firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
- updateUniverse();
- validate();
- }
-}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -6,7 +6,7 @@
* @author tony
* @since 1.3
*/
-public interface WizardOperation<Action extends WizardAbstractOperationAction> {
+public interface WizardOperation<Action extends WizardOperationAction> {
String name();
Copied: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java (from rev 1265, jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java)
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -0,0 +1,94 @@
+package jaxx.runtime.swing.wizard;
+
+import javax.swing.SwingWorker;
+import jaxx.runtime.JAXXContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author tony
+ * @param <E> le type d'étapes
+ * @param <O> le type d'opérations
+ * @param <M> le type de modèle
+ * @since 1.3
+ */
+public abstract class WizardOperationAction<E extends Enum<E>, O extends Enum<O>, M extends WizardOperationModel<E, O>> extends SwingWorker<WizardOperationState, String> {
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ private static final Log log = LogFactory.getLog(WizardOperationAction.class);
+ O operation;
+ WizardOperationState operationState;
+ Exception error;
+
+ public WizardOperationAction(O operation) {
+ super();
+ this.operation = operation;
+ }
+
+ public O getOperation() {
+ return operation;
+ }
+
+ public abstract void start(JAXXContext context);
+
+ public abstract void beforeAction(JAXXContext context, M model) throws Exception;
+
+ public abstract WizardOperationState doAction(M model) throws Exception;
+
+ public abstract WizardOperationState onError(M model, Exception e);
+
+ public abstract WizardOperationState onCancel(M model, Exception e);
+
+ public abstract void afterAction(M model, WizardOperationState result, Exception error);
+
+ protected abstract M getModel();
+
+ public WizardOperationState getOperationState() {
+ return operationState;
+ }
+
+ protected abstract JAXXContext getContext();
+
+ @Override
+ public String toString() {
+ return super.toString() + " < operation: " + operation + ", state: " + getState() + " >";
+ }
+
+ @Override
+ protected WizardOperationState doInBackground() throws Exception {
+ log.trace(this);
+ WizardOperationState result;
+ M model = getModel();
+ try {
+ beforeAction(getContext(), model);
+ result = doAction(model);
+ } catch (Exception e) {
+ error = e;
+ result = onError(model, e);
+ }
+ return result;
+ }
+
+ @Override
+ protected void done() {
+ log.trace(this);
+ WizardOperationState result = null;
+ try {
+ if (isCancelled()) {
+
+ result = onCancel(getModel(), error);
+ } else {
+ result = get();
+ }
+ } catch (Exception e) {
+ result = WizardOperationState.FAILED;
+ error = e;
+ // ne devrait jamais arrivé ?
+ log.error(e.getMessage(), e);
+ } finally {
+ // on enregistre le resultat de l'opération
+ this.operationState = result;
+ }
+ }
+}
Property changes on: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java (from rev 1265, jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java)
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -0,0 +1,235 @@
+package jaxx.runtime.swing.wizard;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.Date;
+import javax.swing.SwingWorker.StateValue;
+import jaxx.runtime.JAXXContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Thread qui réalise les opérations.
+ *
+ * Pour exécuter une nouvelle opération, on utilise la méthode
+ * {@link #launchOperation(SynchroActionWorker)}.
+ *
+ * Note: Pour bloquer (ou débloquer) le thread, on utilise la méthode {@link #setWaiting(boolean)}
+ *
+ * @param <E> le type des etapes
+ * @param <O> le type des operations
+ * @param <M> le type de modele
+ * @param <A> le type d'action d'operation
+ *
+ * @author tony
+ * @since 1.3
+ */
+public abstract class WizardOperationActionThread<E extends Enum<E>, O extends Enum<O>, M extends WizardOperationModel<E, O>, A extends WizardOperationAction<E, O, M>> extends Thread implements PropertyChangeListener {
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ private static final Log log = LogFactory.getLog(WizardOperationActionThread.class);
+ /**
+ * l'état du thread si annulé
+ */
+ private boolean canceled;
+ /** suport of modification propagation */
+ protected PropertyChangeSupport pcs;
+ protected Class<M> modelClass;
+ protected A currentAction;
+ /**
+ * un lock pour permettre la suspension et la reprise du thread
+ * lors du mode interactif.
+ */
+ private final Object LOCK = new Object();
+
+ protected abstract M getModel();
+
+ protected abstract JAXXContext getContext();
+
+ public WizardOperationActionThread(Class<M> modelClass) throws IllegalArgumentException {
+ super(WizardOperationActionThread.class.getSimpleName() + " " + new Date());
+ this.modelClass = modelClass;
+ this.pcs = new PropertyChangeSupport(this);
+ }
+
+ public void cancel() {
+ if (currentAction != null) {
+ log.debug("cancel action " + currentAction);
+ // on a une action en cours, on l'annule
+ currentAction.cancel(true);
+ }
+ // on annule aussi le modele
+ getModel().cancel();
+ this.canceled = true;
+ // on rend la main au thread
+ setWaiting(false);
+ }
+
+ public void launchOperation(A action) {
+
+ if (currentAction != null) {
+ // on ne peut traiter qu'une seule opération à la fois
+ throw new IllegalStateException("can not add a operation when thread is busy, or has another operation to be done");
+ }
+ currentAction = action;
+ // on libere le thread pour qu'il execute l'opération
+ setWaiting(false);
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ log.info(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">");
+ if ("state".equals(evt.getPropertyName())) {
+ //@SuppressWarnings("unchecked")
+ //A action = (A) evt.getSource();
+ StateValue state = (StateValue) evt.getNewValue();
+ if (state == StateValue.DONE) {
+ // on rend la main au thread pour qu'il attende une prochaine operation
+ //getModel().setOperationState(action.getOperation(), action.getOperationState());
+ setWaiting(false);
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+
+ // on vérifie que le context contient bien le modèle
+ if (getModel() == null) {
+ throw new NullPointerException("could not find model " + modelClass + " for " + this);
+ }
+
+ while (!canceled) {
+
+ if (canceled) {
+ // une annulation a été demandé
+ // donc même si une opération est demandée, on ne la traite
+ // pas
+ break;
+ }
+
+ // en attente qu'une opération
+ // le block est bloqué jusqu'à arrivée d'une opération
+ // ou une demande d'annulation
+ setWaiting(true);
+
+ // le thread a repris la main, donc plus en attente
+ log.trace("no more waiting " + this);
+
+ if (!canceled) {
+ // une opération a été demandée
+
+ // le thread écoute les modifications de l'action
+ currentAction.addPropertyChangeListener(this);
+
+ // l'opération passe en etant en cours
+ getModel().setOperationState(WizardOperationState.RUNNING);
+
+ // démarrage de l'opération dans un worker
+ currentAction.start(getContext());
+ // le thread est bloqué jusqu'à la fin de l'opération
+ // ou une demande d'annulation
+ setWaiting(true);
+
+ // le thread reprend la main des que l'operation
+ // est terminée ou a été annulée, on passera alors
+ // dans la méthode onPropertyChanged
+
+ getModel().setOperationState(currentAction.getOperationState());
+
+ // le thread n'écoute plus l'action car elle est terminée
+ // ou annulée
+ currentAction.removePropertyChangeListener(this);
+ // suppression de l'action
+ currentAction = null;
+ }
+
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ unlockThread();
+ log.trace(this + " will close...");
+ close();
+ }
+ }
+
+ /**
+ * La méthode pour nettoyer le thread, a la fermeture.
+ *
+ */
+ protected void close() {
+ // par defaut, on ne fait rien
+ log.trace(this);
+ }
+
+ // PropertyChanged support
+ 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 firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+ pcs.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ protected void setWaiting(boolean waiting) {
+
+ if (waiting && !canceled) {
+ // locking thread
+ try {
+ lockThread();
+ } catch (InterruptedException ex) {
+ log.error(ex.getMessage(), ex);
+ canceled = true;
+ }
+ }
+
+ if (!waiting) {
+ // release lock
+ unlockThread();
+ }
+ }
+
+ protected void lockThread() throws InterruptedException {
+ synchronized (LOCK) {
+ log.trace(this);
+ // lock
+ LOCK.wait();
+ }
+ }
+
+ protected void unlockThread() {
+ synchronized (LOCK) {
+ log.trace(this);
+ // unlock
+ LOCK.notify();
+ }
+ }
+}
Property changes on: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java (from rev 1265, jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java)
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -0,0 +1,191 @@
+package jaxx.runtime.swing.wizard;
+
+import java.util.EnumMap;
+import java.util.EnumSet;
+
+/**
+ * Un modèle de wizard avec des opérations.
+ *
+ * @param <E> le type des étapes.
+ * @param <O> le type des opérations.
+ * @author tony
+ * @since 1.3
+ */
+public class WizardOperationModel<E extends Enum<E>, O extends Enum<O>> extends WizardModel<E> {
+
+ public static final String OPERATIONS_PROPERTY_NAME = "operations";
+ public static final String OPERATION_STATE_PROPERTY_NAME = "operationState";
+ public static final String MODEL_STATE_PROPERTY_NAME = "modelState";
+ public static final String WAS_STARTED_PROPERTY_NAME = "wasStarted";
+ /**
+ * le type d'une opération
+ */
+ protected Class<O> operationClass;
+ /**
+ * La liste des opérations à effectuer
+ */
+ protected EnumSet<O> operations;
+ /**
+ * Pour conserver les états des opérations
+ */
+ protected EnumMap<O, WizardOperationState> operationStates;
+ /**
+ * L'état générale du modèle
+ */
+ protected WizardOperationState modelState;
+ /**
+ * un drapeau pour savoir siune opération a été lancée
+ */
+ protected boolean wasStarted;
+
+ public WizardOperationModel(Class<E> stepClass, Class<O> operationClass, E... steps) {
+ super(stepClass, steps);
+ this.operationClass = operationClass;
+ this.operationStates = new EnumMap<O, WizardOperationState>(operationClass);
+ }
+
+ public EnumSet<O> getOperations() {
+ if (operations == null) {
+ operations = EnumSet.noneOf(operationClass);
+ }
+ return operations;
+ }
+
+ public WizardOperationState getModelState() {
+ return modelState;
+ }
+
+ public boolean isWasStarted() {
+ return wasStarted;
+ }
+
+ @SuppressWarnings("unchecked")
+ public O getOperation() {
+ return ((WizardOperationStep<O>) getStep()).getOperation();
+ }
+
+ public WizardOperationState getOperationState() {
+ O operation = getOperation();
+ return getOperationState(operation);
+ }
+
+ public WizardOperationState getOperationState(O operation) {
+ return operationStates.get(operation);
+ }
+
+ public void setOperationState(WizardOperationState operationState) {
+ O operation = getOperation();
+ setOperationState(operation, operationState);
+ }
+
+ public void setOperationState(O operation, WizardOperationState operationState) {
+ WizardOperationState oldValue = getOperationState(operation);
+ this.operationStates.put(operation, operationState);
+ firePropertyChange(OPERATION_STATE_PROPERTY_NAME, oldValue, operationState);
+ //fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, getOperationIndex(operation), oldValue, operationStates);
+ updateModelState(operation, operationState);
+ validate();
+ }
+
+ @Override
+ public void start() {
+ super.start();
+ // le modèle n'est pas démarré
+ setModelState(WizardOperationState.PENDING);
+ firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ }
+
+ public void cancel() {
+ for (O op : operations) {
+ if (getOperationState(op) == WizardOperationState.PENDING) {
+ // on annule l'opération à venir
+ setOperationState(op, WizardOperationState.CANCELED);
+ }
+ }
+ }
+
+ public WizardOperationModel<E, O> addOperation(O operation) {
+ getOperations().add(operation);
+ // on force la propagation de la nouvelle liste
+ firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ // mis a jour de l'univers des etapes et operations
+ updateUniverse();
+ // validation
+ validate();
+ return this;
+ }
+
+ public void removeOperation(O operation) {
+ getOperations().remove(operation);
+ // on force la propagation de la nouvelle liste
+ firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ // mis a jour de l'univers des etapes et operations
+ updateUniverse();
+ // validation
+ validate();
+ }
+
+ protected void setModelState(WizardOperationState modelState) {
+ WizardOperationState oldValue = this.modelState;
+ this.modelState = modelState;
+ firePropertyChange(MODEL_STATE_PROPERTY_NAME, oldValue, modelState);
+ if (!wasStarted) {
+ if ((oldValue == null || oldValue == WizardOperationState.PENDING) && modelState == WizardOperationState.RUNNING) {
+ this.wasStarted = true;
+ firePropertyChange(WAS_STARTED_PROPERTY_NAME, false, true);
+ }
+ }
+ }
+
+ protected void updateModelState(O operation, WizardOperationState operationState) {
+
+ switch (operationState) {
+ case RUNNING:
+ //le model est occupé
+ setModelState(WizardOperationState.RUNNING);
+ break;
+ case FAILED:
+ //le model est en attente
+ setModelState(WizardOperationState.PENDING);
+ break;
+ case CANCELED:
+ //le model devient annulé
+ setModelState(WizardOperationState.CANCELED);
+ break;
+ case PENDING:
+ //le model est en attente
+ setModelState(WizardOperationState.PENDING);
+ break;
+ case NEED_FIX:
+ //le model est en attente
+ setModelState(WizardOperationState.PENDING);
+ break;
+ case SUCCESSED:
+ // on regarde si on peut passer le model a l'état success
+ boolean valid = true;
+ for (O o : operations) {
+ if (getOperationState(o) != WizardOperationState.SUCCESSED) {
+ valid = false;
+ break;
+ }
+ }
+ if (valid) {
+ setModelState(WizardOperationState.SUCCESSED);
+ } else {
+ setModelState(WizardOperationState.PENDING);
+ }
+ break;
+ }
+ }
+
+ protected int getOperationIndex(O operation) {
+ int index = 0;
+ for (O o : operations) {
+ if (operation == o) {
+ return index;
+ }
+ index++;
+ }
+ return -1;
+ }
+}
Property changes on: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java
___________________________________________________________________
Name: svn:mergeinfo
+
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -0,0 +1,32 @@
+package jaxx.runtime.swing.wizard;
+
+/**
+ * Pour caractériser l'état d'une opération.
+ */
+public enum WizardOperationState {
+
+ /**
+ * 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
+}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -0,0 +1,20 @@
+package jaxx.runtime.swing.wizard;
+
+/**
+ *
+ * @param <Operation>
+ * @author tony
+ * @since 1.3
+ */
+public interface WizardOperationStep<Operation extends Enum<Operation>> {
+
+ String name();
+
+ int ordinal();
+
+ String getLabel();
+
+ String getDescription();
+
+ Operation getOperation();
+}
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -18,8 +18,6 @@
M getModel();
- void init();
-
void start();
JTabbedPane getTabs();
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-13 22:00:34 UTC (rev 1265)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-14 19:24:14 UTC (rev 1266)
@@ -20,18 +20,14 @@
protected UI ui;
- protected abstract void doAction(UI ui);
-
@SuppressWarnings("unchecked")
public WizardUILancher(JAXXContext context, JFrame mainUI, Class<UI> uiClass, Class<M> modelClass) {
super();
try {
+ // instanciate ui parent context
JAXXInitialContext uiContext = new JAXXInitialContext();
- // instanciate ui
- // parent context
uiContext.add(mainUI == null ? context : mainUI);
- // parent context
- // model
+ // parent context model
uiContext.add(modelClass.newInstance());
// apply action
uiContext.add("apply", new Runnable() {
@@ -51,7 +47,7 @@
});
// instanciate ui
- ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext});
+ ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext}, new Class[]{JFrame.class, JAXXContext.class});
} catch (Exception ex) {
throw new RuntimeException("could not instanciate launcher for reason " + ex.getMessage(), ex);
@@ -59,20 +55,28 @@
}
public void start() {
- init(ui);
- //ui.start();
+ try {
+ init(ui);
+ ui.start();
+ } finally {
+ dispose();
+ }
}
+ public void dispose() {
+ ui = null;
+ }
+
protected void init(UI ui) {
}
- protected void afterInit(UI ui) {
+ protected void doAction(UI ui) {
}
protected void doCancel(UI ui) {
}
- public <T> T getContextValue(Class<T> clazz, String name) {
+ protected <T> T getContextValue(Class<T> clazz, String name) {
if (ui == null) {
throw new NullPointerException("ui can not be null");
}
@@ -83,11 +87,7 @@
return ((JAXXObject) ui).getContextValue(clazz, name);
}
- public <T> T getContextValue(Class<T> clazz) {
+ protected <T> T getContextValue(Class<T> clazz) {
return getContextValue(clazz, null);
}
-
- public void dispose() {
- ui = null;
- }
}
1
0
r1265 - in jaxx/trunk: . jaxx-compiler-api jaxx-compiler-api/src/main/java/jaxx/compiler jaxx-compiler-api/src/main/java/jaxx/tags jaxx-example jaxx-example/src/main/java/jaxx/demo jaxx-example/src/main/resources/i18n jaxx-runtime-swing/src/main/java/jaxx/runtime jaxx-runtime-swing/src/main/java/jaxx/runtime/swing jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard
by tchemit@users.labs.libre-entreprise.org 13 Mar '09
by tchemit@users.labs.libre-entreprise.org 13 Mar '09
13 Mar '09
Author: tchemit
Date: 2009-03-13 22:00:34 +0000 (Fri, 13 Mar 2009)
New Revision: 1265
Added:
jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/EmptyDemo.jaxx
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
Removed:
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/WizardModel.java
Modified:
jaxx/trunk/changelog.txt
jaxx/trunk/jaxx-compiler-api/changelog.txt
jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java
jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXCompiler.java
jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXObjectGenerator.java
jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/tags/DefaultObjectHandler.java
jaxx/trunk/jaxx-example/changelog.txt
jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx
jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx
jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties
jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
jaxx/trunk/pom.xml
Log:
- improve demo
- 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
-use i18n 0.10
-introduce Wizard package (must do javadoc)
- add iterator method util on JTabbedPane
Modified: jaxx/trunk/changelog.txt
===================================================================
--- jaxx/trunk/changelog.txt 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/changelog.txt 2009-03-13 22:00:34 UTC (rev 1265)
@@ -1,3 +1,5 @@
+1.3
+ * 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
Modified: jaxx/trunk/jaxx-compiler-api/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-compiler-api/changelog.txt 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-compiler-api/changelog.txt 2009-03-13 22:00:34 UTC (rev 1265)
@@ -1,4 +1,7 @@
1.3 ??? 200902??
+ * 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
Modified: jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java
===================================================================
--- jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -575,26 +575,27 @@
public void registerDataBinding(String src, String property, String assignment, JAXXCompiler compiler) throws CompilerException {
compiler.registerDataBinding(src, getId() + "." + property, assignment);
}
-
- /** @return the array of generic types of the compiled object, or a empty array if none defined */
- public ClassDescriptor[] getGenericTypes() {
- if (genericTypes == null) {
- return new ClassDescriptor[0];
+ public String getGenericTypes() {
+ if (getGenericTypesLength() == 0) {
+ // not using it
+ return "";
}
- try {
- ClassDescriptor[] result = new ClassDescriptor[genericTypes.length];
- for (int i = 0; i < result.length; i++) {
- result[i] = ClassDescriptorLoader.getClassDescriptor(genericTypes[i], getObjectClass().getClassLoader());
- }
- return result;
+ String result = "";
+ for (int i = 0, j = getGenericTypesLength(); i < j; i++) {
+ result += ", " + genericTypes[i];
}
- catch (ClassNotFoundException e) {
- throw new RuntimeException(e);
- }
+ return "< " + result.substring(1) + " >";
}
public void setGenericTypes(String[] genericTypes) {
- this.genericTypes = 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() {
@@ -647,4 +648,8 @@
additionCode = buffer.append(additionCode);
}
+
+ public int getGenericTypesLength() {
+ return genericTypes == null ? 0 : genericTypes.length;
+ }
}
\ No newline at end of file
Modified: jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXCompiler.java
===================================================================
--- jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXCompiler.java 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXCompiler.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -887,6 +887,15 @@
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;
}
@@ -1399,16 +1408,8 @@
if (clazz.isArray()) {
String canonicalName = getCanonicalName(clazz.getComponentType());
if (canonicalName != null) {
- if (compiled.getGenericTypes().length > 0) {
- canonicalName += "<";
- for (int i = 0; i < compiled.getGenericTypes().length; i++) {
- ClassDescriptor classDescriptor = compiled.getGenericTypes()[i];
- if (i > 0) {
- canonicalName += " ,";
- }
- canonicalName += classDescriptor.getName();
- }
- canonicalName += ">";
+ if (compiled.getGenericTypesLength() > 0) {
+ canonicalName += compiled.getGenericTypes();
}
return canonicalName + "[]";
}
@@ -1416,16 +1417,8 @@
}
String canonicalName = clazz.getName().replace('$', '.');
- if (compiled.getGenericTypes().length > 0) {
- canonicalName += "<";
- for (int i = 0; i < compiled.getGenericTypes().length; i++) {
- ClassDescriptor classDescriptor = compiled.getGenericTypes()[i];
- if (i > 0) {
- canonicalName += " ,";
- }
- canonicalName += classDescriptor.getName();
- }
- canonicalName += ">";
+ if (compiled.getGenericTypesLength() > 0) {
+ canonicalName += compiled.getGenericTypes();
}
return canonicalName;
}
Modified: jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXObjectGenerator.java
===================================================================
--- jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXObjectGenerator.java 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/JAXXObjectGenerator.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -536,7 +536,11 @@
code.append(compiler.getLateInitializer());
code.append(JAXXCompiler.getLineSeparator());
}
-
+ //TC-20090313 add an extra method after complete setup
+ MethodDescriptor method = compiler.getScriptMethod("$afterCompleteSetup");
+ if (method!=null) {
+ code.append("$afterCompleteSetup();").append(JAXXCompiler.getLineSeparator());
+ }
return JavaMethod.newMethod(Modifier.PRIVATE, "void", "$completeSetup", code.toString());
}
Modified: jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/tags/DefaultObjectHandler.java
===================================================================
--- jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/tags/DefaultObjectHandler.java 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/tags/DefaultObjectHandler.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -539,7 +539,12 @@
setDefaults(object, tag, compiler);
setAttributes(object, tag, compiler);
-
+ 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);
}
@@ -625,8 +630,9 @@
String name = attribute.getName();
String value = attribute.getValue();
if (name.equals("javaBean")) {
+ //compiler.preprocessScript(value);
continue;
- }
+ }
if (name.equals("constraints") || isEventHandlerName(name)) {
compiler.preprocessScript(value); // adds dependencies as a side effect
} else if (name.equals("constructorParams")) {
@@ -695,12 +701,12 @@
}
if (name.equals("genericType")) {
- if (object != compiler.getRootObject()) {
- // can ony be apply to root object
- compiler.reportError("'genericType' attribute can only be found on root tag but was found on tag " + tag);
- return;
+ //TC-20090313 check after all atributes been processed
+ if (object == compiler.getRootObject() ) {
+ compiler.setGenericType(value);
+ } else {
+ object.setGenericTypes(value.split(","));
}
- compiler.setGenericType(value);
continue;
}
@@ -1041,9 +1047,9 @@
*/
protected int constantValue(String key, String value) {
JAXXBeanInfo JAXXBeanInfo = getJAXXBeanInfo();
- JAXXPropertyDescriptor[] properties = JAXXBeanInfo.getJAXXPropertyDescriptors();
+ JAXXPropertyDescriptor[] props = JAXXBeanInfo.getJAXXPropertyDescriptors();
String lowercaseValue = value.toLowerCase();
- for (JAXXPropertyDescriptor property : properties) {
+ for (JAXXPropertyDescriptor property : props) {
if (property.getName().equals(key)) {
Object[] values = (Object[]) property.getValue("enumerationValues");
if (values != null) {
Modified: jaxx/trunk/jaxx-example/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-example/changelog.txt 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-example/changelog.txt 2009-03-13 22:00:34 UTC (rev 1265)
@@ -1,3 +1,6 @@
+1.3
+ * 20090313 [chemit] - improve demo
+
1.1 chemit 20090220
* 20090202 [chemit] - no more scope attribute on validator
- fix I18NTableCellRenderer (must have tip inside)
Modified: jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx
===================================================================
--- jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/BoxedDecoratorDemo.jaxx 2009-03-13 22:00:34 UTC (rev 1265)
@@ -14,13 +14,12 @@
<script><![CDATA[
import jaxx.runtime.SwingUtil;
-public void initLayer() {
+void $afterCompleteSetup() {
for (JComponent boxed : SwingUtil.getLayeredComponents(this)) {
jaxx.runtime.swing.BlockingLayerUI ui = layerUI.clone();
if ( boxed == c) {
- ui.setUseIcon(false);
ui.setBlock(true);
- }
+ }
SwingUtil.getLayer(boxed).setUI(ui);
//ui.setDirty(true);
}
@@ -31,12 +30,8 @@
jaxx.runtime.swing.BlockingLayerUI ui = (jaxx.runtime.swing.BlockingLayerUI)SwingUtil.getLayer(boxed).getUI();
if ( boxed == c) {
ui.setBlock(active);
- } else {
- ui.setUseIcon(active);
- }
- //ui.setBlock(active && boxed == c);
- //ui.setUseIcon(active && boxed != c);
- //ui.setDirty(true);
+ }
+ ui.setUseIcon(active);
}
}
Added: jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/EmptyDemo.jaxx
===================================================================
--- jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/EmptyDemo.jaxx (rev 0)
+++ jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/EmptyDemo.jaxx 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,5 @@
+<DemoPanel>
+<JPanel id='demoPanel'>
+ <JLabel text='emptyNode'/>
+</JPanel>
+</DemoPanel>
\ No newline at end of file
Modified: jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx
===================================================================
--- jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-example/src/main/java/jaxx/demo/JAXXDemo.jaxx 2009-03-13 22:00:34 UTC (rev 1265)
@@ -1,21 +1,26 @@
<Application title="JAXX Demo" width='1024' height='800' defaultCloseOperation='exit_on_close'>
<script><![CDATA[
-protected void changePanel() {
- Object value = list.getSelectionValue();
- if (value instanceof DemoPanel) {
- cardLayout.show(preview, ((DemoPanel) value).getLabel());
- }
+
+org.codelutin.i18n.I18n.init();
+
+void $afterCompleteSetup() {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ int i=0;
+ while( i < list.getRowCount()) {
+ list.expandRow(i++);
+ }
+ }
+ });
}
-// init i18n
-org.codelutin.i18n.I18n.init();
-boxedDecoratorDemo.initLayer();
-//boxedDecoratorDemo.setLayer(true);
]]></script>
<JSplitPane>
<!--JSplitPane dividerLocation='200'-->
<JScrollPane>
- <JTree id='list' showsRootHandles='true' onValueChanged='changePanel()'
+ <JTree id='list' showsRootHandles='true'
+ onValueChanged='cardLayout.show(preview, list.getSelectionValue() instanceof DemoPanel ? ((DemoPanel) list.getSelectionValue()).getLabel() : emptyDemo.getLabel())'
cellRenderer='{new javax.swing.tree.DefaultTreeCellRenderer() {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (value instanceof DemoPanel)
@@ -82,6 +87,7 @@
<java.awt.CardLayout id='cardLayout'/>
<JPanel id='preview' layout='{cardLayout}'>
+ <EmptyDemo id='emptyDemo' constraints='emptyDemo.getLabel()'/>
<JButtonDemo id='buttonDemo' constraints='buttonDemo.getLabel()'/>
<JCheckBoxDemo id='checkBoxDemo' constraints='checkBoxDemo.getLabel()'/>
<JCheckBoxMenuItemDemo id='checkBoxMenuItemDemo' constraints='checkBoxMenuItemDemo.getLabel()'/>
Modified: jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-en_GB.properties 2009-03-13 22:00:34 UTC (rev 1265)
@@ -88,6 +88,7 @@
button\ A=
button\ B=
button\ C=
+button\ C\ (full\ block)=
button\ with\ layer=
cancel=
close=
@@ -96,6 +97,7 @@
edit=
edit2=
edit3=
+emptyNode=< empty node >
no\ layer=
valid=
validator.field=Champ
Modified: jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties
===================================================================
--- jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-example/src/main/resources/i18n/jaxx-example-fr_FR.properties 2009-03-13 22:00:34 UTC (rev 1265)
@@ -88,6 +88,7 @@
button\ A=
button\ B=
button\ C=
+button\ C\ (full\ block)=
button\ with\ layer=
cancel=
close=
@@ -96,6 +97,7 @@
edit=
edit2=
edit3=
+emptyNode=< empty node >
no\ layer=
valid=
validator.field=Champ
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map;
@@ -31,6 +32,7 @@
import java.util.Properties;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
+import javax.swing.JTabbedPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import jaxx.runtime.swing.I18nTableCellRenderer;
@@ -357,4 +359,101 @@
}
}
}
+
+ /**
+ * Iterate the components of a {@link JTabbedPane} in natural order.
+ *
+ * Says using method {@link JTabbedPane#getComponent(int)}
+ * @param tabs the
+ * @return
+ * @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}.
+ *
+ * Implements the method {@link #get(int, java.awt.Component)} to obtain
+ * the data required given the component (or index).
+ *
+ * You can also inverse the order by usin the method {@link #reverse()}.
+ *
+ * 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 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 IllegalStateException("no next objet! for " + this);
+ }
+ Component next = tabs.getComponent(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;
+ }
+ }
}
Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/WizardModel.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/WizardModel.java 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/WizardModel.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -1,191 +0,0 @@
-package jaxx.runtime.swing;
-
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.List;
-
-/**
- * Un modèle de wizard.
- *
- * @param <E> le type de l'énumération contenant les etapes.
- *
- * @author tony
- * @since 1.3
- */
-public class WizardModel<E extends Enum<E>> {
-
- 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";
- /**
- * le type d'une etape du model (doit etre une enumeration)
- */
- protected final Class<E> stepClass;
- /**
- * Toutes les étapes à passer
- */
- protected List<E> steps;
- /**
- * L'étape courante
- */
- protected E step;
- /**
- * drapeau pour valider l'état de l'étape courante
- */
- protected boolean validStep;
- /**
- * pour propager les changements dans le modèle vers l'ui
- */
- protected PropertyChangeSupport pcs;
-
- public WizardModel(Class<E> stepClass, E... steps) {
- this.stepClass = stepClass;
- this.pcs = new PropertyChangeSupport(this);
- this.steps = new java.util.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 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 + " is not in universe of steps (" + steps + ")");
- }
- setStep(e);
- }
-
- 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() {
- 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;
- }
-
- /**
- * Change l'univers des etapes.
- *
- * 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 = java.util.Collections.unmodifiableList(java.util.Arrays.asList(steps));
- firePropertyChange(STEPS_PROPERTY_NAME, oldValue, this.steps);
- // la propriete nextStep peut avoir changee
- firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep());
- }
-
- 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() {
- for (PropertyChangeListener l : pcs.getPropertyChangeListeners()) {
- pcs.removePropertyChangeListener(l);
- }
- }
- protected 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 validate() {
- if (step == null) {
- // pas de validation quand aucune etape n'est sélectionnée
- return;
- }
- boolean validate = validate(step);
- this.validStep = validate;
- // toujours forcer la propagation
- firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep);
- }
-
- protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
- pcs.firePropertyChange(propertyName, oldValue, newValue);
- }
-}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,94 @@
+package jaxx.runtime.swing.wizard;
+
+import javax.swing.SwingWorker;
+import jaxx.runtime.JAXXContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author tony
+ * @param <E>
+ * @param <O>
+ * @param <R>
+ * @param <M>
+ * @since 1.3
+ */
+public abstract class WizardAbstractOperationAction<E extends Enum<E>,O extends Enum<O>, R extends Enum<R>, M extends WizardModelWithOperations<E,O,R>> extends SwingWorker<R, String> {
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ private static final Log log = LogFactory.getLog(WizardAbstractOperationAction.class);
+ O operation;
+ Exception error;
+
+ public WizardAbstractOperationAction(O operation) {
+ super();
+ this.operation = operation;
+ }
+
+ public O getOperation() {
+ return operation;
+ }
+
+ public abstract void start(JAXXContext context);
+
+ public abstract void beforeAction(JAXXContext context, M model) throws Exception;
+
+ public abstract R doAction(M model) throws Exception;
+
+ public abstract R onError(M model, Exception e);
+
+ public abstract R onCancel(M model, Exception e);
+
+ public abstract void afterAction(M model, R result, Exception error);
+
+ protected abstract M getModel();
+
+ protected abstract JAXXContext getContext();
+
+ @Override
+ public String toString() {
+ return super.toString() + " < operation: " + operation + ", state: " + getState() + " >";
+ }
+
+ @Override
+ protected R doInBackground() throws Exception {
+ R result;
+ M model = getModel();
+ try {
+ log.info(this);
+ beforeAction(getContext(), model);
+ result = doAction(model);
+ } catch (Exception e) {
+ error = e;
+ result = onError(model, e);
+ }
+ return result;
+ }
+
+ @Override
+ protected void done() {
+ R result = null;
+ log.info(this);
+ M model = getModel();
+ try {
+ if (isCancelled()) {
+
+ result = onCancel(model, error);
+ } else {
+ result = get();
+ }
+ } catch (Exception e) {
+ // ne devrait jamais arrivé ?
+ log.error(e.getMessage(), e);
+ throw new RuntimeException(e);
+ } finally {
+ // on enregistre le resultat de l'opération
+
+ model.setOperationResult(operation, result);
+
+ // on notifie le resultat de l'action
+ firePropertyChange(WizardModelWithOperations.OPERATION_RESULT_PROPERTY_NAME, null, result);
+ }
+ }
+}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,265 @@
+package jaxx.runtime.swing.wizard;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.Date;
+import jaxx.runtime.JAXXContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Thread qui réalise les opérations.
+ *
+ * Pour exécuter une nouvelle opération, on utilise la méthode
+ * {@link #launchOperation(SynchroActionWorker)}.
+ *
+ * Le thread possède 2 états internes :
+ *
+ * - busy lorsqu'il exécute une opération
+ *
+ * - canceled lorqu'une annulation a été demandée via la méthode {@link #setCanceled(boolean)}
+ *
+ * Note: Pour bloquer (ou débloquer) le thread, on utilise la méthode {@link #setwaiting(boolean)}
+ * @param <E> le type des etapes
+ * @param <O> le type des operations
+ * @param <R> le type des resultats d'operation
+ * @param <M> le type de modele
+ * @param <A> le type d'action d'operation
+ *
+ * @author tony
+ * @since 1.3
+ */
+public abstract class WizardAbstractOperationActionThread<E extends Enum<E>, O extends Enum<O>, R extends Enum<R>, M extends WizardModelWithOperations<E, O, R>, A extends WizardAbstractOperationAction<E, O, R, M>> extends Thread implements PropertyChangeListener {
+
+ /** to use log facility, just put in your code: log.info(\"...\"); */
+ private static final Log log = LogFactory.getLog(WizardAbstractOperationActionThread.class);
+ public static final String BUSY_PROPERTY_NAME = "busy";
+ public static final String CANCELED_PROPERTY_NAME = "canceled";
+ /**
+ * l'état du thread pendant les étapes non interactives
+ */
+ private boolean busy;
+ /**
+ * l'état du thread si annulé
+ */
+ private boolean canceled;
+ /** suport of modification propagation */
+ protected PropertyChangeSupport pcs;
+ /** le context applicatif */
+ protected JAXXContext cotext;
+ protected Class<M> modelClass;
+ protected A currentAction;
+ /**
+ * un lock pour permettre la suspension et la reprise du thread
+ * lors du mode interactif.
+ */
+ private final Object LOCK = new Object();
+
+ protected abstract M getModel();
+ protected abstract JAXXContext getContext();
+
+ public WizardAbstractOperationActionThread(Class<M> modelClass) throws IllegalArgumentException {
+ super(WizardAbstractOperationActionThread.class.getSimpleName() + " " + new Date());
+ this.modelClass = modelClass;
+ this.pcs = new PropertyChangeSupport(this);
+ }
+
+ public boolean isBusy() {
+ return busy;
+ }
+
+ public boolean isCanceled() {
+ return canceled;
+ }
+
+ public void cancel() {
+ setCanceled(true);
+ //currentAction = null;
+ setBusy(false);
+ setWaiting(false);
+ }
+
+ public void launchOperation(A action) {
+
+ if (busy || currentAction != null) {
+ // on ne peut traiter qu'une seule opération à la fois
+ throw new IllegalStateException("can not add a operation when thread is busy, or has another operation to be done");
+ }
+ currentAction = action;
+ // on libere le thread pour qu'il execute l'opération
+ setWaiting(false);
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (WizardModelWithOperations.OPERATION_RESULT_PROPERTY_NAME.equals(evt.getPropertyName())) {
+ // on rend la main au thread pour qu'il attende une prochaine operation
+ setWaiting(false);
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+
+ // on vérifie que le context contient bien le modèle
+ if (getModel()==null) {
+ throw new NullPointerException("could not find model "+modelClass+" for "+this);
+ }
+
+ while (!canceled) {
+
+ if (canceled) {
+ // une annulation a été demandé
+ // donc même si une opération est demandée, on ne la traite
+ // pas
+ break;
+ }
+
+ // en attente qu'une opération
+ // le block est bloqué jusqu'à arrivée d'une opération
+ // ou une demande d'annulation
+ setWaiting(true);
+
+ // le thread a repris la main, donc plus en attente
+ log.trace("no more waiting " + this);
+
+ if (!canceled) {
+ // une opération a été demandée
+
+ // le thread passe en éta occupé
+ setBusy(true);
+ // le thread écoute les modifications de l'action
+ currentAction.addPropertyChangeListener(this);
+ // démarrage de l'opération
+ currentAction.start(getContext());
+ // le thread est bloqué jusqu'à la fin de l'opération
+ // ou une demande d'annulation
+ setWaiting(true);
+ // la main a ete rendue, le thread n'est plus actif
+ setBusy(false);
+ }
+
+ // le thread reprend la main des que l'operation
+ // est terminée ou a été annulée, on passera alors
+ // dans la méthode onPropertyChanged
+ if (currentAction != null) {
+ // le thread n'écoute plus l'action car elle est terminée
+ // ou annulée
+ currentAction.removePropertyChangeListener(this);
+ // suppression de l'action
+ currentAction = null;
+ }
+
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (busy) {
+ setBusy(false);
+ setWaiting(false);
+ }
+
+ log.info(this + " will close...");
+ close();
+ }
+ }
+
+ /**
+ * La méthode pour nettoyer le thread, a la fermeture.
+ *
+ */
+ protected void close() {
+ // par defaut, on ne fait rien
+ log.info(this);
+ }
+
+ // PropertyChanged support
+ 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 firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+ pcs.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ protected void setBusy(boolean busy) {
+ boolean oldValue = this.busy;
+ this.busy = busy;
+ firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy);
+ }
+
+ protected void setCanceled(boolean canceled) {
+ boolean oldValue = this.canceled;
+ this.canceled = canceled;
+ if (currentAction != null) {
+ log.info("cancel action " + currentAction);
+ // on a une action en cours, on l'annule
+ currentAction.cancel(true);
+ }
+ // on annule aussi le model
+ getModel().cancel();
+ //on notifie les écouteur que le thread est annulé
+ firePropertyChange(CANCELED_PROPERTY_NAME, oldValue, canceled);
+ }
+
+ protected void setWaiting(boolean waiting) {
+
+ if (waiting && !canceled) {
+ // locking thread
+ try {
+ lockThread();
+ } catch (InterruptedException ex) {
+ log.error(ex.getMessage(), ex);
+ canceled = true;
+ }
+ }
+
+ if (!waiting) {
+ // release lock
+ unlockThread();
+ }
+ }
+
+ protected void lockThread() throws InterruptedException {
+ synchronized (LOCK) {
+ log.trace(this);
+ // lock
+ LOCK.wait();
+ }
+ }
+
+ protected void unlockThread() {
+ synchronized (LOCK) {
+ log.trace(this);
+ // unlock
+ LOCK.notify();
+ }
+ }
+}
Copied: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java (from rev 1258, jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/WizardModel.java)
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,196 @@
+package jaxx.runtime.swing.wizard;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.List;
+
+/**
+ * Un modèle de wizard.
+ *
+ * @param <E> le type de l'énumération contenant les etapes.
+ *
+ * @author tony
+ * @since 1.3
+ */
+public class WizardModel<E extends Enum<E>> {
+
+ 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";
+
+ /**
+ * le type d'une etape du model (doit etre une enumeration)
+ */
+ protected final Class<E> stepClass;
+ /**
+ * Toutes les étapes à passer
+ */
+ protected List<E> steps;
+ /**
+ * L'étape courante
+ */
+ protected E step;
+ /**
+ * drapeau pour valider l'état de l'étape courante
+ */
+ protected boolean validStep;
+ /**
+ * pour propager les changements dans le modèle vers l'ui
+ */
+ protected PropertyChangeSupport pcs;
+
+ public WizardModel(Class<E> stepClass, E... steps) {
+ this.stepClass = stepClass;
+ this.pcs = new PropertyChangeSupport(this);
+ this.steps = new java.util.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 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 + " is not in universe of steps (" + steps + ")");
+ }
+ setStep(e);
+ }
+
+ 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() {
+ 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;
+ }
+
+ /**
+ * Change l'univers des etapes.
+ *
+ * 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 = java.util.Collections.unmodifiableList(java.util.Arrays.asList(steps));
+ firePropertyChange(STEPS_PROPERTY_NAME, oldValue, this.steps);
+ // la propriete nextStep peut avoir changee
+ firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep());
+ }
+
+ 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() {
+ for (PropertyChangeListener l : pcs.getPropertyChangeListeners()) {
+ pcs.removePropertyChangeListener(l);
+ }
+ }
+ protected 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 validate() {
+ if (step == null) {
+ // pas de validation quand aucune etape n'est sélectionnée
+ return;
+ }
+ boolean validate = validate(step);
+ this.validStep = validate;
+ // toujours forcer la propagation
+ firePropertyChange(VALID_STEP_PROPERTY_NAME, null, validStep);
+ }
+
+ protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+ pcs.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
+ protected void updateUniverse() {
+
+ }
+}
Property changes on: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java
___________________________________________________________________
Name: svn:mergeinfo
+
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,96 @@
+package jaxx.runtime.swing.wizard;
+
+import java.util.EnumMap;
+import java.util.EnumSet;
+
+/**
+ * Un modèle de wizard.
+ *
+ * @param <E> le type de l'énumération contenant les etapes.
+ *
+ * @param <O> le type de l'énumeration des opérations
+ * @param <R> le type de l'énumération des résultats d'opération
+ * @author tony
+ * @since 1.3
+ */
+public abstract class WizardModelWithOperations<E extends Enum<E>, O extends Enum<O>, R extends Enum<R>> extends WizardModel<E> {
+
+ public static final String OPERATIONS_PROPERTY_NAME = "operations";
+ public static final String OPERATION_RESULT_PROPERTY_NAME = "operationResult";
+ /**
+ * La liste des opérations à effectuer
+ */
+ protected EnumSet<O> operations;
+ /**
+ * Pour conserver les résultats des opérations
+ */
+ protected EnumMap<O, R> operationResults;
+ protected Class<O> operationClass;
+ protected Class<R> operationResultClass;
+
+ public abstract void cancel();
+
+ //protected abstract boolean isCancelResult(R operationResult);
+ //protected abstract boolean isErrorResult(R operationResult);
+
+ public WizardModelWithOperations(Class<E> stepClass, Class<O> operationClass, Class<R> operationResultClass, E... steps) {
+ super(stepClass, steps);
+ this.operationClass = operationClass;
+ this.operationResultClass = operationResultClass;
+ operationResults = new EnumMap<O, R>(operationClass);
+ }
+
+ public EnumSet<O> getOperations() {
+ if (operations == null) {
+ operations = EnumSet.noneOf(operationClass);
+ }
+ return operations;
+ }
+
+ public R getOperationResult(O operation) {
+ return operationResults.get(operation);
+ }
+
+ public void setOperationResult(O operation, R operationResult) {
+ R oldValue = getOperationResult(operation);
+ operationResults.put(operation, operationResult);
+ firePropertyChange(OPERATION_RESULT_PROPERTY_NAME, oldValue, operationResult);
+ }
+
+ @Override
+ public void start() {
+ super.start();
+ firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ }
+
+ public WizardModelWithOperations<E, O, R> addOperation(O operation) {
+ getOperations().add(operation);
+ /*if (operation == SynchroOperation.EXPORT_DATA) {
+ // pour exporter les données utilisateurs
+ // les operations synchronisation de référentiel et validation
+ // sont necessaires
+ getOperations().add(SynchroOperation.SYNCHRONIZE_REFERENTIEL);
+ getOperations().add(SynchroOperation.VALIDATION);
+ }*/
+ // on force la propagation de la nouvelle liste
+ firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+
+ updateUniverse();
+ validate();
+ return this;
+ }
+
+ public void removeOperation(O operation) {
+ getOperations().remove(operation);
+ /*if (operation == SynchroOperation.SYNCHRONIZE_REFERENTIEL || operation == SynchroOperation.VALIDATION) {
+ // pour exporter les données utilisateurs
+ // les operations synchronisation de référentiel et validation
+ // sont necessaires
+ getOperations().remove(SynchroOperation.EXPORT_DATA);
+ }*/
+ // on force la propagation de la nouvelle liste
+ firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
+ updateUniverse();
+ validate();
+ }
+}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,20 @@
+package jaxx.runtime.swing.wizard;
+
+/**
+ *
+ * @param <Action>
+ * @author tony
+ * @since 1.3
+ */
+public interface WizardOperation<Action extends WizardAbstractOperationAction> {
+
+ String name();
+
+ int ordinal();
+
+ String getLabel();
+
+ String getDescription();
+
+ public Action newAction();
+}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,26 @@
+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 tony
+ * @since 1.3
+ */
+public interface WizardUI<E extends Enum<E>, M extends WizardModel<E>> {
+
+ public E getSelectedStep();
+
+ M getModel();
+
+ void init();
+
+ void start();
+
+ JTabbedPane getTabs();
+}
Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java (rev 0)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-13 22:00:34 UTC (rev 1265)
@@ -0,0 +1,93 @@
+package jaxx.runtime.swing.wizard;
+
+import javax.swing.JFrame;
+import jaxx.runtime.JAXXContext;
+import jaxx.runtime.JAXXInitialContext;
+import jaxx.runtime.JAXXObject;
+import org.apache.commons.beanutils.ConstructorUtils;
+
+/**
+ *
+ * Une classe pour lancer une ui avec wizard.
+ *
+ * @param <E> le type des etapes
+ * @param <M> le type de modele
+ * @param <UI> le type d'ui
+ * @author tony
+ * @since 1.3
+ */
+public abstract class WizardUILancher<E extends Enum<E>, M extends WizardModel<E>, UI extends WizardUI<E, M>> {
+
+ protected UI ui;
+
+ protected abstract void doAction(UI ui);
+
+ @SuppressWarnings("unchecked")
+ public WizardUILancher(JAXXContext context, JFrame mainUI, Class<UI> uiClass, Class<M> modelClass) {
+ super();
+ try {
+ JAXXInitialContext uiContext = new JAXXInitialContext();
+ // instanciate ui
+ // parent context
+ uiContext.add(mainUI == null ? context : mainUI);
+ // parent context
+ // model
+ uiContext.add(modelClass.newInstance());
+ // apply action
+ uiContext.add("apply", new Runnable() {
+
+ @Override
+ public void run() {
+ doAction(ui);
+ }
+ });
+ // cancel action
+ uiContext.add("cancel", new Runnable() {
+
+ @Override
+ public void run() {
+ doCancel(ui);
+ }
+ });
+
+ // instanciate ui
+ ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext});
+
+ } catch (Exception ex) {
+ throw new RuntimeException("could not instanciate launcher for reason " + ex.getMessage(), ex);
+ }
+ }
+
+ public void start() {
+ init(ui);
+ //ui.start();
+ }
+
+ protected void init(UI ui) {
+ }
+
+ protected void afterInit(UI ui) {
+ }
+
+ protected void doCancel(UI ui) {
+ }
+
+ 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);
+ }
+
+ public void dispose() {
+ ui = null;
+ }
+}
Modified: jaxx/trunk/pom.xml
===================================================================
--- jaxx/trunk/pom.xml 2009-03-12 09:03:21 UTC (rev 1264)
+++ jaxx/trunk/pom.xml 2009-03-13 22:00:34 UTC (rev 1265)
@@ -148,7 +148,7 @@
<!-- libs version -->
<lutinutil.version>1.0.3</lutinutil.version>
<jaxx.version>${project.version}</jaxx.version>
- <i18n.version>0.9</i18n.version>
+ <i18n.version>0.10</i18n.version>
<lutinpluginutil.version>0.3</lutinpluginutil.version>
</properties>
1
0
r1264 - in jaxx/trunk/jaxx-runtime-swing: . src/main/java/jaxx/runtime
by tchemit@users.labs.libre-entreprise.org 12 Mar '09
by tchemit@users.labs.libre-entreprise.org 12 Mar '09
12 Mar '09
Author: tchemit
Date: 2009-03-12 09:03:21 +0000 (Thu, 12 Mar 2009)
New Revision: 1264
Modified:
jaxx/trunk/jaxx-runtime-swing/changelog.txt
jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
Log:
add some usefull code from ObServe (load Nimbus L&F, load ui configuration)
Modified: jaxx/trunk/jaxx-runtime-swing/changelog.txt
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/changelog.txt 2009-03-10 22:57:32 UTC (rev 1263)
+++ jaxx/trunk/jaxx-runtime-swing/changelog.txt 2009-03-12 09:03:21 UTC (rev 1264)
@@ -1,4 +1,5 @@
1.3 ?? 200903??
+ * 20090312 [chemit] - add some usefull code from ObServe (load Nimbus L&F, load ui configuration)
* 20090309 [chemit] - in BlockingLayerUI, add a new state 'block' to enable/disable blocking mode with a blockingColor
* 20090303 [chemit] - in BlockingLayerUI, add a new state 'useIcon' to enable/disable use of the action icon
- add a simple WizardModel
Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java
===================================================================
--- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-10 22:57:32 UTC (rev 1263)
+++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-12 09:03:21 UTC (rev 1264)
@@ -1,11 +1,15 @@
package jaxx.runtime;
+import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
+import java.awt.Rectangle;
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.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
@@ -24,7 +28,11 @@
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Properties;
+import javax.swing.ImageIcon;
import javax.swing.JComponent;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
import jaxx.runtime.swing.I18nTableCellRenderer;
import jaxx.runtime.swing.Item;
import jaxx.runtime.swing.JAXXComboBox;
@@ -46,6 +54,8 @@
static private final Log log = LogFactory.getLog(SwingUtil.class);
private static Field numReaders;
private static Field notifyingListeners;
+ public static final String ICON_PREFIX = "icon.";
+ public static final String COLOR_PREFIX = "color.";
public static void setText(final JTextComponent c, final String text) {
try {
@@ -261,4 +271,90 @@
return result;
}
+
+ /**
+ * Centrer un component graphique au center d'un autre component.
+ *
+ * <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])));
+ }
+ }
+ }
}
1
0
r1263 - jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator
by tchemit@users.labs.libre-entreprise.org 10 Mar '09
by tchemit@users.labs.libre-entreprise.org 10 Mar '09
10 Mar '09
Author: tchemit
Date: 2009-03-10 22:57:32 +0000 (Tue, 10 Mar 2009)
New Revision: 1263
Modified:
jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-validation.xml
Log:
improve CollectionUniqueKeyValidator
Modified: jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-validation.xml
===================================================================
--- jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-validation.xml 2009-03-10 22:57:22 UTC (rev 1262)
+++ jaxx/trunk/jaxx-runtime-validator/src/test/resources/jaxx/runtime/validator/ValidatorBean-validation.xml 2009-03-10 22:57:32 UTC (rev 1263)
@@ -85,6 +85,11 @@
<param name="keys">intValue,stringValue,stringValue2</param>
<message>collectionUniqueKey.four.failed</message>
</field-validator>
+ <field-validator type="collectionUniqueKey">
+ <param name="keys">stringValue</param>
+ <param name="againstProperty">entry</param>
+ <message>collectionUniqueKey.five.failed</message>
+ </field-validator>
</field>
</validators>
\ No newline at end of file
1
0