r1272 - in jaxx/trunk: jaxx-example jaxx-example/src/main/java/jaxx/demo jaxx-example/src/main/resources jaxx-example/src/main/resources/i18n jaxx-example/src/main/resources/jaxx/demo jaxx-runtime-validator jaxx-runtime-validator/src/main/java/jaxx/runtime jaxx-runtime-validator/src/main/java/jaxx/runtime/validator jaxx-runtime-validator/src/main/java/jaxx/runtime/validator/field jaxx-runtime-validator/src/test/java/jaxx/runtime/validator jaxx-runtime-validator/src/test/java/jaxx/runtime/vali
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
participants (1)
-
tchemit@users.labs.libre-entreprise.org